diff --git a/.gitignore b/.gitignore index ca81938..4bb5c7a 100644 --- a/.gitignore +++ b/.gitignore @@ -9,11 +9,34 @@ config.log config.status daemon-init Makefile +tags .deps/ .libs/ + +nbproject/ +.kdev4/ +.settings/ +.cproject +.project +*.kdev4 + *.o *.la *.lo *.gcda *.gcno -/gmon.out +*.gcov +*.a +*.so +cgi/run* +gmon.out +core.[1-9]* +/Documentation +*.pre-indent +*.swp + +html/angularjs/angular-1.3.9 +html/angularjs/ui-utils-0.2.1 +html/bootstrap-3.3.0 +html/d3 +html/index.php diff --git a/Changelog b/Changelog index a58855c..8794e16 100644 --- a/Changelog +++ b/Changelog @@ -1,748 +1,393 @@ -##################### -Nagios 3.x Change Log -##################### +######################## +Nagios Core 4 Change Log +######################## -3.5.1 - 08/30/2013 +4.3.2 - xxxx-xx-xx ------------------ -* Added handler for SIGXFSZ signal (Eric Stanley) -* Fixed bug #444: Nagios 3.5.0 problem with macro $ADMINEMAIL$ : @ is converted to %40 after 2 nagios reload (Duplicate of bug #407) -* Fixed bug #407: Reloading nagios config causes spaces in notifications to become plus signs (Alexey Dvoryanchikov) -* Fixed bug #445: Adding triggered downtime for child hosts causes a SIGSEGV on restart/reload (Eric Stanley) -* Fixed bug #375: Freshness expiration never reached and bug #427: freshness threshold doesn't work if it is set long (Scott Wilkerson, Eric Stanley) -* Fixed bug #432: Downtime scheduled as "Nagios Process" and not the Users name (Sam Lansing, Eric Stanley) +FIXED +* Every 15sec /var/log/messages is flooded with "nagios: set_environment_var" (John Frickson) +* Changed release date to ISO format (yyyy-mm-dd) (John Frickson) +* `make all` fails if unzip is not installed (John Frickson) +* Quick Search no longer allows search by Alias (John Frickson) +* flexible downtime on a service immediately turns off notifications (John Frickson) +* Fix to allow url_encode to be called twice (Z. Liu) +* Update timeperiods.cfg.in (spelling) (Parth Laxmikant Kolekar) +* Spelling fixes (Josh Soref) +* Vent command pipe before remove to avoid deadlocks on writing end (Kai Kunstmann) +* CGI utility cgiutil.c does not process relative config file path names properly (John Frickson) +* xdata/xodtemplate.c bug in option-deprecation code (John Frickson) +* Wildcard searching causes service status links to not work properly (John Frickson) +* Quick search with no hits shows a permission denied error (John Frickson) +* Setting a service as its own parent is not caught by the sanity checker (-v) and causes a segfault (John Frickson) -3.5.0 - 03/15/2013 ------------------- -* Fixed bug #403: The "configuration" page of the webui doesn't use entity encoding when displaying the "command expansion" item (Eric Stanley, Phil Randal) -* Fixed bug #424: Nagios Core 3.4.4 seg fault (core dump) on restart after removing config for running service (Eric Stanley) -* Updated CGI utility functions to support UTF-8 characters (Eric Stanley) -* Fixed bug where selecting Command Expansion from Configuration CGI page would display commands instead (Eric Stanley) -* Fixed bug #369: status.cgi crashes with segfault when there are german ulauts (äöüß) in the hostname or the servicename (Eric Stanley) -* Fixed bug #418: Scheduled Downtime Notifications Resent On Nagios Restart/reload (Eric Stanley) -3.4.4 - 01/12/2013 ------------------- -* Reenabled check for newer versions of Nagios Core (Mike Guthrie) -* Fixed bug #408: service checks get duplicated on reload (Eric Stanley) -* Fixed bug #401: segmentation fault on Solaris when parsing unknown timeperiod directives. (Eric Stanley) -* Added NULL pointer checks to CGI code. (Eric Stanley) -* Fixed buffer overflow vulnerability in CGI code. Thanks to Neohapsis (http://archives.neohapsis.com/archives/fulldisclosure/2012-12/0108.html) for finding this. (Eric Stanley) - -3.4.3 - 11/30/2012 ------------------- -* Reverted squeue changes intended for Nagios 4 -* Reapplied all patches from 3.4.2 release -* Applied fix for pagination and sorting on status.cgi #381 (Phil Randal) - -3.4.2 - 11/09/2012 +4.3.1 - 2017-02-23 ------------------ FIXES -* Fixed issue where deleting a downtime could cause Nagios to crash (Eric Stanley) -* Corrected logic so that end times for flexible downtimes are calculated from the downtime start rather than the current time in the case where Nagios is restarted (Eric Stanley) -* Fixed issue introduced by fix for bug #124 where flexible downtimes are not taken into account on Nagios restart. (Scott Wilkerson, Eric Stanley) -* Fixed bug #247: If a service reports no performance data, the perfdata log file has no line indicating the test. (omnikron@free.fr) -* Fixed link for unhandled unreachable host problems on tactical overview page (Rudolf Cejka) -* Fixed bug #345 with wild card searches not paging properly on status.cgi (Phil Randal) -* Fixed bug #343 on status.cgi where Service Group Summary can potentially show wrong totals (Mark Ziesemer) -* Fixed memory leaks on SIGHUP (Carlos Velasco) +* Service hard state generation and host hard or soft down status (John Frickson) +* Comments are duplicated through Nagios reload (John Frickson) +* host hourly value is incorrectly dumped as json boolean (John Frickson) +* Bug - Quick Search no longer allows search by IP (John Frickson) +* Config: status_update_interval can not be set to 1 (John Frickson) +* Check attempts not increasing if nagios is reloaded (John Frickson) +* nagios hangs on reload while sending external command to cmd file (John Frickson) +* Feature Request: return code xxx out of bounds - include message as well (John Frickson) -3.4.1 - 05/11/2012 + +4.3.0 - 2017-02-21 +------------------ +SECURITY FIXES +* Fix for CVE-2016-6209 - The "corewindow" parameter (as in + http://localhost/nagios?corewindow=www.somewhere.com) has been disabled by + default. See the UPGRADING document for how to enable it. (John Frickson) + +FIXES +* Fix early event scheduling (pmalek / John Frickson) +* on-demand host checks triggered by service checks cause attempt number increments (fredericve) +* Service notification not being send when host is in soft down state (John Frickson) +* configure does not error if no perl installed on CentOS 7 (John Frickson) +* failed passive requests leave .ok files in checkresults dir (caronc) +* Services don't show in status.cgi if "noheader" specified (John Frickson) +* Standardized check interval config file names (John Frickson) +* "Event Log" (showlog.cgi) could not open log file (John Frickson) +* "nagios_check_command" has been deprecated since v3.0. Last vestiges removed (John Frickson) + +ENHANCEMENTS +* Added new flag to cgi.cfg: tac_cgi_hard_only to show only HARD states (John Frickson) +* Add broker-event for the end of a timed event (NEBTYPE_TIMEDEVENT_END) (John Frickson) +* There is no Macro to retrieve addresses of hostgroup members (now $HOSTGROUPMEMBERADDRESSES$) (John Frickson) +* Add "Page Tour" videos to several of the core web pages (John Frickson) +* Added a login page, and a `Logoff` links (John Frickson) +* On the status map, the host name will be colored if services are not all OK. (John Frickson) +* Added "Clear flapping state" command on host and services detail pages. (John Frickson) +* User-entered comment now displays below generated comment for downtime (John Frickson) + + +4.2.4 - 2016-12-07 +------------------ +SECURITY FIXES +* Fixed another root privilege escalation (CVE-2016-9566) Thanks for bringing this + to our attention go to Dawid Golunski (http://legalhackers.com). + + +4.2.3 - 2016-11-21 +------------------- +SECURITY FIXES +* Fixed a root privilege escalation (CVE-2016-8641) (John Frickson) + +FIXES +* external command during reload doesn't work (John Frickson) +* Nagios provides no error condition as to why it fails on the verify for serviceescalation (John Frickson) +* No root group in FreeBSD and Apple OS X (John Frickson) +* jsonquery.html doesn't display scheduled_time_ok correctly (John Frickson) +* daemon_dumps_core=1 has no effect on Linux when Nagios started as root (John Frickson) +* Configuration check in hostgroup - misspelled hostname does not error (John Frickson) +* contacts or contact_groups directive with no value should not be allowed (John Frickson) +* Compile 64-bit on SPARC produces LD error (John Frickson) +* HOSTSTATEID returns 0 even if host does not exist (John Frickson) +* Submitting UNREACHABLE passive result for host sets it as DOWN if the host has no parents (John Frickson) +* nagios: job XX (pid=YY): read() returned error 11 (changed from LOG_ERR to LOG_NOTICE) (John Frickson) +* Fix for quick search not showing services if wildcard used (John Frickson) + + +4.2.2 - 2016-10-24 +------------------ +SECURITY FIXES +* There was a fix to vulnerability CVE-2008-4796 in the 4.2.0 release on + August 1, 2016. The fix was apparently incomplete, as there was still a + problem. However, we are now getting all RSS feeds using AJAX calls + instead of the (outdated) MagpieRSS package. Thanks for bringing this to + our attention go to Dawid Golunski (http://legalhackers.com). + +ENHANCEMENTS +* Update status.c to display passive check icon for hosts when passive checks + are enabled and actives disabled (John Frickson) + +FIXES +* Fix permissions for Host Groups reports (status.cgi) (Patrik Halfar) +* Service Parents does not appear to be functioning as intended (lev) +* Availability report mixes up scheduled and unscheduled warning percentages (Helmut Mikulcik) +* Invalid values for saved_stamp in compute_subject_downtime_times() (John Frickson) +* Remove deprecated "framespacing" (John Frickson) +* The nagios tarball contains two identical jquery copies (John Frickson) +* extinfo.cgi does not set content-type (most cgi's don't) (John Frickson) +* Timeperiods are corrupted by external command CHANGE_SVC_CHECK_TIMEPERIOD (xoubih) +* Quick search doesn't show hosts without services (service status detail page) (John Frickson) +* In host/services details view, if exactly 100 entries would not show last one (John Frickson) +* nagios host URL parameter for NEW map doesn`t work - Network Map for All Hosts (John Frickson) +* next_problem_id is improperly initialized (gherteg) +* Passive problems not showing as "unhandled" (John Frickson) +* September reported as Sept instead of Sep (Rostislav Opočenský) +* Notifications are not sent for active alerts after scheduled downtime ends (John Frickson) +* Nagios 4.2.0 not working on Solaris (John Frickson) +* install-exfoliation and install-classicui don't work FreeBSD and Mac OS X (John Frickson) +* Updated makefile to delete some no-longer-needed files (John Frickson) + + +4.2.1 - 2016-09-06 ------------------ FIXES -* Double quotes in check_command definition break functionality (#332, reverts #86) +* Fix undefined variable php error (John Frickson) +* Links on the sidebar menu under 'Problems' are indented too far (John Frickson) +* Using $ARGn$ Macros in perfdata (John Frickson) +* using a wildcard in search returns service status total all zero's (John Frickson) +* read_only does not take priority (deppy) +* Running nagios -v on 4.2.0 takes 90+ seconds (John Frickson) +* Bare "make" invoked in subtarget (mjo) +* Theme images/stylesheets installed with inconsistent permissions (mjo / John Frickson) +* Missing Image for Host and Service State Trends in Availability Report (nichokap / John Frickson) +* Maintain non-persistent comments through reload (John Frickson) +* Servicegroup availability report ignores includesoftstates in service report links (PriceChild) +* error: format not a string literal and no format arguments (Karsten Weiss) +* Synced config.guess and config.sub with GNU (Zakhar Kleyman) -3.4.0 - 05/04/2012 +4.2.0 - 2016-08-01 +------------------ +SECURITY FIXES +* Fixed vulnerability CVE-2008-4796 (John Frickson) +* Fixed vulnerability CVE-2013-4214 (John Frickson) +* web interface vulnerable to Cross-Site Request Forgery attacks (John Frickson) + +ENHANCEMENTS +* Increase socket queue length for listen() +* Added host name to the website page title (leres / John Frickson) +* Added additional icons for NetBSD and SuSE (John Frickson) +* The new Status Map will now use cgi.cfg options (John Frickson) + default_statusmap_layout will default to "6" for the new map +* The new Status Map will now show some valid values in the popup for "Nagios Process" (John Frickson) + +FIXES +* Network outage view without access to all hosts (John Frickson) +* Core workers looping (John Frickson) +* service query returns duplicate host_name and description fields in the returned data (John Frickson) +* HTML output of plug-ins is parsed in wrong way => webgui unusable (John Frickson) +* Command worker fails to handle SIGPIPE +* "View Status" links under "Map" broken in Nagios Core Version 4.1.1 (John Frickson) +* Can't send big buffer - wproc: Core Worker seems to be choked (velripn / John Frickson) +* Too big CPU load on FreeBSD and other systems using poll() interface (cejkar) +* Flexible downtime recorded as unscheduled downtime (John Frickson) +* Service Flexible downtimes produce 1 notification before entering (John Frickson) +* Once you "set flap_detection_enabled 0" it should remove flapping state from the host/services page (John Frickson) +* New map doesn't finish loading if a logo image is not found (John Frickson) +* Extraneous Div end tag in map.html (Scott Wilkerson) +* Issue with "Problems" section (John Frickson) +* Status Map icons and online/offline status dots disappear in IE11 (John Frickson) +* New network map overlays the nagios process with objects (John Frickson) +* Added Default-Start and Default-Stop to the init script (John Frickson) +* Compile / logging issues with BSD 6 +* Related to above, Fixed a lot of incorrectly handled time_t's in *printf's (John Frickson) +* New map not working for RU locale (actually, most locales) (John Frickson) +* Replaced all instances of signal() with sigaction() + blocking (John Frickson) +* UTF-8 characters like german ä are not processed properly by function url_encode (John Frickson) +* nagios worker processes can hog CPU (huxley / John Frickson) +* custom time periods that include special characters were not being handled in reports (John Frickson) +* Fixed init script to wait up to 90 seconds then kill the nagios process (John Frickson) +* No Host Groups results in wrong error message (John Frickson) +* Setup Nagios users to view specific host is not working in the new network map (John Frickson) +* statusjson.cgi fails glibc realloc truncate response output (John Frickson) +* Report Time Period does not work if an @ character is in the timeperiod name (John Frickson) +* State History does not use actual plugin long_output (John Frickson) +* Time period corruption (xoubih) +* Tactical Overview - Disabled Flap Detection Link (John Frickson) + +4.1.1 - 08/19/2015 +------------------ +FIXES +* CGI Could not read object configuration data (broken by error in 4.1.0) +* exclude (!) not working (broken by mis-applied fix for 4.1.0) + + +4.1.0 - 08/18/2015 ------------------ ENHANCEMENTS -* Added service_check_timeout_state configuration variable (Bill McGonigle) -* Permanently remove sleep on run_event == FALSE in main loop (Max ) -* Reduce notification load by moving notification viability check into notification list creation (Opsview Team) -* Added code to apply allow_empty_hostgroup_assignment flag to host and service dependencies (Daniel Wittenberg) -* Users can now see hostgroups and servicegroups that contain at least one host or service they are authorized for, instead of having to be authorized for them all (Ethan Galstad) -* RSS feed boxes fallback if an error occurs (Ethan Galstad) -* RSS feeds no longer block main page load (Mike Guthrie) +* Promoted JSON CGIs to released status (Eric Stanley) +* New graphical CGI displays: statusmap, trends, histogram (Eric Stanley) +* Make sticky status for acks and comments configurable enhancement #20 (Trevor McDonald / Scott Wilkerson) +* Add host_down_disable_service_checks directive to nagios.cfg #44 (Trevor McDonald / Scott Wilkerson) +* httpd.conf doesn't support Apache versions > 2.3 (DanielB / John Frickson) FIXES -* Fix $NOTIFICATIONRECIPIENTS$ macro to contain all contacts assigned to host|service, not only notified contacts (Bug #98 Matt Harrington) -* Scheduled Downtime Notifications Resent On Nagios Restart/reload (Bug #124 - ricardo) -* NOTIFICATIONTYPE MACRO never became CUSTOM (Bug #168 - Alexey Dvoryanchikov) -* Plugged minor memory leaks in notification logic +* Fix for not all service dependencies created (John Frickson) +* Fix SIGSEGV with empty custom variable (orbis / John Frickson) +* Fix contact macros in environment variables (dvoryanchikov) +* Fixed host's current attempt goes to 1 after going to hard state (John Frickson) +* Fixed two bugs/problems: Replace use of %zd in base/utils.c & incorrect va_start() in cgi/jsonutils.c (Peter Eriksson) +* Fixed: Let remove_specialized actually remove all workers (Phil Mayers) +* Fixed log file spam caused when using perfdata command directives in nagios.cfg (shashikanthbussa) +* Fixed off-by-one error in bounds check leads to segfault (Phil Mayers) +* Added links for legacy graphical displays (Eric Stanley) +* Update embedded URL's to https versions of Nagios websites (scottwilkerson) +* Fixed doxygen comments to work with latest doxygen 1.8.9.1 #30 (Trevor McDonald) +* Fixed makefile target "html" to PHONY to fix GitHub issue #28 (Trevor McDonald) +* Fixed typo as per GitHub issue #27 (Trevor McDonald) +* Fixed jsonquery.php 404 not found error, and disabled Send Query button until form populates #43 (Scott Wilkerson) +* Fixed linking in Tactical Overview for several of the Host entries in Featured section #48 (Scott Wilkerson) +* Fixed passing limit and sort options to pagination and sort links #42 (Scott Wilkerson) +* Added form field for icon URL and clean-up when it changes in CGI Status Map. (Eric Stanley) +* Added options to cgi.cfg to uncheck sticky and send when acknowledging a problem (Trevor McDonald) +* Low impact changes to automate the generation of RPMs from nagios.spec file. (T.J. Yang) +* Update index.php (Trevor McDonald) +* Fixed escaping of corewindow parameter to account for possible XSS injection (Scott Wilkerson) +* Typo correction (T.J. Yang) +* Make getCoreStatus respect cgi_base_url (Moritz Schlarb) +* Adjusted map layout to work within frames (Eric Stanley) +* Fixed map displays are now the full size of browser window (Eric Stanley) +* Fixed labels and icons on circular markup no longer scale on zoom (Eric Stanley) +* Got all maps except circular markup working with icons (Eric Stanley) +* Fixes to make legacy CGIs work again. (Eric Stanley) +* Fixes to make all/html target tolerant of being run multiple times (Eric Stanley) +* For user-supplied maps, converted node group to have transform (Eric Stanley) +* Fixed issue transitioning from circular markup map to other maps (Eric Stanley) +* Fix displayForm to trigger on the button press (Scott Wilkerson) +* Fix fo getBBox crash on Firefox (Eric Stanley) +* Fixed map now resets zoom when form apply()'d (Eric Stanley) +* Fixed so close box on dialogs actually closes dialog (Eric Stanley) +* Corrected directive in trends display (Eric Stanley) +* Fixed minor issue with link in trends links (Eric Stanley) +* Fixed issue with map displaying on Firefox (Eric Stanley) +* Added exclusions for ctags generation (Eric Stanley) +* Update map-popup.html (Scott Wilkerson) +* Initial commit of new graphical CGIs (Eric Stanley) +* Fixed Github bug #18 - archivejson.cgi returns wrong host for state change query (Eric Stanley) +* Status JSON: Added next_check to service details (Eric Stanley) +* Fixed escaping of keys for scalar values in JSON CGIs (Eric Stanley) +* build: Include if it exists. (Eric J. Mislivec) +* lib-tests: test-io{cache|broker} need -lsocket to link. (Eric J. Mislivec) +* lib-tests: test-runcmd assumes GNU echo. (Eric J. Mislivec) +* lib-tests: Signal handlers don't return int on most platforms, and using a cast was the wrong way to resolve this. (Eric J. Mislivec) +* Fix some type/format mismatch warnings for pid_t. (Eric J. Mislivec) +* Fix build on Solaris. (Eric J. Mislivec) +* runcmd: Fix build when we don't HAVE_SETENV. (Eric J. Mislivec) +* Fixed checkresult output processing (Eric Mislivec) +* Corrected escaping of long output macros (Eric Mislivec) +* Fixed null pointer dereferences in archive JSON (Eric Stanley) +* Fixed memory overwrite issue in JSON string escaping (Eric Stanley) +* JSON CGI: Now escaping object and array keys (Eric Stanley) +KNOWN ISSUES +* New map does not account for multiple parents, leaving "legacy" map as an option in the menu -3.3.1 - 07/25/2011 +4.0.8 - 08/12/2014 ------------------ ENHANCEMENTS -* Added support for same host service dependencies with servicegroups (Mathieu Gagné) -* Empty hostgroups referenced from services now optionally generate a warning instead of an error. -* Documentation links now point to online resources -* Matt Wall's Exfoliation theme is now installed by default. You can reinstall the classic theme with "make install-classicui" -* Downtime delete commands made "distributable" by deleting by host group name, host name or start time/comment (Opsview team) -* Allow status.cgi to order by "host urgency" (Jochen Bern) -* Added news items and quick links to main splash page -* Added ability to authenticate to CGIs using contactgroup name (Stephen Gran) +* Removed 8 kB string size limitation in JSON CGIs (Eric Stanley) +* Re-implemented auto-rescheduling of checks (Eric Mislivec) +* Avoid bunching of checks delayed due to timeperiod constraints (Eric Stanley) +* Limit the number of autocalculated core workers to not spawn too many on large systems (Eric Mislivec, Janice Singh) FIXES -* Fixes status.cgi when called with no parameters, where host should be set to all if none specified (Michael Friedrich) -* Fixes possible validation error with empty hostgroups/servicegroups (Sven-Göran Bergh) -* Performance-data handling and checking is now thread-safe so long as embedded perl is not used. -* Children should no longer hang on mutex locks held in parent for localtime() (and similar) calls. -* Debug logging is now properly serialized, using soft-locking with a timeout of 150 milliseconds to avoid multiple threads competing for the privilege to write debug info. -* Fixed extraneous alerts for services when host is down -* Fixed incorrect parsing of multi-line host check results (Jochen Bern) -* Fixed bug with passive host checks being incorrectly sent to event brokers as active checks -* Fixed bug where passive host check status updates were not being propagated to event brokers -* Reverted 'Fix for retaining host display name and alias, as well as service display name' as configuration information stored incorrectly over a reload -* Fixed compile warnings for size_t (Michael Friedrich) -* Fixed problem where acknowledgements were getting reset when a hard state change occurred -* Removed duplicated unlinks for check result files with multiple results -* Fixed race condition on flexible downtime commands when duration not set or zero (Michael Friedrich) -* Fixed flexible downtime on service hard state change doesn't get triggered/activated (Michael Friedrich) -* Fixed XSS vulnerability in config.cgi and statusmap.cgi (Stefan Schurtz) -* Fixed segfault when sending host notifications (Michael Friedrich) -* Fixed bug where unauthorized contacts could issue hostgroup and servicegroup commands (Sven Nierlein) +* Removed quotes from numeric duration values in JSON CGIs (Eric Stanley) +* Fixed escaping in JSON CGIs so all required characters are escaped, and in the correct order (Eric Stanley) +* Fixed segfault in archive JSON CGI when plugin output was empty (Eric Stanley) +* Fixed several possibilities for buffer overflow (Eric Mislivec, Dirkjan Bussink) +* Fixed Tracker #582, #626: Handle VAR=VAL assignments at the start of simple commands (Eric Mislivec, Phil Randal) +* Fixed Tracker #630: Recognize '<' and '>' as redirection operators (Eric Mislivec) +* Corrected worker communication protocol documentation (Phil Mayers) +* Fixed init script to leave config test log in a better location, let sysconfig override init script variables, and not remove nagios.cmd when attempting to start with another instance running (Eric Mislivec, Robin Kearney) +* Fixed Tracker #361: Downtime notifications not displayed properly (Andrew Widdersheim) -WARNINGS - - -3.2.3 - 10/03/2010 +4.0.7 - 06/03/2014 ------------------ ENHANCEMENTS +* Added value of custom variables to Object JSON output for hosts, services and contacts (Eric Stanley) FIXES -* Fixes problem where disabling all active hosts/services was not taking effect -* Fixes for compiler warnings (code cleanup by Stephen Gran) -* Fixes for format errors in event handler logging (Guillaume Rousse) -* Fixed incorrect info in sample nagios.cfg file for state_retention_file (Michael Friedrich) -* Fixed broker_event_handler() to return ERR if data is NULL (Michael Friedrich) +* Fixed bug #616: Unescape plugin output read from checkresult files, fix multiline perf data concatenation, and avoid extra memory allocation and copies. (Eric Mislivec) +* Fixed bug #609: Image on home page doesn't have correct image path prefix. (Derek Brewer) +* Fixed bug #608: Extra newline in service check timeout output string. (Mauno Pihelgas) +* Fixed bug #596: Crashes checking contact authorization for host escalations. (Alexey Dvoryanchikov - duplicates #590, #586) +* Fixed bug #496: Syntax error in exfoliation's common.css. (Karsten Weiss) -WARNINGS - - -3.2.2 - 09/01/2010 +4.0.6 - 04/29/2014 ------------------ ENHANCEMENTS -* Patch to new_mini_epn to allow any command line length without breaking on extra trailing or leading whitespace (Ray Bengen) -* Patch to mini_epn to allow any command line length (Thomas Guyot-Sionnest) -* Patch to speed up loading of state retention data (Matthieu Kermagoret) -* Custom notifications are now suppressed during scheduled downtime (Sven Nierlein) -* Added code to warn user about exit code of 126 meaning plugin is not executable (bug #153) -* Scheduled downtime can now start on SOFT error states (bug #47) -* Main window frame URL can now be specify with a "corewindow=" parameter -* Improved config CGI shows commands, command args in an easier to use manner (Jochen Bern) -* Added ability for NEB modules to override execution of event handlers (Sven Nierlein) -* Custom macros are no longer cleaned/stripped as they are user-defined and should be trusted (Peter Morch) +* Added name of authenticated user to JSON CGI results object (Eric Stanley) +* Added Nagios Core version to the Status JSON CGI programstatus query (Eric Stanley) +* Added daemon status to main page (Eric Mislivec) FIXES -* Fix for choosing next valid time on day of DST change when clocks go one hour backwards -* Fix for nagios now erroring when "Error: Could not find any contactgroup matching..." displayed -* Fix tap tests for Solaris 10 and newer versions of Test::Harness -* Fix for notifications not being sent out when scheduled downtime is cancelled (Daniel Pouzzner) -* Fix for first notification delay being calculated incorrectly, and notifications potentially going out early (Pawel Malachowski) -* Fix for text of scheduling downtime of all services on a host (Holger Weiss) -* Fix for services inheriting notification period from hosts if not defined (Gordon Messmer) -* Fix for incorrect service states on host failures (bug #130 Petya Kohts) -* Fix for incorrect service state attributes being set on host failures (bug #128 Petya Kohts) -* Fix for non-scheduled hosts and services not being updated in NDOUtils -* Fix for typos in TAC, CMD CGIs (bugs #150, #144, #148) -* Fix for types in documentation (bugs #145, #105, #106) -* Fix for incorrect host state counts in status CGI when viewing servicegroups (bug #72) -* Fix for new Splunk integration query parameters (bug #136) -* Fix for extra field header in availability CSV export (bug #113) -* Fix for macro processing code modifying input string (Jochen Bern) -* Fix for update check API -* Fix for CGI speedup when persistent=0 for comments -* Fix for event execution loop re-scheduling host checks instead of executing them if service checks are disabled (bug #152) -* Fix for segfaults on Solaris (Torsten Huebler) -* Fix for incorrect comment expiration times being passed to event broker (Mattieu Kermagot) -* Doc updates related to cleaning of custom macros (Peter Valdemar Morch) -* Fix to sample notify-service-by-email command (bug #62) -* Fix for retaining host display name and alias, as well as service display name (Folkert van Heusden) +* Fixed bug #600: Service Check Timeout State always returns OK (0) status (Mauno Pihelgas, Eric Stanley) +* Fixed bug #583: Status Check Output of (No output on stdout) stderr: (Eric +Stanley - duplicate of bug #573) +* Fixed bug #573: Service checks returns (No output on stdout) stderr (Eric Stanley) +* Fixed bug #438: Reloads during downtime causes wrong availability calculations (Eric Stanley) +* Fixed feed updates when daemon can not access external networks (Eric Mislivec) +* Archive JSON: Fixed bugs calculating availability (Eric Stanley) +* Archive JSON: Allow missing logs to be skipped (Eric Stanley) +4.0.5 - 04/11/2014 +------------------ +* Fixed bug #595: Nagios 4 security fix (Alexey Dvoryanchikov, Eric Stanley) +* Fixed bug #594: Nagios 4 fix contactgroups parsing (Alexey Dvoryanchikov, Eric Stanley) +* Fixed bug #577: Nagios 4 checks stalled when write to socket failed (Alexey Dvoryanchikov) +* Fixed bug #580: Nagios 4 memory leak (Eric Stanley) +* Fixed init script to remove the switching of users when performing configuration verification which was causing failures if nagios user was set to nologin (Scott Wilkerson) +* Fixed auto creation of RAMDISK via environment variables in init script to properly check existence using $RAMDISK_DIR environment variable. (Scott Wilkerson) +* Fixed unreferenced variable NagiosVarDir in daemon-init (Eric Mislivec) +* Fixed bug where audio alerts wouldn't work with a 0 height and width - https://support.nagios.com/forum/viewtopic.php?t=26387 (Scott Wilkerson) - -3.2.1 - 03/09/2010 +4.0.4 - 03/14/2014 ------------------ ENHANCEMENTS -* Link to allow scheduling downtime for all services on a host (Hendrik Baecker) -* Speedup to CGIs when lots of comments or downtimes in status.dat file (Jonathan Kamens) -* Patch for new_mini_epn to allow for any command line length without breaking extra trailing or leading whitespace (Ray Bengen) +* JSON CGIs moved to beta status (Eric Stanley) FIXES -* Fix for incorrect scheduling when time has gone back an hour (partial fix for 24x7) -* Fix for compile on Fedora Core 3 (bug #0000082) -* Fix for compile on Solaris -* Fix for logging test, which was not timezone aware (bug #0000077 - Allan Clark) -* Trivial cleanups for autoconf (Allan Clark) -* Fix for CSS validation of padding: X -* Fix for documentation re: case-insensitive nature of custom variables (Marc Powell) -* Fix for template configurations which use negated wildcards (Tim Wilde) - -WARNINGS -* N/A +* Fixed bug #491,#553: Rebuilt the daemon-init scripts back to something that should work on all systems (Scott Wilkerson) - -3.2.0 - 08/12/2009 +4.0.3 - 02/28/2014 ------------------ -* Fix for read-only permissions bug in CGIs that caused problems viewing comments (bug #0000029) -* Fix for incorrect CGI reports (availability, trends, etc.) when reporting period spans Daylight Savings Time (bug #0000046) -* Fix for detection of truecolor support in GD library (Lars Hecking) -* Reverted to use --datadir configure script option instead of the more recently introduced --datarootdir option -* Status and retention files are now flushed/synced to disk to prevent incomplete information being displayed in CGIs -* Fix for incorrect next service check time calculation when Nagios is reloaded with different timeperiod ranges -* Updated Fedora quickstart guide to indicate PHP requirements -* Known issue: Service checks that are defined with timeperiods that contain "exclude" directives are incorrectly re-scheduled. Don't use these for now - we'll get this fixed for 3.4 +ENHANCEMENTS +* Aliased hourly_value to importance and minimum_value to minimum_importance and deprecated the former (Eric Stanley) +* Added host and service importance macros (Eric Stanley) +* Added notifications on flexible downtime expiration (Dan Wittenberg) +FIXES +* Bug #548: Temporary fix that rejects all external command during restart to prevent Core from crashing (Eric Stanley) +* Corrected calculation of host importance and importance defaults (Eric Stanley) +* Fixed bug #498: Nagios 4 enable_environment_macros=1 not working (Eric Stanley, Alexey Dvoryanchikov) +* No longer checks whether logs can be written when verifying configuration (Eric Stanley) +* Fixed CGI bug where the CGI could read past the end of the list of CGI variables, potentially crashing the CGI (Scott Wilkerson) +* Fixed inheritance of hourly_value from host and service templates (Scott Wilkerson) +* Fixed bug #502: 4.0.0: Configuration -> Service Escalations = incomplete list (Eric Stanley) +* Fixed bug #523: quotes and double quotes in plugin message are converted to HTML escapes in Nagios 4.0 (duplicate of bug #524) +* Fixed bug #524: URLs returned in plugin check results are not correctly displayed (Eric Stanley) +* Fixed bug where passive service checks would return "Service check timed out after 0.00 seconds" (Scott Wilkerson) - -3.1.2 - 06/23/2009 +4.0.2 - 11/25/2013 ------------------ -* Fix for CPU hogging in service and host check scheduling logic +FIXES +* Fixed bug 528: Nagios 4.0.1: Logrotation: Only current host- and servicestates saved in rotated logfiles (duplicate of 507) +* Fixed bug 507: Nagios 4.0.0 - Problem during log rotate (Stefano Ghelfi) +* Fixed bug 530: RPM spec file sets wrong permissions on plugins directory (duplicate of bug 494) +* Fixed bug 494: nagios.spec fixes (with patch) (Karsten Weiss) +* Fixed bug 515: Segsegv after starting up nagios (duplicate of bug 526) +* Fixed bug 513: Crash while entering downtime for service (duplicate of bug 526) +* Fixed bug 529: Core Worker failed to reap child in 4.0.1 Description +* Fixed bug 514: scheduled downtime not showing in web interface (Eric Stanley) +* Fixed bug 526: sort_downtime() corrupts scheduled_downtime_list causing segfault (Adam James) +* Fixed bug 492: Nagios 4 fails to remove/add checks upon reload (Eric Stanley) +* Fixed Bug 484: Beta4.0.0b4 service checks returning (No output on stdout) (Eric Stanley) +* Fixed Bug 470: statusmap doesn't display info (Cameron Moore) +* Fixed Bug 499: Security issue in daemon-init.in, function check_config (Tómas Edwardsson) - - -3.1.1 - 06/22/2009 +4.0.1 - 10/15/2013 ------------------ -* New "important check command" flag for use in service templates, to aid configuration in distributed environments -* Fix for nagios validation error when no services defined -* Fix for stylesheet link -* Fix for extinfo.cgi error message when cgi.cfg doesn't exist -* Fix for notifications.cgi where Update button on right didn't retain host information when no host= was in query parameters -* Fix for potential bug where a contactgroup with no members could cause parsing errors -* Fix for W3 validation for history.cgi -* Fix for W3 validation for extinfo.cgi -* Fix for nagiostats to return non-zero with failures in MRTG mode -* Added t/ directory for tests. Use make test to run. Requires perl on development server -* Fix for duplicate event_id attributes in status and retention data -* Fix for duplicate unlink() during check processing -* Added missing check period column to host config display (CGI) -* Fix for embedded Perl initialization under FreeBSD -* Fix for incorrect re-initialization of mutext after program restart -* Fix for incorrect weighting in host flap detection logic -* Added libtap to distribution. Use ./configure --enable-libtap to compile -* nagios.log permissions are now kept after log rotation -* Fix for "Max concurrent service checks (X) has been reached" messages - will now push services 5 + random(10) seconds ahead for retry -* Fix for removing old HTML files for web frontend that are now replaced with PHP equivalents (index/main/side.html) -* Fix for incorrect service history link text in CGIs -* Fix for useless code loop in netutils.c -* Fix for potential divide by zero in event scheduling code -* Fix for trailing backslash in plugin output causing memory corruption in CGIs -* Fix for bug that could affect host/service scheduling during clock time skew or changes to timeperod definitions between restarts -* Leading whitespace from continuation lines in configuration files is now stripped out -* Fix for bug where pipe (used by IPC) file descriptors get inherited by child processed (e.g. event handlers) (bug #0000026) -* Fix for failure to daemonize - Nagios now bails (bug #0000011) -* Fix for notifications about flapping starting not processed properly by retention data -* Patch to add transparency to statusmap icons for truecolor images -* Patch to add read-only permissions to extinfo CGI -* Security fix for statuswml.cgi where arbitrary shell injection was possible +ENHANCEMENTS +* Added compiler flags in RPM spec file to reduce compiler noise (Dan Wittenberg) +* Added logging of failure in dlclose() call (Anton Lofgren) +* Added a simple query handler interface, nagios-qh.rb (Dan Wittenberg) +* Multiple code simplifications, additional error handling in downtime code (Andreas Ericsson) +FIXES +* Reverted commit f99a9a7b which set check_interval to 1 if it was configured as zero. +* Corrected order of arguments when logging unknown hosts/services (Scott Wilkerson) +* Downtime initialized before retention data read (Eric Stanley) +* Patches to make RPM build again (Dan Wittenberg) +* Ensure that scheduled_downtime_depth never drops below zero (Andreas Ericsson) - -3.1.0 - 01/25/2009 +4.0.0 - 09/20/2013 ------------------ -* Added automatic update check functionality - runs once a day to check for new Nagios releases -* Splash screen on web UI now indicates whether a new update is available (requires that update checks are enabled) -* Updates to nagiostats utility for faster execution if using external stats file -* Added a bit more verbosity to config verification -* Fixed bug in logging event handlers -* Fix to prevent debug output from being shown when Nagios is compiled with embedded Perl interpreter -* Fix for CPU hogging issues on OpenBSD -* Fix to RPM spec file for sample configuration files -* Fix for bug in time calculation routines that could cause notification, reporting, and check scheduling anomalies -* Fix for scheduling forced service checks from web interface -* Minor mods for frameset base for HTML compliance (more fixes coming soon) -* Fix for bug in handling of hard host and service problem states during restarts that could incorrectly set current check attempt and adversely affect notifications, etc. -* Fix for bug in timeperiod calculation of year/month rollovers and display of fixed calendar dates in web interface - - - -3.0.6 - 12/01/2008 ------------------- -* Fix for CGI submission of external commands (writing newlines and submitting service comments) -* Fix for Apache group membership in RPM spec file -* Fix for improper notification propagation command processing -* Better out-of-disk-space error handling when writing retention and status files -* Disabled adaptive check and eventhandler commands for security reasons -* Fix for reading output from system commands (event handlers, etc) that have timed out -* Added wildcard host matching in CGIs -* Fixes for playing audio alerts in CGIs -* Fix for incorrect host status links in status CGI when viewing hostgroup summary -* Added support for x509 cert authentication in the CGIs - - - -3.0.5 - 11/04/2008 ------------------- -* Security fix for Cross Site Request Forgery (CSRF) bug reported by Tim Starling. -* Sample audio files for CGIs removed from distribution -* Fix for mutliline config file continuation bug -* Minor fix to RPM spec file -* Fix for AIX compiler warnings -* Minor sample config file fix -* Added documentation on CGI security issues - - - -3.0.4 - 10/15/2008 ------------------- -* Fix for properly terminating plugins when parent processes get killed (e.g. using 'killall nagios' with check_timeout plugins running) -* Fix for event broker callback when service notifications are disabled -* Fix for scheduling scheduling servicegroup downtime with 'hosts too' option in CGIs -* Fix for segfault under Solaris with NULL plugin output -* Fixes for bugs in sample event handlers - stop/start active service checks and enable notifications -* Cosmetic fix for logging of notifications -* Fix for high CPU utilization under OS X -* Fix for host/service name encoding in CGIs (trends and availability reports, etc.) - - - -3.0.3 - 06/25/2008 ------------------- -* Typo fix in object config routines -* Segfault fix in history CGI -* Fix for bug in retention of contact notification options -* Fix for bug in calculation of negative (month) days in timeperiod definitions -* Fix for debug logging of notifications -* Fix for encoding host and servicegroup names in trends and availability CGIs -* Fix for checking for abnormal termination of host checks -* Fix for spurious orphaned host check errors with non-scheduled hosts -* Fix for url encoding null string in CGIs (caused status CGI segfault) -* Fix for encoding URLs in macros -* Fix for bug in handling of contact groups in escalation definitions -* Changes to service check event broker logic (DNX patches) -* Minor doc updates - - - -3.0.2 - 05/19/2008 ------------------- -* Minor bug fixes in CGIs to ensure extra host/servicegroup url strings are terminated properly -* Minor bug fix in navigation frame link for unhandled service problems -* Better error logging during fork() errors -* Embedded Perl is now disabled by default -* Fixed bug in parsing host dependencies -* Added note to Makefile about 'make install-webconf' option -* Fixed bug in config CGI where active host check attributes were not displayed properly -* Fixed bug in status CGI where sounds were not played for passive service problems -* Fixed sample script for distributed monitoring -* Updated p1.pl to allow for 4KB lines in Perl plugin output under epn -* Fixed bug in command for disabling contact notifications -* Fix for bugs in host and service orphan check logic -* Fix for 'make install' functionality for contrib directory -* Fix for host problem links in CGI status summary view -* Fix for properly escaping macros containing URLs -* Patches for possible XSS vulnerability in CGIs (CVE-2007-5803) - Florian Weimer & SUSE Linux team - - - -3.0.1 - 04/01/2008 -------------------- -* Fixed bug in trends CGI with user not being authorized for hosts/services -* Fixed bug in status CGI with page layout messing up when sounds enabled - - - -3.0 - 03/13/2008 -------------------- -* Faster program startup times (especially in large installs) with new object lookup code -* Fix for special contact inheritance rules in host and service escalations -* Fix for threading-related bugs that resulted in checks failing under NetBSD -* Configure script fix -* Fix for bug in processing $CONTACTADDRESSx$ macros -* Documentation fixes - - - -3.0rc3 - 02/26/2008 -------------------- -* Fix for passive service check stats bugs in nagiostats -* Nagios no longer warns or errors when encountering host/contact/service groups with empty memberships -* Debugging info fix in notification logic -* Fix for multiline support in config files (again) -* Fix for stripping illegal chars in output, perfdata macros -* Patch to allow non-ASCII characters in notifications, etc. -* Fix for bug in on-demand service macros with blank/null host names -* Fix for cleaning up zombie child processes if large installation tweaks disabled and fork twice option disabled -* Fix for incorrect total checks counts in nagiostats -* Fix for segfault if embedded Perl support compiled in, but disabled by config file option -* Smarter host check logic to reduce (uncached) on-demand host checks during "stable" service problems -* Fix for recursive subgroup membership for host/service/contact groups -* Fix for renaming/moving files on network file systems -* New flap detection startup logic speedups when large installations tweaks enabled -* Speed improvements during startup routines when using precached config -* Speed improvements in reading retention data during startup -* Safer loading mechanism for NEB modules to prevent segfaults in Nagios -* Fix for segfault in CGIs when converting object names with extended ASCII characters to URLs - - - -3.0rc2 - 01/29/2008 -------------------- -* Changed embedded audio MIME types in CGIs to "application/wav" -* Fixed bug in sample helloworld NEB module -* Modified p1.pl to allow for multiline-line output of Perl plugins under embedded Perl interpreter (epn) -* Fix for incorrect environment variables names for custom host and contact macros -* Fix for external command file thread polling code -* Fix for cfg_dir directive not working on Solaris -* Fixed segfault in extinfo CGI when passed an invalid service description/name -* Fixed bug in summary CGI with reports on specific hosts -* Fix for writing check result files under Cygwin -* Fix for not building sample helloworld.o event broker module if event broker is disabled by configure script -* Fix to sample event handler scripts -* Fix for handling plugin output with escaped newlines and backslashes -* Fix for bug in service and host event scheduling logic -* Fix for reversed object sort order when using fast startup options -* Fix for bug with notification commands not being run if notifications were not logged - - - -3.0rc1 - 12/17/2007 -------------------- -* Fixed bug where status log was left after a restart with faulty config -* Fix for compilation bug on systems that don't support setenv() (e.g. Solaris) -* Support for line continuation/breaks in config files - end lines with one backslash (\) to continue on next line -* Fixed bug with not deleting old check result files that contained results for invalid host/service -* Fixed bug with init script option to check Nagios config -* Auto-filled comment/author fields for acknowledging problems through WAP interface -* Fixed bug with processing of CONTACTGROUPNAMES, NOTES, NOTESURL, and ACTIONURL macros -* Doc fix regarding soft state dependencies -* Fix for segfault in event broker module code - - - -3.0b7 - 11/23/2007 ------------------- -* Memory leak fix in macro code -* Added use_timezone option to allow Nagios instances to run in non-native timezones -* Fix for encoding HTML characters in CGIs -* Fix for unimplemented $LASTHOSTSTATE$, $LASTHOSTSTATEID$, $LASTSERVICESTATE$, and $LASTSERVICESTATEID$ macros -* Fixes for memory leaks with passive check, performance data routines -* Makefile fixes -* Code cleanup, fixes for compiler warnings -* Fix to prevent FLAPPINGSTART notifications from incorrectly being resent after program restarts -* Added free_child_process_memory and child_processes_fork_twice options for performance tweaks -* Fix for bug in processing of on-demand service macros - - - -3.0b6 - 10/31/2007 ------------------- -* Logging API revamp, cleanup -* Misc internal performance improvements -* Bug fix with attempting to access an uninitalized mutex if external commands are disabled -* Updates to .cvsignore files -* Fix for embedded Perl interpreter to recache scripts when they're modified -* Fix for cancelling inheritance with 'null' in various object directives -* Additional functionality of additive inheritance feature -* Fixed bug where missing host/servicegroups in object definitions didn't always generate errors -* Increased max plugin output length cap from 4kb to 8kb -* Caching of Perl scripts now enabled by default if embedded Perl interpreter is compiled in -* Fix for segfault when contact definitions had no notification timeperiods defined -* Retention of host/service check scheduling options -* Fix for race condition when freshening host and service check results -* Added null -b option to install-sh for Solaris so install scripts don't break -* Added .gitignore files for git users -* Added new external commands to change notification period for host, services, and contact on-the-fly -* Added new external commands to change modified object attributes (affecting data retention logic) -* Added $ISVALIDTIME:$ and $NEXTVALIDTIME:$ on-demand macros -* Added enable_environment_macros option to determine whether or not macros are set as environment vars -* Major overhaul (read: complete rewrite) of macro code, so macros are now only computed when found -* Summary macros are now available as regular (non-environment) macros if requested when large installation tweaks are enabled -* Bug fix for scheduling hostgroup host downtime through web interface -* Better error logging when failing to rename/move files -* Added $LASTHOSTSTATE$, $LASTHOSTSTATEID$, $LASTSERVICESTATE$, and $LASTSERVICESTATEID$ macros -* Addition of object pointers to event broker module data structures (may require event broker module rebuilds) -* Spec file changes to better support RPM builds on 64-bit systems -* Possible fix for Unicode html encoding errors in CGIs - - - -3.0b5 - 10/08/2007 ------------------- -* Minor bug fix in CSS files -* Bug fix in sample config files -* Fix for recovery notifications not being sent out when first_notification_delay option used in host/service definitions -* Fix for ochp commands not running properly -* Special additive inheritance rule: escalation contact(group)(s) that begin with '+' will now inherit from associated host/service definition if not inheriting from another escalation template -* Status file is no longer deleted during restarts due to a SIGHUP or external command -* Improvement in service flap detection logic -* Added additional_freshness_latency config file directive -* Improvements in freshness check logic -* Temporarily removed $SERVICEGROUPMEMBERS$ macro, as it was causing crashes for some users (this need further investigation) -* Added $EVENTSTARTTIME$ macro to indicate time Nagios started processing events (checks, etc.) -* Added use_pending_states option to CGI config file to determine displayed state of hosts/services that have not been checked -* Workaround to prevent browsers from incorrectly using cached statusmap image on page refresh -* Fix for incorrect latency calculations for passive host/service checks -* Added passive check latency stats to nagiostats -* Added support for relative paths in config_file and config_dir directives -* Fix for compile error under Solaris - - - -3.0b4 - 09/27/2007 ------------------- -* New macros: $HOSTGROUPMEMBERS$, $HOSTGROUPNOTES$, $HOSTGROUPNOTESURL$, $HOSTGROUPACTIONURL$, $SERVICEGROUPMEMBERS$, $SERVICEGROUPNOTES$, $SERVICEGROUPNOTESURL$, $SERVICEGROUPACTIONURL$, $CONTACTGROUPALIAS$, $CONTACTGROUPMEMBERS$, $NOTIFICATIONRECIPIENTS$, $NOTIFICATIONAUTHOR$, $NOTIFICATIONAUTHORNAME$, $NOTIFICATIONAUTHORALIAS$, $NOTIFICATIONCOMMENT$ -* Removed host/service downtime author/comment macros introduced in 3.0b2 in favor of more generic $NOTIFICATION...$ macros -* Fix for segfault when cancelling active scheduled host downtime -* Macro code cleanup -* Added on-demand contact and contactgroup macro support -* More complete (but still partial) support for macros in CGIs ($xNOTES$, $xNOTESURL$, and $xACTIONURL$ macros) -* Fixed bug in config CGI with displaying incorrect notification interval for escalations -* Added new 'check' option to init script to verify configuration -* Added custom host and service notifications, with option to force the notifications and broadcast them to all contacts -* Fix for on-demand/cached host check statistics -* Fixed bug where null host check command would cause high CPU utilization -* Alias, if not specified, now defaults to object name in host, hostgroup, servicegroup, contact, and contactgroup definitions -* Fixed bug with excluding hosts, services, and contacts with bang (!) in object definitions -* Fixed bug in nagiostats with NULL mrtg data arguments printing bogus string -* Added custom delimiter option in nagiostats output (useful for CSV output) - - - -3.0b3 - 08/30/2007 ------------------- -* Minor bug fix for debug logging of macros -* Version number is now printed in CGI pages -* HTML documentation cleanup (HTML Tidy, link checking, etc.) -* Fixed bug where notifications would not be sent out host/service contact group members - - - -3.0b2 - 08/29/2007 ------------------- -* Fix for some sample config files getting installed with .sample extension -* Improvements to the host check logic performance (more use of cached and parallel checks) -* Minor bug fix with notification timeout error messages -* Fix bug with logging of passive host and service check results -* Fixed bug with warning about no contactgroups being defined -* Internal data structure cleanups -* New macros: $SERVICEISVOLATILE$, $TOTALHOSTSERVICES$, $TOTALHOSTSERVICESOK$, $TOTALHOSTSERVICESWARNING$, $TOTALHOSTSERVICESUNKNOWN$, $TOTALHOSTSERVICESCRITICAL$, $HOSTDOWNTIMEAUTHOR$, $HOSTDOWNTIMEAUTHORNAME$, $HOSTDOWNTIMEAUTHORALIAS$, $HOSTDOWNTIMECOMMENT$, $SERVICEDOWNTIMEAUTHOR$, $SERVICEDOWNTIMEAUTHORNAME$, $SERVICEDOWNTIMEAUTHORALIAS$, $SERVICEDOWNTIMECOMMENT$ -* Added 'lock_author_names' option to CGI config file to prevent alteration of author names - when submitting comments, scheduled downtime, etc. -* Fix for concatentation of multiline plugin perfdata -* Added status CGI host/service property filters for hard and soft states - - - -3.0b1 - 07/31/2007 ------------------- -* Fixed bug with processing epn directives in Perl plugins -* Fixed bug with check_result_path config option being ignored -* Added $MAXHOSTATTEMPTS$ and $MAXSERVICEATTEMPTS$ macros -* Fixed bug with incorrect output returned from embedded Perl plugins -* Fixed bug where status data file was not read by CGIs using mmap() -* Fix for CGI segfault -* Program status now updated at least every 5 seconds for addons that watch NDOUtils DB -* Added escape_html_tags option to CGI config file to escape HTML tags in plugin output -* Added optional integration with Splunk into the CGIs -* Added new action and notes URL target frame options to CGI config file -* Added new 'exclude' option to timeperiod definitions for easy on-call rotation definitions - - - -3.0a5 - 06/19/2007 ------------------- -* Fixed problem with multiline long plugin output and Perl plugin output -* Fixed compilation problem with embedded Perl -* More debug/trace log functionality -* Added new 'passive_host_checks_are_soft' config option -* Fixed bug with host notifications occurring during soft host states -* Fixed bug in processing multiple check results contained in a single file -* Expanded timeperiod definitions to allow for day/date exceptions -* Changes to sample config files and installation location -* Changed debug file format to include current pid -* Added 'initial_state' option to host and service definitions to allow for non-UP/OK initial states -* Minor changes to freshness threshold calculation -* Documentation updates - - - -3.0a4 - 05/08/2007 ------------------- -* Fix for segfault fix when low priority event queue's only item is removed -* Added test for writeability of temp directory during configuration test -* Fix for unescaping backslashes in plugin output in the CGIs -* Removed check_result_buffer_slots option from main configuration file -* New IPC method for passing host/service check results back to main daemon -* Added check_result_path option to set path used to store check results -* Added max_check_result_file_age option to control processing of check results in older files -* Added new --with-temp-dir option to configure script -* Removed legacy 2.x host check logic and use_old_host_check_logic option -* Removed DEBUGx options from configure script -* Added new debug/trace log functionaltiy (only partially complete) -* Fixed compilation error under OSX -* Fix for SIGTERMs being seen as SIGEXITs, non-logging of SIGTERMs/shutdowns - - - -3.0a3 - 04/10/2007 ------------------- -* Configure script fix for no mail program found/installed on system -* Fix for compilation warnings about implicit declaration of round() - may (strangely enough) also - fix segfaults that were occuring on some systems -* Added detection of Apache conf.d directory and 'make install-webconf' functionality -* Configure script option bug fixes for cygwin and embedded perl -* Added buffer stats and check statistics to performance information in extinfo CGI -* Hostgroup and servicegroup definitions now have notes, notes_url, and action_url directives -* Patch for incorrect time down percentage in availability CGI -* Command definitions and host/service plugin perfdata with HTML should now be escaped in CGIs -* Updated init script to fix a race condition during restarts -* Documentation updates - - - -3.0a2 - 03/27/2007 ------------------- -* Added warning about aggregate_status_updates directive being deprecated. -* Added new "p" option to host/service_perfdata_file_mode directives for pipes. -* Fix for incorrect performance data file write/append mode options -* Regular expression matching in object config files now also triggered by '+' and '\.' -* Added support for extended regular expression matching in object config files -* Fix for incorrect processing of y_2d coordinates for host objects in statusmap layout -* Fix for current status of hosts with no check command defined -* SIGSEGV signals should now be logged again (broken in 3.0a1) -* Added warning for invalid temp_path directory -* Documentation bug fixes and updates - - - -3.0a1 - 03/06/2007 ------------------- -Here are all the changes since Nagios 2.x: - -* Adaptive monitoring: - - Check timeperiod can now be modified on-the-fly - -* Notification changes: - - Added first_notification_delay to host and object definitions to delay first notification - - Notifications are now sent out when flap detection is disabled on a host/service-specific - or program-wide basis ($NOTIFICATIONTYPE$ macro = "FLAPPINGDISABLED") - - Notifications can now be sent out when scheduled downtime starts, ends, and is cancelled. The - $NOTIFICATIONTYPE$ macro will be set to "DOWNTIMESTART", "DOWNTIMEEND", or "DOWNTIMECANCELLED", - respectively. In order to receive downtime notifications, specify 's' or 'downtime' in contact, host, - and/or service notification options. - -* Object changes: - - Added ability to use multiple template names (separated by commas) in object definitions - - Added ability to null out optional character directives in object definitions (using 'null' without quotes) - - Added hostg/service/contactgroup_members directives to host/service/contactgroup definitions, - respectively, for allowing including host, service, or contact members from "sub" groups. - - Added support for custom variables in host, service, and contact definitions - - Added host_notifications_enabled, service_notifications_enabled, can_submit_commands to contact definitions - - Added optional display_name directive to host and service definitions - - Removed serviceextinfo definitions and merged variables with service definitions - - Removed hostextinfo definitions and merged variables with host definitions - - Services inherit contactgroups, notification interval, and notification period from associated host if not specified - - Service escalations inherit contactgroups, notification interval, and escalation period from associated service if not specified - - Host escalations inherit contactgroups, notification interval, and escalation period from associated host if not specified - - Host, service, host escalation, and service escalation definitions now support a 'contacts' directive, along with 'contact_groups' - - Service dependencies with blank dependent host/hostgroup names will create "same host" dependencies - - -* Performance optimizations: - - Added ability to precache object config files - - Added ability to exclude object relationship and circular path - checks from verification process - -* Check output: - - Multiline output support for host and service checks - -* Macro changes: - - Added $LONGHOSTOUTPUT$ and $LONGSERVICEOUTPUT$ macros - - Added $TEMPPATH$ macro - - Removed $COMMENTDATAFILE$ and $DOWNTIMEDATAFILE$ macros - - Added $HOSTDISPLAYNAME$ and $SERVICEDISPLAYNAME$ macros - - Custom host/service/contact macros accessible via $_HOST$, $_SERVICE, or $_CONTACT$. - On-demand host/service macros for custom vars are working. Custom vars are also set as environment vars. - - On-demand service macros can contain and empty host name field. In this case, the name of the current host will be used. - - $HOSTNOTES$ and $SERVICENOTES$ macros may now contain macros themselves - -* Flapping changes: - - Added flap_detection_options directive to host and service definitions to control which - states (i.e. OK, WARNING, UNKNOWN, and/or CRITICAL) are used in flap detection logic - - Percent state change and state history are now retained and recorded even when host/service - flap detection is disabled. - - Hosts and services are immediately check for flapping when flap detection is enabled program-wide. - - Hosts/services that are flapping when flap detection is disabled program-wide are now logged - -* External command changes: - - Added PROCESS_FILE external command to allow processing of external commands found in - an external (regular) file. Very useful for passive checks with long output or scripting. - - Custom commands can now be submitted to Nagios. Custom command names are prefixed with an underscore - and are not processed internally by the Nagios daemon. They may, however, be processed by NEB modules. - - External commands are now checked by default. Nagios 2.x and earlier did not check for external commands - by default. - -* Status data changes: - - Contact status information is now saved (although it is not processed by the old CGIs) - -* Retention data changes: - - Contact status information is now retained across program restarts - - Comment and downtime IDs are now stored across program restarts, should be unique unless reset - - Added retained_host/service_attribute_mask variables to control what host/service attribs are retained globally - - Added retained_process_host/service_attribute_mask variables to control what process attribs are retained - - Added retained_contact_host/service_attribute_mask variables to control what contact attribs are retained globally - -* Downtime changes: - - Scheduled downtime entries are now stored in the status and retention files - -* Comment changes: - - Comments are now stored in the status and retention files - - Non-persistent acknowledgement comments are now deleted when the acknowledgement is removed (instead of when Nagios restarts) - -* Host check logic changes: - - Most host checks are now run asynchronously, in parallel! - - Scheduled host checks now help improve performance, instead of hinder it (if caching is enabled) - - Added cached_host_check_horizon option for enabling use of cached host check results - - Added enable_predictive_host_dependency_checks for enabling predictive checks of dependent hosts - - Added retry_interval to host definitions - - Added check_for_orphaned_hosts option and support for orphaned host checks - - Passive host check states can now be translated from their original DOWN/UNREACHABLE state if the - new translate_passive_host_results option is enabled - -* Service check logic changes: - - 'parallelize' option in service definitions deprecated/no longer used - - Added cached_service_check_horizon option for enabling use of cached service check results - - Added enable_predictive_service_dependency_checks for enabling predictive checks of dependent services - -* Dependency changes: - - Host and service dependencies can now have a timeperiod during which they're valid (dependency_period directive) - -* Event broker changes: - - Updated NEB API version - - Modified adaptive program status callback - - Added adaptive contact status callback - - Added host/service precheck callbacks to allow modules to cancel/override internal host/service checks - -* Embedded Perl changes: - - Added 'enable_embedded_perl' option to main config file to control whether epn is enabled/disabled - - Added support for perl plugins to specify whether or not they should be run under the epn... The - second to tenth line of a perl plugin may start with '# nagios: +epn' or '# nagios: -epn' to explicity indicate that it - should be run under the epn. - - Added 'use_embedded_perl_implicitly' option to main config file to determine whether or not perl - plugins will use the epn if they don't explicitly allow/disalow it - -* CGI changes: - - Hostgroup and servicegroup summaries now show important/unimportant problem breakdowns like the TAC CGI - - Minor layout changes to host and service detail views in extinfo CGI - -* Misc changes: - - More information given when testing scheduling (-s command line option) - - Removed fixed length restrictions for host names and service descriptions - - Plugin output length restriction bumped up to 4K - - Added temp_path directive to main config file for specifying temp directory - - Multiline output support for system commands via my_system() - - Added global event_id and notification_id vars that are at least unique during a single run of Nagios - - Default is now to check for orphaned services, rather than not - - Renamed service_reaper_frequency to check_result_reaper_frequency - - Fractional notification and check intervals are now supported (e.g. "3.5" minutes) - - Backslash chars are now used to escape command arguments that contain \ or ! characters - - Added 'external_command_buffer_slots' and 'check_result_buffer_slots' variables to specify size of internal buffers - - Added check statistics to status file, available via nagiostats for graphing in MRTG - - Added $HOSTGROUPNAMES$, $SERVICEGROUPNAMES$, $HOSTACKAUTHORNAME$, $HOSTACKAUTHORALIAS$, $SERVICEACKAUTHORNAME$, - and $SERVICEACKAUTHORALIAS$ macros - - - - +See http://nagios.sourceforge.net/docs/nagioscore/4/en/whatsnew.html for a +list of the changes in Nagios Core 4 diff --git a/LEGAL b/LEGAL index 278eeee..7827702 100644 --- a/LEGAL +++ b/LEGAL @@ -1,3 +1,12 @@ +Copyright(c) 1999-2009: + Ethan Galstad +Copyright(c) 2009 until further notice: + Nagios Core Development Team and Nagios Community Contributors + +For detailed authorship information, refer to the source control +management history and pay particular attention to commit messages +and the THANKS file. + All source code, binaries, documentation, information, and other files contained in this distribution are provided AS IS with NO WARRANTY OF diff --git a/Makefile.in b/Makefile.in index 5cc7f81..19aff26 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1,12 +1,12 @@ ############################### # Makefile for Nagios # -# Last Modified: 04-13-2008 ############################### # Source code directories SRC_BASE=@srcdir@/base +SRC_LIB=@srcdir@/lib SRC_CGI=@srcdir@/cgi SRC_HTM=@srcdir@/html SRC_MODULE=@srcdir@/module @@ -15,6 +15,7 @@ SRC_COMMON=@srcdir@/common SRC_XDATA=@srcdir@/xdata SRC_CONTRIB=@srcdir@/contrib SRC_TTAP=@srcdir@/t-tap +SRC_WORKERS=@srcdir@/worker CC=@CC@ CFLAGS=@CFLAGS@ @DEFS@ @@ -28,32 +29,32 @@ CFGDIR=@sysconfdir@ BINDIR=@bindir@ CGIDIR=@sbindir@ LIBEXECDIR=@libexecdir@ +LIBDIR=@libdir@ +INCLUDEDIR=@includedir@/nagios HTMLDIR=@datadir@ +datarootdir=@datarootdir@ +LN_S=@LN_S@ INSTALL=@INSTALL@ INSTALL_OPTS=@INSTALL_OPTS@ COMMAND_OPTS=@COMMAND_OPTS@ HTTPD_CONF=@HTTPD_CONF@ +LN_HTTPD_SITES_ENABLED=@LN_HTTPD_SITES_ENABLED@ INIT_DIR=@init_dir@ -INIT_OPTS=-o root -g root +INIT_OPTS=@INIT_OPTS@ CGICFGDIR=$(CGIDIR) -PERLDIR=@PERLDIR@ USE_EVENTBROKER=@USE_EVENTBROKER@ USE_LIBTAP=@USE_LIBTAP@ -INSTALLPERLSTUFF=@INSTALLPERLSTUFF@ - CGIEXTRAS=@CGIEXTRAS@ -SNPRINTF_O=@SNPRINTF_O@ - CP=@CP@ @SET_MAKE@ none: @echo "Please supply a command line argument (i.e. 'make all'). Other targets are:" - @echo " nagios cgis contrib modules" + @echo " nagios cgis contrib modules workers" @echo " clean" @echo " install install-base install-cgis install-html install-exfoliation install-config install-init install-commandmode fullinstall" # @echo " uninstall" @@ -66,7 +67,7 @@ indent: @sh indent-all.sh ctags: - ctags -R + ctags -R --exclude=html/angularjs --exclude=html/d3 --exclude=t-tap all: cd $(SRC_BASE) && $(MAKE) @@ -75,6 +76,7 @@ all: if [ x$(USE_EVENTBROKER) = xyes ]; then \ cd $(SRC_MODULE) && $(MAKE); \ fi + cd $(SRC_WORKERS) && $(MAKE) $@ @echo "" @echo "*** Compile finished ***" @@ -121,7 +123,7 @@ all: @echo "" @echo " - Look at the sample config files" @echo " - Read the documentation on the Nagios Library at:" - @echo " http://library.nagios.com" + @echo " https://library.nagios.com" @echo "" @echo "before you post a question to one of the mailing lists." @echo "Also make sure to include pertinent information that could" @@ -134,13 +136,16 @@ all: @echo "" @echo "For more information on obtaining support for Nagios, visit:" @echo "" - @echo " http://support.nagios.com" + @echo " https://support.nagios.com" @echo "" @echo "*************************************************************" @echo "" @echo "Enjoy." @echo "" +$(SRC_LIB)/libnagios.a: + cd $(SRC_LIB) && $(MAKE) + nagios: cd $(SRC_BASE) && $(MAKE) @@ -161,7 +166,11 @@ contrib: modules: cd $(SRC_MODULE) && $(MAKE) +workers: + cd $(SRC_WORKERS) && $(MAKE) all + clean: + cd $(SRC_LIB) && $(MAKE) $@ cd $(SRC_BASE) && $(MAKE) $@ cd $(SRC_CGI) && $(MAKE) $@ cd $(SRC_COMMON) && $(MAKE) $@ @@ -171,10 +180,12 @@ clean: cd $(SRC_CONTRIB) && $(MAKE) $@ cd $(SRC_MODULE) && $(MAKE) $@ cd $(SRC_TTAP) && $(MAKE) $@ + cd $(SRC_WORKERS) && $(MAKE) $@ rm -f *.cfg core rm -f *~ *.*~ */*~ */*.*~ */*/*.*~ distclean: clean + cd $(SRC_LIB) && $(MAKE) $@ cd $(SRC_BASE) && $(MAKE) $@ cd $(SRC_CGI) && $(MAKE) $@ cd $(SRC_COMMON) && $(MAKE) $@ @@ -184,6 +195,7 @@ distclean: clean cd $(SRC_CONTRIB) && $(MAKE) $@ cd $(SRC_MODULE) && $(MAKE) $@ cd $(SRC_TTAP) && $(MAKE) $@ + cd $(SRC_WORKERS) && $(MAKE) $@ rm -f sample-config/*.cfg sample-config/*.conf sample-config/template-object/*.cfg rm -f daemon-init pkginfo rm -f Makefile subst @@ -192,7 +204,8 @@ distclean: clean devclean: distclean -test: +test: nagios cgis + cd $(SRC_LIB) && $(MAKE) test $(MAKE) test-perl $(MAKE) test-tap @@ -211,7 +224,7 @@ test-perl: cgis install-html: cd $(SRC_HTM) && $(MAKE) install - make install-exfoliation + $(MAKE) install-exfoliation install-base: cd $(SRC_BASE) && $(MAKE) install @@ -223,24 +236,22 @@ install: cd $(SRC_BASE) && $(MAKE) $@ cd $(SRC_CGI) && $(MAKE) $@ cd $(SRC_HTM) && $(MAKE) $@ - $(MAKE) install-exfoliation + $(MAKE) install-exfoliation $(MAKE) install-basic install-unstripped: cd $(SRC_BASE) && $(MAKE) $@ cd $(SRC_CGI) && $(MAKE) $@ cd $(SRC_HTM) && $(MAKE) $@ - $(MAKE) install-exfoliation + $(MAKE) install-exfoliation $(MAKE) install-basic install-basic: $(INSTALL) -m 775 $(INSTALL_OPTS) -d $(DESTDIR)$(LIBEXECDIR) $(INSTALL) -m 775 $(INSTALL_OPTS) -d $(DESTDIR)$(LOGDIR) $(INSTALL) -m 775 $(INSTALL_OPTS) -d $(DESTDIR)$(LOGDIR)/archives - $(INSTALL) -m 775 $(INSTALL_OPTS) -d $(DESTDIR)$(CHECKRESULTDIR) - if [ $(INSTALLPERLSTUFF) = yes ]; then \ - $(INSTALL) -m 664 $(INSTALL_OPTS) p1.pl $(DESTDIR)$(BINDIR); \ - fi; + $(INSTALL) -m 775 $(COMMAND_OPTS) -d $(DESTDIR)$(CHECKRESULTDIR) + chmod g+s $(DESTDIR)$(CHECKRESULTDIR) @echo "" @echo "*** Main program, CGIs and HTML files installed ***" @@ -285,23 +296,42 @@ install-config: install-webconf: $(INSTALL) -m 644 sample-config/httpd.conf $(DESTDIR)$(HTTPD_CONF)/nagios.conf + if [ $(LN_HTTPD_SITES_ENABLED) -eq 1 ]; then \ + $(LN_S) $(DESTDIR)$(HTTPD_CONF)/nagios.conf $(DESTDIR)/etc/apache2/sites-enabled/nagios.conf; \ + fi @echo "" @echo "*** Nagios/Apache conf file installed ***" @echo "" - + install-exfoliation: - cp -rf contrib/exfoliation/stylesheets/* $(DESTDIR)$(HTMLDIR)/stylesheets - cp -rf contrib/exfoliation/images/* $(DESTDIR)$(HTMLDIR)/images + @cd contrib/exfoliation; \ + $(INSTALL) $(INSTALL_OPTS) -d $(DESTDIR)$(HTMLDIR)/stylesheets; \ + for file in $$(find ./stylesheets/ -type f); do \ + $(INSTALL) -m 644 $(INSTALL_OPTS) $${file} $(DESTDIR)$(HTMLDIR)/$${file}; \ + done; \ + $(INSTALL) $(INSTALL_OPTS) -d $(DESTDIR)$(HTMLDIR)/images; \ + for file in $$(find ./images -type f); do \ + $(INSTALL) -m 644 $(INSTALL_OPTS) $${file} $(DESTDIR)$(HTMLDIR)/$${file}; \ + done; \ + cd ../.. @echo "" @echo "*** Exfoliation theme installed ***" @echo "NOTE: Use 'make install-classicui' to revert to classic Nagios theme"; @echo "" - + install-classicui: - cp -rf html/stylesheets/* $(DESTDIR)$(HTMLDIR)/stylesheets - cp -rf html/images/* $(DESTDIR)$(HTMLDIR)/images + @cd html; \ + $(INSTALL) $(INSTALL_OPTS) -d $(DESTDIR)$(HTMLDIR)/stylesheets; \ + for file in $$(find ./stylesheets/ -type f); do \ + $(INSTALL) -m 644 $(INSTALL_OPTS) $${file} $(DESTDIR)$(HTMLDIR)/$${file}; \ + done; \ + $(INSTALL) $(INSTALL_OPTS) -d $(DESTDIR)$(HTMLDIR)/images; \ + for file in $$(find ./images -type f); do \ + $(INSTALL) -m 644 $(INSTALL_OPTS) $${file} $(DESTDIR)$(HTMLDIR)/$${file}; \ + done; \ + cd .. @echo "" @echo "*** Classic theme installed ***" @@ -328,7 +358,25 @@ install-commandmode: @echo "" -fullinstall: install install-init install-commandmode install-webconf +install-devel: install-headers install-lib + +install-headers: + $(INSTALL) -d -m 755 $(DESTDIR)$(INCLUDEDIR) + $(INSTALL) -d -m 755 $(DESTDIR)$(INCLUDEDIR)/lib + $(INSTALL) -m 644 include/*.h $(DESTDIR)$(INCLUDEDIR) + $(INSTALL) -m 644 lib/*.h $(DESTDIR)$(INCLUDEDIR)/lib + rm -f $(DESTDIR)$(INCLUDEDIR)/config*.h + +install-lib: $(SRC_LIB)/libnagios.a + $(INSTALL) -d -m 755 $(DESTDIR)$(LIBDIR) + $(INSTALL) -m 644 $(SRC_LIB)/libnagios.a $(DESTDIR)$(LIBDIR) + +dox: + @rm -rf Documentation + doxygen doxy.conf + + +fullinstall: install install-init install-commandmode install-webconf install-devel # Uninstall is too destructive if base install directory is /usr, etc. #uninstall: @@ -375,5 +423,11 @@ pkgset: nagios.SPARC.pkg.tar.gz pkgclean: rm -rf pkg Prototype nagios.SPARC.pkg.tar.gz +dist: distclean + rm -f nagios-$(VERSION) + ln -s . nagios-$(VERSION) + tar zhcf nagios-$(VERSION).tar.gz --exclude nagios-$(VERSION)/nagios-$(VERSION).tar.gz --exclude nagios-$(VERSION)/nagios-$(VERSION) --exclude RCS --exclude CVS --exclude build-* --exclude *~ --exclude .git* nagios-$(VERSION)/ + rm -f nagios-$(VERSION) + # Targets that always get built -.PHONY: indent clean clean distclean +.PHONY: indent clean clean distclean dox test html diff --git a/OutputTrap.pm b/OutputTrap.pm deleted file mode 100644 index 73eac36..0000000 --- a/OutputTrap.pm +++ /dev/null @@ -1,39 +0,0 @@ -package OutputTrap; -# -# Methods for use by tied STDOUT in embedded PERL module. -# -# Simply redirects STDOUT to a temporary file associated with the -# current child/grandchild process. -# - -use strict; -# Perl before 5.6 does not seem to have warnings.pm ??? -#use warnings; -use IO::File; - -sub TIEHANDLE { - my ($class, $fn) = @_; - my $handle = new IO::File "> $fn" or die "Cannot open embedded work filei $!\n"; - bless { FH => $handle, Value => 0}, $class; -} - -sub PRINT { - my $self = shift; - my $handle = $self -> {FH}; - print $handle join("",@_); -} - -sub PRINTF { - my $self = shift; - my $fmt = shift; - my $handle = $self -> {FH}; - printf $handle ($fmt,@_); -} - -sub CLOSE { - my $self = shift; - my $handle = $self -> {FH}; - close $handle; -} -1; -__END__ diff --git a/README b/README index 0e7de62..d469d9b 100644 --- a/README +++ b/README @@ -1,29 +1 @@ -Nagios 3.x README ------------------ - - -Nagios is a host/service/network monitoring program written in C and -released under the GNU General Public License. CGI programs are -included to allow you to view the current status, history, etc via -a web interface if you so desire. - -Features: - -1) Monitoring of network services (via SMTP, POP3, HTTP, PING, etc). -2) A plugin interface to allow for user-developed service monitoring methods. -3) Notifications when problems occur and get resolved (via email, pager, - or user-defined method). -4) Ability to define "event handlers" for proactive problem resolution -5) Web output (current status, notifications, problem history, log file, etc.) -6) Automatic log file rotation/archiving - -For installation instructions, use a web browser to read the HTML documentation -in the html/docs subdirectory. - -Visit the Nagios homepage at http://www.nagios.org for online -documentation, new releases, bug reports, information on the mailing -lists, etc. - - -- Ethan Galstad (egalstad@nagios.org) - - +README.asciidoc \ No newline at end of file diff --git a/README.asciidoc b/README.asciidoc new file mode 100644 index 0000000..e24d296 --- /dev/null +++ b/README.asciidoc @@ -0,0 +1,80 @@ +Nagios 4.x README +================= + +Nagios is a host/service/network monitoring program written in C and +released under the GNU General Public License, version 2. CGI programs +are included to allow you to view the current status, history, etc via +a web interface if you so desire. + +Visit the Nagios homepage at https://www.nagios.org for documentation, +new releases, bug reports, information on discussion forums, and more. + + +https://www.nagios.org/about/features/[Features] +----------------------------------------------- +* Monitoring of network services (via SMTP, POP3, HTTP, PING, etc). +* Monitoring of host resources (processor load, disk usage, etc.). +* A plugin interface to allow for user-developed service monitoring + methods. +* Ability to define network host hierarchy using "parent" hosts, + allowing detection of and distinction between hosts that are down + and those that are unreachable. +* Notifications when problems occur and get resolved (via email, + pager, or user-defined method). +* Ability to define event handlers for proactive problem resolution. +* Automatic log file rotation/archiving. +* Optional web interface for viewing current network status, + notification and problem history, log file, etc. + + +Changes +------- +See the +https://raw.githubusercontent.com/NagiosEnterprises/nagioscore/master/Changelog[Changelog] +for a summary of important changes and fixes, or the +https://github.com/NagiosEnterprises/nagioscore/commits/master[commit history] +for more detail. + + +Download +-------- +Latest releases can be downloaded from https://www.nagios.org/download/ + + +Installation +------------ +http://nagios.sourceforge.net/docs/nagioscore/4/en/quickstart.html[Quickstart installation guides] +are available to help you get Nagios up and monitoring. + + +Documentation & Support +----------------------- +* http://nagios.sourceforge.net/docs/nagioscore/4/en/[User Guide] +* https://library.nagios.com/library/products/nagioscore/[Nagios Core Documentation Library] +* https://support.nagios.com/forum/viewforum.php?f=7[Support Forums] +* https://www.nagios.org/support/[Additional Support Resources] + + +Contributing +------------ +The Nagios source code is hosted on GitHub: +https://github.com/NagiosEnterprises/nagioscore + +Do you have an idea or feature request to make Nagios better? Join or +start a discussion on the +https://support.nagios.com/forum/viewforum.php?f=34[Nagios Core Development forum]. +Bugs can be reported by +https://github.com/NagiosEnterprises/nagioscore/issues/new[opening an +issue on GitHub]. If you have identified a security related issue in +Nagios, please contact security@nagios.com. + +Patches and GitHub pull requests are welcome. Pull requests on GitHub +link commits in version control to review and discussion of the +changes, helping to show how and why changes were made, in addition to +who was involved. + +Created by Ethan Galstad, the success of Nagios has been due to the +fantastic community members that support it and provide bug reports, +patches, and great ideas. See the +https://raw.githubusercontent.com/NagiosEnterprises/nagioscore/master/THANKS[THANKS file] +for some of the many who have contributed since 1999. diff --git a/THANKS b/THANKS index b7c666e..90ee406 100644 --- a/THANKS +++ b/THANKS @@ -5,299 +5,329 @@ THANKS! The success of Nagios has been due to the fantastic community members that support it and provide bug reports, patches, and great ideas. Here are a few of the many members that have contributed to Nagios in various ways -since 1999. If I missed your name, let me know. +since 1999. If I missed your name, misspelled it or otherwise got it +wrong, please let me know. -* Greg Abrams -* Petr Adamec -* Gavin Adams -* David Allan -* Felipe Almeida -* Markus Almroth -* Jon Andrews -* Michael Anthon -* Bernd Arnold -* Erwan Arzur -* Volker Aust -* Hendrik Baecker -* Markus Baertschi -* Michael Bailey -* Luigi Balzano -* Sebastien Barbereau -* Wolfgang Barth -* Devin Bayer -* Simon Beale -* Ben Bell -* Marlo Bell -* Ray Bengen -* Derrick Bennett -* Chris Bensend -* Kevin Benton -* Gary Berger -* Sven-Göran Bergh -* Jochen Bern -* Tom Bertelson -* Joel Berry -* Olivier Beytrison -* Christoph Biedl -* Dennis Biringer -* Mike Bird -* Jason Blakey -* Jeffrey Blank -* Ian Blenke -* Fran Boon -* Jeremy Bouse * Adam Bowen -* Ludo Bosmans -* Henning Brauer -* Michael Bunk -* Daniel Burke -* Grant Byers -* John Calcote -* Don Carroll -* Ian Cass +* Ahmon Dancy +* Alain Radix +* Albrecht Dress +* Alessandro Ren +* Alex Peeters * Alexios Chouhoulas * Allan Clark -* Jonathan Clarke -* Justin Clarke -* Perry Clarke -* Nick Cleaton -* Charlie Cook -* Garry Cook -* Jeff Cours -* Michelle Craft -* Matthias Cramer -* Matthieu Kermagoret -* Jim Crilley -* Joel Crisp -* Jean-Eric Cuendet -* Ahmon Dancy -* Jan David -* Stephen Davies -* Karl DeBisschop -* Tom De Blende -* Mark DeTrano -* Thomas Dohl -* Mike Dorman -* Albrecht Dress * Alok Dubey -* Jim Dumser -* Thomas Dunkel -* Matthias Eble -* Ari Edelkind -* Matthias Eichler -* Rob Enders -* Andreas Ericsson -* Matt Ezell -* Sylvain Falardeau -* Duncan Ferguson -* Sean Finney -* Andy Finkenstadt -* Mika Fischer -* Matthias Flacke -* Marcus Fleige -* Matthias Flittner -* Bastian Friedrich -* Jean Gabes -* Szabo Gabor -* Mathieu Gagne -* Dan Gailey -* Darren Gamble -* Robert Gash -* Hugo Gayosso -* Subhendu Ghosh -* Mark Goldfinch -* Jeffrey Goldschrafe -* Jan Grant -* Stephen Gran -* Matthew Grant -* Martin Green -* Todd Green -* Nathan Grennan -* Sebastian Guarino -* Thomas Guyot-Sionnest -* Sergio Guzman -* Hugo Hallqvist -* Lars Hansson -* Ben Heavner -* Lars Hecking -* Jason Hedden -* Karl Hegbloom -* Thomas Hepper -* Marcus Hildenbrand -* Arne Hinrichsen -* Ronald Ho -* Stanley Hopcroft -* Sam Howard -* Torsten Huebler -* Stig Jacobsen -* Percy Jahn -* Stewart James -* Olivier Jan -* Jeff Johnson -* Jonathan Kamens -* Andrew Kaplan -* Lars Kellogg-Stedman -* Paul Kent -* Matthieu Kermagoret -* Matthias Kerk -* Bo Kersey -* Andreas Kirchwitz -* Burkhard Klaus -* Tobias Klausmann -* Igno Kley -* Rene Klootwijk -* David Kmoch -* Brandon Knitter -* Uwe Knop -* Ryoji Kobayashi -* Uwe Knop -* Daniel Koffler -* Petya Kohts -* Chris Kolquist -* Jiri Kostern -* Christoph Kron -* Ivan Kuncl -* Dean Lane -* Ingo Lantschner -* Gerhard Lausser -* William Leibzon -* Pedro Leite -* Bernard Li -* Joerg Linge -* Michael Little -* Shad Lords -* Larry Low -* Michael Lubben -* Tyler Lund -* Jacob Lundqvist -* James Maddison -* Joseph Maiorana -* Ricardo Maraschini -* Michael Marineau -* Roberto Marrodan -* Ernst-Deiter Martin -* Christoph Maser -* Christian Masopust -* Emanuel Massano -* Richard Mayhew -* Mike McHenry -* Gordon Messmer -* Lars Michelson -* Martin Mielke -* Christian Mies -* Gary Miller -* Peter Valdemar Morch -* James Moseley -* Tobias Mucke -* Gerd Mueller -* Bob (Netshell) -* Time Niemueller -* Sven Nierlein -* Michael O'Reilly -* Tomer Okavi -* Vadim Okun -* Hiren Patel -* Rob Patrick -* Remi Paulmier -* Alex Peeters -* James "Showkilr" Peterson -* Cary Petterborg -* Bill Pier -* Badri Pillai -* Steven Pokrandt -* Jim Popovitch -* Janet Post -* Paul Pot -* Daniel Pouzzner -* Marc Powell -* William Preston -* Patrick Proy -* Luiz Felipe R E -* Alain Radix -* Kenneth Ray -* Nick Reinking -* Rob Remus -* Alessandro Ren -* Bob Rentschler -* Mindaugas Riauba -* Matthew Richardson -* Dietmar Rieder -* Brian Riggs -* Peter Ringe -* Eirik Robertstad -* Stefan Rompf +* Aman Gupta * Amir Rosenblatt -* Luke Ross -* Ralph Rossner -* Chris Rothecker -* John Rouillard -* Yves Rubin -* Mattias Ryrlen -* Jonathan Saggau -* Karel Salavec -* Jorge Sanchez -* Bogdan Sandu -* Pavel Satrapa -* Frederic Schaer -* Mark Schenker -* David Schlecht -* Russell Scibetti -* Max Schubert -* Stefan Schurtz -* Thomas Sebastien -* Brian Seklecki -* Denis Seleznyov -* Lonny Selinger -* Nate Shafer -* Moshe Sharon -* Andy Shellam -* Nick Shore -* Ryan Skorstad -* Michael Smedius -* Gordon Smith -* Lou Sneddon -* Mark Spieth -* Tim Starling -* Thomas Stolle -* Kevin Stone -* Herbert Straub -* Sven Strickroth -* SUSE Linux Team -* Horvath Tamas -* Nicholas Tang -* Glenn Thompson -* Robert Thompson -* Josh Thorstad -* David Tilloy -* Gennaro Tortone -* Steve Underwood -* Kai Ung -* Stephane Urbanovski -* Franky Van Liedekerke -* Nikola Vassilev -* Esteban Manchado Velazquez -* Geert Vanderkelen -* Carlos Velasco -* Jan Vejvalka -* Robert August Vincent II -* Dave Viner -* Ton Voon -* Lars Vogdt -* Phil Walther -* Jeremy Weatherford -* Holger Weiss -* Tom Welsh -* Brad Werschler -* Peter Westlake -* Todd Wheeler -* Florian Weimer -* Tim Wilde -* Chris Witterholt -* Evan Winter -* Armin Wolfermann -* Greg Woods -* Cliff Woolley -* Mitch Wright -* Michal Zimen -* Pawel Zuzelski * Anders K. Lindgren +* Andreas Ericsson +* Andreas Kirchwitz +* Andrew Kaplan +* Andrew Widdersheim +* Andy Finkenstadt +* Andy Shellam +* Anton Lofgren +* Ari Edelkind +* Armin Wolfermann +* Arne Hinrichsen +* Badri Pillai +* Bastian Friedrich +* Ben Bell +* Ben Heavner +* Bernard Li +* Bernd Arnold +* Bill Pier +* Bo Kersey +* Bob (Netshell) +* Bob Rentschler +* Bogdan Sandu +* Brad Werschler +* Brandon Knitter +* Brian Riggs +* Brian Seklecki +* Burkhard Klaus +* Carlos Velasco +* Cary Petterborg +* Charlie Cook +* Chris Bensend +* Chris Kolquist +* Chris Rothecker +* Chris Witterholt +* Christian Masopust +* Christian Mies +* Christoph Biedl +* Christoph Kron +* Christoph Maser +* Cliff Woolley +* Dan Gailey +* Daniel Burke +* Daniel Koffler +* Daniel Pouzzner +* Daniel Wittenberg +* Darren Gamble +* Dave Viner +* David Allan +* David Kmoch +* David Schlecht +* David Tilloy +* Dawid Golunski +* Dean Lane +* Denis Seleznyov +* Dennis Biringer +* Derrick Bennett +* Devin Bayer +* Dietmar Rieder +* Dirkjan Bussink +* Don Carroll +* Duncan Ferguson +* Eirik Robertstad +* Emanuel Massano +* Ernst-Deiter Martin +* Erwan Arzur +* Esteban Manchado Velazquez +* Evan Winter +* Felipe Almeida +* Florian Weimer +* Fran Boon +* Franky Van Liedekerke +* Frederic Schaer +* Frederic Van Espen +* Garry Cook +* Gary Berger +* Gary Miller +* Gavin Adams +* Geert Vanderkelen +* Gennaro Tortone +* Geoff Montee +* Gerd Mueller +* Gerhard Lausser +* gherteg +* Glenn Thompson +* Gordon Messmer +* Gordon Smith +* Grant Byers +* Greg Abrams +* Greg Woods +* Hayakawa Shinya +* Helmut Mikulcik +* Hendrik Baecker +* Henning Brauer +* Herbert Straub +* Hiren Patel +* Holger Weiss +* Horvath Tamas +* Hugo Gayosso +* Hugo Hallqvist +* Ian Blenke +* Ian Cass +* Igno Kley +* Ingo Lantschner +* Ivan Kuncl +* Jacob Lundqvist +* James "Showkilr" Peterson +* James Maddison +* James Moseley +* Jan David +* Jan Grant +* Jan Vejvalka +* Janet Post +* Janice Singh +* Jason Blakey +* Jason Hedden +* Jean Gabes +* Jean-Eric Cuendet +* Jeff Cours +* Jeff Johnson +* Jeffrey Blank +* Jeffrey Goldschrafe +* Jeremy Bouse +* Jeremy Weatherford +* Jim Crilley +* Jim Dumser +* Jim Popovitch +* Jiri Kostern +* Jochen Bern +* Joel Berry +* Joel Crisp +* Joerg Linge +* John Calcote +* John Rouillard +* Jon Andrews +* Jonathan Clarke +* Jonathan Kamens +* Jonathan Saggau +* Jorge Sanchez +* Joseph Maiorana +* Josh Soref +* Josh Thorstad +* Justin Clarke +* Kai Kunstmann +* Kai Ung +* Karel Salavec +* Karl DeBisschop +* Karl Hegbloom +* Karsten Weiss +* Kenneth Ray +* Kevin Benton +* Kevin Stone +* Larry Low +* Lars Hansson +* Lars Hecking +* Lars Kellogg-Stedman +* Lars Michelson +* Lars Vogdt +* lev +* Lonny Selinger +* Lou Sneddon +* Ludo Bosmans +* Luigi Balzano +* Luiz Felipe R E +* Luke Ross +* Marc Powell +* Marcus Fleige +* Marcus Hildenbrand +* Mark DeTrano +* Mark Frost +* Mark Goldfinch +* Mark Schenker +* Mark Spieth +* Markus Almroth +* Markus Baertschi +* Marlo Bell +* Martin Green +* Martin Mielke +* Mathieu Gagne +* Matt Ezell +* Matthew Grant +* Matthew Richardson +* Matthias Cramer +* Matthias Eble +* Matthias Eichler +* Matthias Flacke +* Matthias Flittner +* Matthias Kerk +* Matthieu Kermagoret +* Matthieu Kermagoret +* Mattias Ryrlen +* Max Schubert +* Max Sikstrom +* Michael Anthon +* Michael Bailey +* Michael Bunk +* Michael Little +* Michael Lubben +* Michael Marineau +* Michael O'Reilly +* Michael Smedius +* Michal Zimen +* Michelle Craft +* Mika Fischer +* Mike Bird +* Mike Dorman +* Mike McHenry +* Mindaugas Riauba +* Mitch Wright +* Moshe Sharon +* Nate Shafer +* Nathan Grennan +* Nicholas Tang +* Nick Cleaton +* Nick Reinking +* Nick Shore +* Nikola Vassilev +* Olivier Beytrison +* Olivier Jan +* Parth Laxmikant Kolekar +* Patrick Proy +* Patrik Halfar +* Paul Kent +* Paul Pot +* Pavel Satrapa +* Pawel Zuzelski +* Pedro Leite +* Percy Jahn +* Perry Clarke +* Peter Ringe +* Peter Valdemar Morch +* Peter Westlake +* Petr Adamec +* Petya Kohts +* Phil Mayers +* Phil Randal +* Phil Walther +* Ralph Rossner +* Ray Bengen +* Remi Paulmier +* Rene Klootwijk +* Ricardo Maraschini +* Richard Mayhew +* Rob Enders +* Rob Patrick +* Rob Remus +* Robert August Vincent II +* Robert Gash +* Robert Thompson +* Roberto Marrodan +* Robin Kearney +* Robin Sonefors +* Ronald Ho +* Rostislav Opočenský +* Russell Scibetti +* Ryan Skorstad +* Ryoji Kobayashi +* Sam Howard +* Sean Finney +* Sebastian Guarino +* Sebastien Barbereau +* Sergio Guzman +* Shad Lords +* Simon Beale +* Stanley Hopcroft +* Stefan Rompf +* Stefan Schurtz +* Stephane Urbanovski +* Stephen Davies +* Stephen Gran +* Steve Underwood +* Steven Pokrandt +* Stewart James +* Stig Jacobsen +* Subhendu Ghosh +* SUSE Linux Team +* Sven Nierlein +* Sven Strickroth +* Sven-Göran Bergh +* Sylvain Falardeau +* Szabo Gabor +* Thomas Dohl +* Thomas Dunkel +* Thomas Guyot-Sionnest +* Thomas Hepper +* Thomas Sebastien +* Thomas Stolle +* Tim Starling +* Tim Wilde +* Time Niemueller +* Tobias Klausmann +* Tobias Mucke +* Todd Green +* Todd Wheeler +* Tom Bertelson +* Tom De Blende +* Tom Welsh +* Tomer Okavi +* Ton Voon +* Torsten Huebler +* Tyler Lund +* Uwe Knop +* Uwe Knop +* Vadim Okun +* Volkan Yazici +* Volker Aust +* William Leibzon +* William Preston +* Wolfgang Barth +* xoubih +* Yves Rubin +* Zakhar Kleyman +* Z. Liu diff --git a/UPGRADING b/UPGRADING index 2b97924..921e153 100644 --- a/UPGRADING +++ b/UPGRADING @@ -1,5 +1,18 @@ -Upgrading to Nagios 3.x ------------------------ +Upgrading Nagios Core +===================== + +nagios-4.3.0 - 2017-02-21 +------------------------- + +If you use "corewindow", as in + http://localhost/nagios?corewindow=www.somewhere.com +note that this functionality has been disabled by default in this +release. If you still want to use it, run ./configure with the +parameter --enable-corewindow + + +nagios-3.0 +---------- The HTML documentation covers what you need to know in order to upgrade from Nagios 2.x You can find the documentation in @@ -11,9 +24,3 @@ Make sure to read the following sections: - "What's New" (whatsnew.html) - "Upgrading Nagios" (upgrading.html) - - - - - - diff --git a/base/Makefile.in b/base/Makefile.in index 868e1d1..74a8211 100644 --- a/base/Makefile.in +++ b/base/Makefile.in @@ -1,7 +1,6 @@ ############################ # Makefile for Nagios # -# Last Modified: 12-05-2008 ############################ @@ -9,9 +8,10 @@ SRC_COMMON=../common SRC_INCLUDE=../include SRC_XDATA=../xdata +SRC_LIB=../lib CC=@CC@ -CFLAGS=-Wall @CFLAGS@ @DEFS@ -DNSCORE +CFLAGS=-Wall -I.. @CFLAGS@ @DEFS@ -DNSCORE # Compiler flags for use with gprof #CFLAGS=-pg -DHAVE_CONFIG_H -DNSCORE @@ -47,82 +47,52 @@ CGIURL=@cgiurl@ HTMURL=@htmurl@ MATHLIBS=-lm -PERLLIBS=@PERLLIBS@ -PERLXSI_O=@PERLXSI_O@ SOCKETLIBS=@SOCKETLIBS@ -THREADLIBS=@THREADLIBS@ BROKERLIBS=@BROKERLIBS@ BROKER_LDFLAGS=@BROKER_LDFLAGS@ CP=@CP@ -# External data I/O code and headers -XSDC=@XSDC@ -XSDH=@XSDH@ -XCDC=@XCDC@ -XCDH=@XCDH@ -XRDC=@XRDC@ -XRDH=@XRDH@ -XODC=@XODC@ -XODH=@XODH@ -XPDC=@XPDC@ -XPDH=@XPDH@ -XDDC=@XDDC@ -XDDH=@XDDH@ - # Extra base code BASEEXTRALIBS=@BASEEXTRALIBS@ # Generated automatically from configure script -SNPRINTF_O=@SNPRINTF_O@ BROKER_O=@BROKER_O@ BROKER_H=@BROKER_H@ # Object data -#ODATALIBS=$(SRC_COMMON)/objects.c $(SRC_XDATA)/$(XODC) -#ODATAHDRS=$(SRC_INCLUDE)/objects.h $(SRC_XDATA)/$(XODH) ODATALIBS=objects-base.o xobjects-base.o ODATAHDRS= ODATADEPS=$(ODATALIBS) # Retention data -#RDATALIBS=sretention.o $(SRC_XDATA)/$(XRDC) -#RDATAHDRS=$(SRC_INCLUDE)/sretention.h $(SRC_XDATA)/$(XRDH) RDATALIBS=retention-base.o xretention-base.o RDATAHDRS= RDATADEPS=$(RDATALIBS) # Comment data -#CDATALIBS=$(SRC_COMMON)/comments.c $(SRC_XDATA)/$(XCDC) -#CDATAHDRS=$(SRC_INCLUDE)/comments.h $(SRC_XDATA)/$(XCDH) CDATALIBS=comments-base.o xcomments-base.o CDATAHDRS= CDATADEPS=$(CDATALIBS) # Status data -#SDATALIBS=$(SRC_COMMON)/statusdata.c $(SRC_XDATA)/$(XSDC) -#SDATAHDRS=$(SRC_INCLUDE)/statusdata.h $(SRC_XDATA)/$(XSDH) SDATALIBS=statusdata-base.o xstatusdata-base.o SDATAHDRS= SDATADEPS=$(SDATALIBS) # Performance data -#PDATALIBS=perfdata.o $(SRC_XDATA)/$(XPDC) -#PDATAHDRS=$(SRC_INCLUDE)/perfdata.h $(SRC_XDATA)/$(XPDH) PDATALIBS=perfdata-base.o xperfdata-base.o PDATAHDRS= PDATADEPS=$(PDATALIBS) # Downtime data -#DDATALIBS=$(SRC_COMMON)/downtime.c $(SRC_XDATA)/$(XDDC) -#DDATAHDRS=$(SRC_INCLUDE)/downtime.h $(SRC_XDATA)/$(XDDH) -DDATALIBS=downtime-base.o xdowntime-base.o +DDATALIBS=downtime-base.o DDATAHDRS= DDATADEPS=$(DDATALIBS) -OBJS=$(BROKER_O) $(SRC_COMMON)/shared.o checks.o config.o commands.o events.o flapping.o logging.o macros-base.o netutils.o notifications.o sehandlers.o skiplist.o utils.o $(RDATALIBS) $(CDATALIBS) $(ODATALIBS) $(SDATALIBS) $(PDATALIBS) $(DDATALIBS) $(BASEEXTRALIBS) $(SNPRINTF_O) $(PERLXSI_O) +OBJS=$(BROKER_O) $(SRC_COMMON)/shared.o nerd.o query-handler.o workers.o checks.o config.o commands.o events.o flapping.o logging.o macros-base.o netutils.o notifications.o sehandlers.o utils.o $(RDATALIBS) $(CDATALIBS) $(ODATALIBS) $(SDATALIBS) $(PDATALIBS) $(DDATALIBS) $(BASEEXTRALIBS) OBJDEPS=$(ODATADEPS) $(ODATADEPS) $(RDATADEPS) $(CDATADEPS) $(SDATADEPS) $(PDATADEPS) $(DDATADEPS) $(BROKER_H) all: nagios nagiostats @@ -133,56 +103,61 @@ all: nagios nagiostats macros-base.o: $(SRC_COMMON)/macros.c $(SRC_INCLUDE)/macros.h $(CC) $(CFLAGS) -c -o $@ $(SRC_COMMON)/macros.c -skiplist.o: $(SRC_COMMON)/skiplist.c $(SRC_INCLUDE)/skiplist.h - $(CC) $(CFLAGS) -c -o $@ $(SRC_COMMON)/skiplist.c - objects-base.o: $(SRC_COMMON)/objects.c $(SRC_INCLUDE)/objects.h $(CC) $(CFLAGS) -c -o $@ $(SRC_COMMON)/objects.c -xobjects-base.o: $(SRC_XDATA)/$(XODC) $(SRC_XDATA)/$(XODH) - $(CC) $(CFLAGS) -c -o $@ $(SRC_XDATA)/$(XODC) +xobjects-base.o: $(SRC_XDATA)/xodtemplate.c $(SRC_XDATA)/xodtemplate.h + $(CC) $(CFLAGS) -c -o $@ $(SRC_XDATA)/xodtemplate.c statusdata-base.o: $(SRC_COMMON)/statusdata.c $(SRC_INCLUDE)/statusdata.h $(CC) $(CFLAGS) -c -o $@ $(SRC_COMMON)/statusdata.c -xstatusdata-base.o: $(SRC_XDATA)/$(XSDC) $(SRC_XDATA)/$(XSDH) - $(CC) $(CFLAGS) -c -o $@ $(SRC_XDATA)/$(XSDC) +xstatusdata-base.o: $(SRC_XDATA)/xsddefault.c $(SRC_XDATA)/xsddefault.h + $(CC) $(CFLAGS) -c -o $@ $(SRC_XDATA)/xsddefault.c comments-base.o: $(SRC_COMMON)/comments.c $(SRC_INCLUDE)/comments.h $(CC) $(CFLAGS) -c -o $@ $(SRC_COMMON)/comments.c -xcomments-base.o: $(SRC_XDATA)/$(XCDC) $(SRC_XDATA)/$(XCDH) - $(CC) $(CFLAGS) -c -o $@ $(SRC_XDATA)/$(XCDC) +xcomments-base.o: $(SRC_XDATA)/xcddefault.c $(SRC_XDATA)/xcddefault.h + $(CC) $(CFLAGS) -c -o $@ $(SRC_XDATA)/xcddefault.c downtime-base.o: $(SRC_COMMON)/downtime.c $(SRC_INCLUDE)/downtime.h $(CC) $(CFLAGS) -c -o $@ $(SRC_COMMON)/downtime.c -xdowntime-base.o: $(SRC_XDATA)/$(XDDC) $(SRC_XDATA)/$(XDDH) - $(CC) $(CFLAGS) -c -o $@ $(SRC_XDATA)/$(XDDC) - perfdata-base.o: perfdata.c $(SRC_INCLUDE)/perfdata.h $(CC) $(CFLAGS) -c -o $@ perfdata.c -xperfdata-base.o: $(SRC_XDATA)/$(XPDC) $(SRC_XDATA)/$(XPDH) - $(CC) $(CFLAGS) -c -o $@ $(SRC_XDATA)/$(XPDC) +xperfdata-base.o: $(SRC_XDATA)/xpddefault.c $(SRC_XDATA)/xpddefault.h + $(CC) $(CFLAGS) -c -o $@ $(SRC_XDATA)/xpddefault.c retention-base.o: sretention.c $(SRC_INCLUDE)/sretention.h $(CC) $(CFLAGS) -c -o $@ sretention.c -xretention-base.o: $(SRC_XDATA)/$(XRDC) $(SRC_XDATA)/$(XRDH) - $(CC) $(CFLAGS) -c -o $@ $(SRC_XDATA)/$(XRDC) +xretention-base.o: $(SRC_XDATA)/xrddefault.c $(SRC_XDATA)/xrddefault.h + $(CC) $(CFLAGS) -c -o $@ $(SRC_XDATA)/xrddefault.c $(SRC_COMMON)/shared.o: $(SRC_COMMON)/shared.c $(CC) $(CFLAGS) -c -o $@ $< +workers.o: workers.c wpres-phash.h + $(CC) $(CFLAGS) -c -o $@ $< + +wpres-phash.h: wpres.gperf + gperf -S 1 -t -H wpres_key_phash -N wpres_get_key $< > $@ ########## NAGIOS ########## -nagios: nagios.c $(OBJS) $(OBJDEPS) $(SRC_INCLUDE)/nagios.h $(SRC_INCLUDE)/locations.h - $(CC) $(CFLAGS) -o $@ nagios.c $(OBJS) $(BROKER_LDFLAGS) $(LDFLAGS) $(PERLLIBS) $(MATHLIBS) $(SOCKETLIBS) $(THREADLIBS) $(BROKERLIBS) $(LIBS) +libnagios: + $(MAKE) -C $(SRC_LIB) -nagiostats: nagiostats.c $(SRC_INCLUDE)/locations.h - $(CC) $(CFLAGS) -o $@ nagiostats.c $(LDFLAGS) $(MATHLIBS) $(LIBS) +nagios.o: nagios.c $(SRC_INCLUDE)/nagios.h $(SRC_INCLUDE)/locations.h + $(CC) $(CFLAGS) -c -o $@ nagios.c + +nagios: nagios.o $(OBJS) $(OBJDEPS) libnagios + $(CC) $(CFLAGS) -o $@ $< $(OBJS) $(BROKER_LDFLAGS) $(LDFLAGS) $(MATHLIBS) $(SOCKETLIBS) $(BROKERLIBS) $(LIBS) $(SRC_LIB)/libnagios.a + +nagiostats: nagiostats.c $(SRC_INCLUDE)/locations.h libnagios + $(CC) $(CFLAGS) -o $@ nagiostats.c $(LDFLAGS) $(MATHLIBS) $(LIBS) $(SRC_LIB)/libnagios.a $(OBJS): $(SRC_INCLUDE)/locations.h @@ -195,6 +170,7 @@ distclean: clean rm -f Makefile devclean: distclean + rm -f wpres-phash.h install: $(MAKE) install-basic @@ -211,3 +187,5 @@ install-basic: strip-post-install: $(STRIP) $(DESTDIR)$(BINDIR)/@nagios_name@ $(STRIP) $(DESTDIR)$(BINDIR)/@nagiostats_name@ + +.PHONY: libnagios diff --git a/base/broker.c b/base/broker.c index 0d3adef..9381da2 100644 --- a/base/broker.c +++ b/base/broker.c @@ -2,9 +2,6 @@ * * BROKER.C - Event broker routines for Nagios * - * Copyright (c) 2010 Nagios Core Development Team - * Copyright (c) 2002-2006 Ethan Galstad (egalstad@nagios.org) - * Last Modified: 10-03-2010 * * License: * @@ -32,31 +29,6 @@ #include "../include/nebstructs.h" #include "../include/nebmods.h" -extern unsigned long event_broker_options; - -extern time_t program_start; -extern int nagios_pid; -extern int daemon_mode; -extern time_t last_command_check; -extern time_t last_log_rotation; -extern int enable_notifications; -extern int execute_service_checks; -extern int accept_passive_service_checks; -extern int execute_host_checks; -extern int accept_passive_host_checks; -extern int enable_event_handlers; -extern int obsess_over_services; -extern int obsess_over_hosts; -extern int enable_flap_detection; -extern int enable_failure_prediction; -extern int process_performance_data; -extern int aggregate_status_updates; -extern unsigned long modified_host_process_attributes; -extern unsigned long modified_service_process_attributes; -extern char *global_host_event_handler; -extern char *global_service_event_handler; - - #ifdef USE_EVENT_BROKER @@ -241,7 +213,7 @@ int broker_event_handler(int type, int flags, int attr, int eventhandler_type, v /* send host check data to broker */ -int broker_host_check(int type, int flags, int attr, host *hst, int check_type, int state, int state_type, struct timeval start_time, struct timeval end_time, char *cmd, double latency, double exectime, int timeout, int early_timeout, int retcode, char *cmdline, char *output, char *long_output, char *perfdata, struct timeval *timestamp) { +int broker_host_check(int type, int flags, int attr, host *hst, int check_type, int state, int state_type, struct timeval start_time, struct timeval end_time, char *cmd, double latency, double exectime, int timeout, int early_timeout, int retcode, char *cmdline, char *output, char *long_output, char *perfdata, struct timeval *timestamp, check_result *cr) { char *command_buf = NULL; char *command_name = NULL; char *command_args = NULL; @@ -287,6 +259,7 @@ int broker_host_check(int type, int flags, int attr, host *hst, int check_type, ds.output = output; ds.long_output = long_output; ds.perf_data = perfdata; + ds.check_result_ptr = cr; /* make callbacks */ return_code = neb_make_callbacks(NEBCALLBACK_HOST_CHECK_DATA, (void *)&ds); @@ -300,7 +273,7 @@ int broker_host_check(int type, int flags, int attr, host *hst, int check_type, /* send service check data to broker */ -int broker_service_check(int type, int flags, int attr, service *svc, int check_type, struct timeval start_time, struct timeval end_time, char *cmd, double latency, double exectime, int timeout, int early_timeout, int retcode, char *cmdline, struct timeval *timestamp) { +int broker_service_check(int type, int flags, int attr, service *svc, int check_type, struct timeval start_time, struct timeval end_time, char *cmd, double latency, double exectime, int timeout, int early_timeout, int retcode, char *cmdline, struct timeval *timestamp, check_result *cr) { char *command_buf = NULL; char *command_name = NULL; char *command_args = NULL; @@ -347,6 +320,7 @@ int broker_service_check(int type, int flags, int attr, service *svc, int check_ ds.output = svc->plugin_output; ds.long_output = svc->long_plugin_output; ds.perf_data = svc->perf_data; + ds.check_result_ptr = cr; /* make callbacks */ return_code = neb_make_callbacks(NEBCALLBACK_SERVICE_CHECK_DATA, (void *)&ds); @@ -488,7 +462,6 @@ void broker_program_status(int type, int flags, int attr, struct timeval *timest ds.program_start = program_start; ds.pid = nagios_pid; ds.daemon_mode = daemon_mode; - ds.last_command_check = last_command_check; ds.last_log_rotation = last_log_rotation; ds.notifications_enabled = enable_notifications; ds.active_service_checks_enabled = execute_service_checks; @@ -497,7 +470,6 @@ void broker_program_status(int type, int flags, int attr, struct timeval *timest ds.passive_host_checks_enabled = accept_passive_host_checks; ds.event_handlers_enabled = enable_event_handlers; ds.flap_detection_enabled = enable_flap_detection; - ds.failure_prediction_enabled = enable_failure_prediction; ds.process_performance_data = process_performance_data; ds.obsess_over_hosts = obsess_over_hosts; ds.obsess_over_services = obsess_over_services; @@ -975,12 +947,14 @@ void broker_statechange_data(int type, int flags, int attr, int statechange_type ds.host_name = temp_service->host_name; ds.service_description = temp_service->description; ds.output = temp_service->plugin_output; + ds.longoutput = temp_service->long_plugin_output; } else { temp_host = (host *)data; ds.host_name = temp_host->name; ds.service_description = NULL; ds.output = temp_host->plugin_output; + ds.longoutput = temp_host->long_plugin_output; } ds.object_ptr = data; ds.state = state; @@ -1012,6 +986,4 @@ struct timeval get_broker_timestamp(struct timeval *timestamp) { return tv; } - - #endif diff --git a/base/checks.c b/base/checks.c index df4a092..aeeb739 100644 --- a/base/checks.c +++ b/base/checks.c @@ -2,9 +2,6 @@ * * CHECKS.C - Service and host check functions for Nagios * - * Copyright (c) 2011 Nagios Core Development Team - * Copyright (c) 1999-2010 Ethan Galstad (egalstad@nagios.org) - * Last Modified: 01-20-2011 * * License: * @@ -32,195 +29,29 @@ #include "../include/nagios.h" #include "../include/broker.h" #include "../include/perfdata.h" +#include "../include/workers.h" /*#define DEBUG_CHECKS*/ /*#define DEBUG_HOST_CHECKS 1*/ -#ifdef EMBEDDEDPERL -#include "../include/epn_nagios.h" -#endif - #ifdef USE_EVENT_BROKER #include "../include/neberrors.h" #endif -extern int sigshutdown; -extern int sigrestart; - -extern char *temp_file; -extern char *temp_path; -extern char *check_result_path; - -extern int interval_length; - -extern int command_check_interval; - -extern int log_initial_states; -extern int log_passive_checks; -extern int log_host_retries; - -extern int service_check_timeout; -extern int host_check_timeout; - -extern int check_reaper_interval; -extern int max_check_reaper_time; - -extern int use_aggressive_host_checking; -extern unsigned long cached_host_check_horizon; -extern unsigned long cached_service_check_horizon; -extern int enable_predictive_host_dependency_checks; -extern int enable_predictive_service_dependency_checks; - -extern int soft_state_dependencies; - -extern int currently_running_service_checks; -extern int currently_running_host_checks; - -extern int accept_passive_service_checks; -extern int execute_service_checks; -extern int accept_passive_host_checks; -extern int execute_host_checks; -extern int obsess_over_services; -extern int obsess_over_hosts; - -extern int translate_passive_host_checks; -extern int passive_host_checks_are_soft; - -extern int check_service_freshness; -extern int check_host_freshness; -extern int additional_freshness_latency; - -extern int max_host_check_spread; -extern int max_service_check_spread; - -extern int use_large_installation_tweaks; -extern int free_child_process_memory; -extern int child_processes_fork_twice; - -extern time_t last_program_stop; -extern time_t program_start; -extern time_t event_start; - -extern timed_event *event_list_low; -extern timed_event *event_list_low_tail; - -extern host *host_list; -extern service *service_list; -extern servicedependency *servicedependency_list; -extern hostdependency *hostdependency_list; - -extern unsigned long next_event_id; -extern unsigned long next_problem_id; - -extern check_result check_result_info; -extern check_result *check_result_list; - -extern pthread_t worker_threads[TOTAL_WORKER_THREADS]; - -extern unsigned long max_debug_file_size; - -#ifdef EMBEDDEDPERL -extern int use_embedded_perl; -#endif - - - - - /******************************************************************/ /********************** CHECK REAPER FUNCTIONS ********************/ /******************************************************************/ /* reaps host and service check results */ int reap_check_results(void) { - check_result *queued_check_result = NULL; - service *temp_service = NULL; - host *temp_host = NULL; - time_t current_time = 0L; - time_t reaper_start_time = 0L; int reaped_checks = 0; log_debug_info(DEBUGL_FUNCTIONS, 0, "reap_check_results() start\n"); log_debug_info(DEBUGL_CHECKS, 0, "Starting to reap check results.\n"); - /* get the start time */ - time(&reaper_start_time); - /* process files in the check result queue */ - process_check_result_queue(check_result_path); - - /* read all check results that have come in... */ - while((queued_check_result = read_check_result(&check_result_list))) { - - reaped_checks++; - - log_debug_info(DEBUGL_CHECKS, 2, "Found a check result (#%d) to handle...\n", reaped_checks); - - /* service check */ - if(queued_check_result->object_check_type == SERVICE_CHECK) { - - /* make sure the service exists */ - if((temp_service = find_service(queued_check_result->host_name, queued_check_result->service_description)) == NULL) { - - logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Check result queue contained results for service '%s' on host '%s', but the service could not be found! Perhaps you forgot to define the service in your config files?\n", queued_check_result->service_description, queued_check_result->host_name); - - /* free memory */ - free_check_result(queued_check_result); - my_free(queued_check_result); - - /* TODO - add new service definition automatically */ - - continue; - } - - log_debug_info(DEBUGL_CHECKS, 1, "Handling check result for service '%s' on host '%s'...\n", temp_service->description, temp_service->host_name); - - /* process the check result */ - handle_async_service_check_result(temp_service, queued_check_result); - } - - /* host check */ - else { - if((temp_host = find_host(queued_check_result->host_name)) == NULL) { - - /* make sure the host exists */ - logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Check result queue contained results for host '%s', but the host could not be found! Perhaps you forgot to define the host in your config files?\n", queued_check_result->host_name); - - /* free memory */ - free_check_result(queued_check_result); - my_free(queued_check_result); - - /* TODO - add new host definition automatically */ - - continue; - } - - log_debug_info(DEBUGL_CHECKS, 1, "Handling check result for host '%s'...\n", temp_host->name); - - /* process the check result */ - handle_async_host_check_result_3x(temp_host, queued_check_result); - } - - log_debug_info(DEBUGL_CHECKS | DEBUGL_IPC, 1, "Deleted check result file '%s'\n", queued_check_result->output_file); - - /* free allocated memory */ - free_check_result(queued_check_result); - my_free(queued_check_result); - - /* break out if we've been here too long (max_check_reaper_time seconds) */ - time(¤t_time); - if((int)(current_time - reaper_start_time) > max_check_reaper_time) { - log_debug_info(DEBUGL_CHECKS, 0, "Breaking out of check result reaper: max reaper time exceeded\n"); - break; - } - - /* bail out if we encountered a signal */ - if(sigshutdown == TRUE || sigrestart == TRUE) { - log_debug_info(DEBUGL_CHECKS, 0, "Breaking out of check result reaper: signal encountered\n"); - break; - } - } + reaped_checks = process_check_result_queue(check_result_path); log_debug_info(DEBUGL_CHECKS, 0, "Finished reaping %d check results\n", reaped_checks); log_debug_info(DEBUGL_FUNCTIONS, 0, "reap_check_results() end\n"); @@ -278,25 +109,16 @@ int run_scheduled_service_check(service *svc, int check_options, double latency) get_next_valid_time(preferred_time, &next_valid_time, svc->check_period_ptr); /* - logit(NSLOG_RUNTIME_WARNING,TRUE,"Warning: Service '%s' on host '%s' timeperiod check failed...\n",svc->description,svc->host_name); - logit(NSLOG_RUNTIME_WARNING,TRUE,"Current time: %s",ctime(¤t_time)); - logit(NSLOG_RUNTIME_WARNING,TRUE,"Preferred time: %s",ctime(&preferred_time)); - logit(NSLOG_RUNTIME_WARNING,TRUE,"Next valid time: %s",ctime(&next_valid_time)); - */ - - /* the service could not be rescheduled properly - set the next check time for next week */ - /*if(time_is_valid==FALSE && next_valid_time==preferred_time){*/ - /* UPDATED 08/12/09 EG to reflect proper timeperod check logic */ + * If we really can't reschedule the service properly, we + * just push the check to preferred_time plus some reasonable + * random value and try again then. + */ if(time_is_valid == FALSE && check_time_against_period(next_valid_time, svc->check_period_ptr) == ERROR) { - /* - svc->next_check=(time_t)(next_valid_time+(60*60*24*365)); - svc->should_be_scheduled=FALSE; - */ + svc->next_check = preferred_time + + ranged_urand(0, check_window(svc)); - svc->next_check = (time_t)(next_valid_time + (60 * 60 * 24 * 7)); - - logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Check of service '%s' on host '%s' could not be rescheduled properly. Scheduling check for next week...\n", svc->description, svc->host_name); + logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Check of service '%s' on host '%s' could not be rescheduled properly. Scheduling check for %s...\n", svc->description, svc->host_name, ctime(&preferred_time)); log_debug_info(DEBUGL_CHECKS, 1, "Unable to find any valid times to reschedule the next service check!\n"); } @@ -304,14 +126,24 @@ int run_scheduled_service_check(service *svc, int check_options, double latency) /* this service could be rescheduled... */ else { svc->next_check = next_valid_time; + if(next_valid_time > preferred_time) { + /* Next valid time is further in the future because of + * timeperiod constraints. Add a random amount so we + * don't get all checks subject to that timeperiod + * constraint scheduled at the same time + */ + svc->next_check += ranged_urand(0, check_window(svc)); + } svc->should_be_scheduled = TRUE; log_debug_info(DEBUGL_CHECKS, 1, "Rescheduled next service check for %s", ctime(&next_valid_time)); } } - /* reschedule the next service check - unless we couldn't find a valid next check time */ - /* 10/19/07 EG - keep original check options */ + /* + * reschedule the next service check - unless we couldn't + * find a valid next check time, but keep original options + */ if(svc->should_be_scheduled == TRUE) schedule_service_check(svc, svc->next_check, check_options); @@ -330,36 +162,15 @@ int run_async_service_check(service *svc, int check_options, double latency, int nagios_macros mac; char *raw_command = NULL; char *processed_command = NULL; - char output_buffer[MAX_INPUT_BUFFER] = ""; - char *temp_buffer = NULL; struct timeval start_time, end_time; - pid_t pid = 0; - int fork_error = FALSE; - int wait_result = 0; host *temp_host = NULL; - FILE *fp = NULL; - int pclose_result = 0; - mode_t new_umask = 077; - mode_t old_umask; - char *output_file = NULL; double old_latency = 0.0; - dbuf checkresult_dbuf; - int dbuf_chunk = 1024; + check_result *cr; + int runchk_result = OK; + int macro_options = STRIP_ILLEGAL_MACRO_CHARS | ESCAPE_MACRO_CHARS; #ifdef USE_EVENT_BROKER int neb_result = OK; #endif -#ifdef EMBEDDEDPERL - char fname[512] = ""; - char *args[5] = {"", DO_CLEAN, "", "", NULL }; - char *perl_plugin_output = NULL; - SV *plugin_hndlr_cr = NULL; - int count ; - int use_epn = FALSE; -#ifdef aTHX - dTHX; -#endif - dSP; -#endif log_debug_info(DEBUGL_FUNCTIONS, 0, "run_async_service_check()\n"); @@ -385,8 +196,13 @@ int run_async_service_check(service *svc, int check_options, double latency, int end_time.tv_usec = 0L; /* send data to event broker */ - neb_result = broker_service_check(NEBTYPE_SERVICECHECK_ASYNC_PRECHECK, NEBFLAG_NONE, NEBATTR_NONE, svc, SERVICE_CHECK_ACTIVE, start_time, end_time, svc->service_check_command, svc->latency, 0.0, 0, FALSE, 0, NULL, NULL); + neb_result = broker_service_check(NEBTYPE_SERVICECHECK_ASYNC_PRECHECK, NEBFLAG_NONE, NEBATTR_NONE, svc, CHECK_TYPE_ACTIVE, start_time, end_time, svc->check_command, svc->latency, 0.0, 0, FALSE, 0, NULL, NULL, NULL); + if (neb_result == NEBERROR_CALLBACKCANCEL || neb_result == NEBERROR_CALLBACKOVERRIDE) { + log_debug_info(DEBUGL_CHECKS, 0, "Check of service '%s' on host '%s' (id=%u) was %s by a module\n", + svc->description, svc->host_name, svc->id, + neb_result == NEBERROR_CALLBACKCANCEL ? "cancelled" : "overridden"); + } /* neb module wants to cancel the service check - the check will be rescheduled for a later time by the scheduling logic */ if(neb_result == NEBERROR_CALLBACKCANCEL) { if(preferred_time) @@ -419,7 +235,7 @@ int run_async_service_check(service *svc, int check_options, double latency, int grab_service_macros_r(&mac, svc); /* get the raw command line */ - get_raw_command_line_r(&mac, svc->check_command_ptr, svc->service_check_command, &raw_command, 0); + get_raw_command_line_r(&mac, svc->check_command_ptr, svc->check_command, &raw_command, macro_options); if(raw_command == NULL) { clear_volatile_macros_r(&mac); log_debug_info(DEBUGL_CHECKS, 0, "Raw check command for service '%s' on host '%s' was NULL - aborting.\n", svc->description, svc->host_name); @@ -430,7 +246,7 @@ int run_async_service_check(service *svc, int check_options, double latency, int } /* process any macros contained in the argument */ - process_macros_r(&mac, raw_command, &processed_command, 0); + process_macros_r(&mac, raw_command, &processed_command, macro_options); my_free(raw_command); if(processed_command == NULL) { clear_volatile_macros_r(&mac); @@ -444,450 +260,126 @@ int run_async_service_check(service *svc, int check_options, double latency, int /* get the command start time */ gettimeofday(&start_time, NULL); + cr = calloc(1, sizeof(*cr)); + if (!cr) { + clear_volatile_macros_r(&mac); + svc->latency = old_latency; + my_free(processed_command); + return ERROR; + } + init_check_result(cr); + + /* save check info */ + cr->object_check_type = SERVICE_CHECK; + cr->check_type = CHECK_TYPE_ACTIVE; + cr->check_options = check_options; + cr->scheduled_check = scheduled_check; + cr->reschedule_check = reschedule_check; + cr->latency = latency; + cr->start_time = start_time; + cr->finish_time = start_time; + cr->early_timeout = FALSE; + cr->exited_ok = TRUE; + cr->return_code = STATE_OK; + cr->output = NULL; + cr->host_name = (char *)strdup(svc->host_name); + cr->service_description = (char *)strdup(svc->description); + #ifdef USE_EVENT_BROKER /* send data to event broker */ - neb_result = broker_service_check(NEBTYPE_SERVICECHECK_INITIATE, NEBFLAG_NONE, NEBATTR_NONE, svc, SERVICE_CHECK_ACTIVE, start_time, end_time, svc->service_check_command, svc->latency, 0.0, service_check_timeout, FALSE, 0, processed_command, NULL); + neb_result = broker_service_check(NEBTYPE_SERVICECHECK_INITIATE, NEBFLAG_NONE, NEBATTR_NONE, svc, CHECK_TYPE_ACTIVE, start_time, end_time, svc->check_command, svc->latency, 0.0, service_check_timeout, FALSE, 0, processed_command, NULL, cr); /* neb module wants to override the service check - perhaps it will check the service itself */ if(neb_result == NEBERROR_CALLBACKOVERRIDE) { clear_volatile_macros_r(&mac); svc->latency = old_latency; + free_check_result(cr); my_free(processed_command); return OK; } #endif - /* increment number of service checks that are currently running... */ - currently_running_service_checks++; - - /* set the execution flag */ - svc->is_executing = TRUE; - - /* start save check info */ - check_result_info.object_check_type = SERVICE_CHECK; - check_result_info.check_type = SERVICE_CHECK_ACTIVE; - check_result_info.check_options = check_options; - check_result_info.scheduled_check = scheduled_check; - check_result_info.reschedule_check = reschedule_check; - check_result_info.start_time = start_time; - check_result_info.finish_time = start_time; - check_result_info.early_timeout = FALSE; - check_result_info.exited_ok = TRUE; - check_result_info.return_code = STATE_OK; - check_result_info.output = NULL; - - /* open a temp file for storing check output */ - old_umask = umask(new_umask); - asprintf(&output_file, "%s/checkXXXXXX", temp_path); - check_result_info.output_file_fd = mkstemp(output_file); - if(check_result_info.output_file_fd >= 0) - check_result_info.output_file_fp = fdopen(check_result_info.output_file_fd, "w"); - else { - check_result_info.output_file_fp = NULL; - check_result_info.output_file_fd = -1; - } - umask(old_umask); - - log_debug_info(DEBUGL_CHECKS | DEBUGL_IPC, 1, "Check result output will be written to '%s' (fd=%d)\n", output_file, check_result_info.output_file_fd); - - - /* finish save check info */ - check_result_info.host_name = (char *)strdup(svc->host_name); - check_result_info.service_description = (char *)strdup(svc->description); - check_result_info.output_file = (check_result_info.output_file_fd < 0 || output_file == NULL) ? NULL : strdup(output_file); - - /* free memory */ - my_free(output_file); - - /* write start of check result file */ - /* if things go really bad later on down the line, the user will at least have a partial file to help debug missing output results */ - if(check_result_info.output_file_fp) { - - fprintf(check_result_info.output_file_fp, "### Active Check Result File ###\n"); - fprintf(check_result_info.output_file_fp, "file_time=%lu\n", (unsigned long)check_result_info.start_time.tv_sec); - fprintf(check_result_info.output_file_fp, "\n"); - - fprintf(check_result_info.output_file_fp, "### Nagios Service Check Result ###\n"); - fprintf(check_result_info.output_file_fp, "# Time: %s", ctime(&check_result_info.start_time.tv_sec)); - fprintf(check_result_info.output_file_fp, "host_name=%s\n", check_result_info.host_name); - fprintf(check_result_info.output_file_fp, "service_description=%s\n", check_result_info.service_description); - fprintf(check_result_info.output_file_fp, "check_type=%d\n", check_result_info.check_type); - fprintf(check_result_info.output_file_fp, "check_options=%d\n", check_result_info.check_options); - fprintf(check_result_info.output_file_fp, "scheduled_check=%d\n", check_result_info.scheduled_check); - fprintf(check_result_info.output_file_fp, "reschedule_check=%d\n", check_result_info.reschedule_check); - fprintf(check_result_info.output_file_fp, "latency=%f\n", svc->latency); - fprintf(check_result_info.output_file_fp, "start_time=%lu.%lu\n", check_result_info.start_time.tv_sec, check_result_info.start_time.tv_usec); - - /* flush output or it'll get written again when we fork() */ - fflush(check_result_info.output_file_fp); - } - - /* initialize dynamic buffer for storing plugin output */ - dbuf_init(&checkresult_dbuf, dbuf_chunk); - - /* reset latency (permanent value will be set later) */ svc->latency = old_latency; - /* update check statistics */ - update_check_stats((scheduled_check == TRUE) ? ACTIVE_SCHEDULED_SERVICE_CHECK_STATS : ACTIVE_ONDEMAND_SERVICE_CHECK_STATS, start_time.tv_sec); - -#ifdef EMBEDDEDPERL - - /* get"filename" component of command */ - strncpy(fname, processed_command, strcspn(processed_command, " ")); - fname[strcspn(processed_command, " ")] = '\x0'; - - /* should we use the embedded Perl interpreter to run this script? */ - use_epn = file_uses_embedded_perl(fname); - - /* if yes, do some initialization */ - if(use_epn == TRUE) { - - log_debug_info(DEBUGL_CHECKS, 1, "** Using Embedded Perl interpreter to run service check...\n"); - - args[0] = fname; - args[2] = ""; - - if(strchr(processed_command, ' ') == NULL) - args[3] = ""; - else - args[3] = processed_command + strlen(fname) + 1; - - ENTER; - SAVETMPS; - PUSHMARK(SP); - XPUSHs(sv_2mortal(newSVpv(args[0], 0))); - XPUSHs(sv_2mortal(newSVpv(args[1], 0))); - XPUSHs(sv_2mortal(newSVpv(args[2], 0))); - XPUSHs(sv_2mortal(newSVpv(args[3], 0))); - PUTBACK; - - /* call our perl interpreter to compile and optionally cache the command */ - - call_pv("Embed::Persistent::eval_file", G_SCALAR | G_EVAL); - - SPAGAIN ; - - if(SvTRUE(ERRSV)) { - - /* - * if SvTRUE(ERRSV) - * write failure to IPC pipe - * return - */ - - /* remove the top element of the Perl stack (undef) */ - (void) POPs ; - - pclose_result = STATE_UNKNOWN; - perl_plugin_output = SvPVX(ERRSV); - - log_debug_info(DEBUGL_CHECKS, 0, "Embedded Perl failed to compile %s, compile error %s - skipping plugin\n", fname, perl_plugin_output); - - /* save plugin output */ - if(perl_plugin_output != NULL) { - temp_buffer = escape_newlines(perl_plugin_output); - dbuf_strcat(&checkresult_dbuf, temp_buffer); - my_free(temp_buffer); - } - - /* get the check finish time */ - gettimeofday(&end_time, NULL); - - /* record check result info */ - check_result_info.exited_ok = FALSE; - check_result_info.return_code = pclose_result; - check_result_info.finish_time = end_time; - - /* write check result to file */ - if(check_result_info.output_file_fp) { - - fprintf(check_result_info.output_file_fp, "finish_time=%lu.%lu\n", check_result_info.finish_time.tv_sec, check_result_info.finish_time.tv_usec); - fprintf(check_result_info.output_file_fp, "early_timeout=%d\n", check_result_info.early_timeout); - fprintf(check_result_info.output_file_fp, "exited_ok=%d\n", check_result_info.exited_ok); - fprintf(check_result_info.output_file_fp, "return_code=%d\n", check_result_info.return_code); - fprintf(check_result_info.output_file_fp, "output=%s\n", (checkresult_dbuf.buf == NULL) ? "(null)" : checkresult_dbuf.buf); - - /* close the temp file */ - fclose(check_result_info.output_file_fp); - - /* move check result to queue directory */ - move_check_result_to_queue(check_result_info.output_file); - } - - /* free memory */ - dbuf_free(&checkresult_dbuf); - - /* free check result memory */ - free_check_result(&check_result_info); - - return OK; - } - else { - - plugin_hndlr_cr = newSVsv(POPs); - - log_debug_info(DEBUGL_CHECKS, 1, "Embedded Perl successfully compiled %s and returned code ref to plugin handler\n", fname); - - PUTBACK ; - FREETMPS ; - LEAVE ; - } - } -#endif - - /* plugin is a C plugin or a Perl plugin _without_ compilation errors */ - - /* fork a child process */ - pid = fork(); - - /* an error occurred while trying to fork */ - if(pid == -1) { - - fork_error = TRUE; - - logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: The check of service '%s' on host '%s' could not be performed due to a fork() error: '%s'. The check will be rescheduled.\n", svc->description, svc->host_name, strerror(errno)); - - log_debug_info(DEBUGL_CHECKS, 0, "Check of service '%s' on host '%s' could not be performed due to a fork() error: '%s'!\n", svc->description, svc->host_name, strerror(errno)); - } - - /* if we are in the child process... */ - else if(pid == 0) { - - /* set environment variables */ - set_all_macro_environment_vars_r(&mac, TRUE); - - /* ADDED 11/12/07 EG */ - /* close external command file and shut down worker thread */ - close_command_file(); - - /* fork again if we're not in a large installation */ - if(child_processes_fork_twice == TRUE) { - - /* fork again... */ - pid = fork(); - - /* an error occurred while trying to fork again */ - if(pid == -1) - exit(STATE_UNKNOWN); - } - - /* the grandchild (or child if large install tweaks are enabled) process should run the service check... */ - if(pid == 0 || child_processes_fork_twice == FALSE) { - - /* reset signal handling */ - reset_sighandler(); - - /* become the process group leader */ - setpgid(0, 0); - - /* exit on term signals at this process level */ - signal(SIGTERM, SIG_DFL); - - /* catch plugins that don't finish in a timely manner */ - signal(SIGALRM, service_check_sighandler); - alarm(service_check_timeout); - - /* disable rotation of the debug file */ - max_debug_file_size = 0L; - - /******** BEGIN EMBEDDED PERL INTERPRETER EXECUTION ********/ -#ifdef EMBEDDEDPERL - if(use_epn == TRUE) { - - /* execute our previously compiled script - from call_pv("Embed::Persistent::eval_file",..) */ - /* NB. args[2] is _now_ a code ref (to the Perl subroutine corresp to the plugin) returned by eval_file() */ - - ENTER; - SAVETMPS; - PUSHMARK(SP); - - XPUSHs(sv_2mortal(newSVpv(args[0], 0))); - XPUSHs(sv_2mortal(newSVpv(args[1], 0))); - XPUSHs(plugin_hndlr_cr); - XPUSHs(sv_2mortal(newSVpv(args[3], 0))); - - PUTBACK; - - count = call_pv("Embed::Persistent::run_package", G_ARRAY); - - SPAGAIN; - - perl_plugin_output = POPpx ; - pclose_result = POPi ; - - /* NOTE: 07/16/07 This has to be done before FREETMPS statement below, or the POPpx pointer will be invalid (Hendrik B.) */ - /* get perl plugin output - escape newlines */ - if(perl_plugin_output != NULL) { - temp_buffer = escape_newlines(perl_plugin_output); - dbuf_strcat(&checkresult_dbuf, temp_buffer); - my_free(temp_buffer); - } - - PUTBACK; - FREETMPS; - LEAVE; - - log_debug_info(DEBUGL_CHECKS, 1, "Embedded Perl ran %s: return code=%d, plugin output=%s\n", fname, pclose_result, (perl_plugin_output == NULL) ? "NULL" : checkresult_dbuf.buf); - - /* reset the alarm */ - alarm(0); - - /* get the check finish time */ - gettimeofday(&end_time, NULL); - - /* record check result info */ - check_result_info.return_code = pclose_result; - check_result_info.finish_time = end_time; - - /* write check result to file */ - if(check_result_info.output_file_fp) { - - fprintf(check_result_info.output_file_fp, "finish_time=%lu.%lu\n", check_result_info.finish_time.tv_sec, check_result_info.finish_time.tv_usec); - fprintf(check_result_info.output_file_fp, "early_timeout=%d\n", check_result_info.early_timeout); - fprintf(check_result_info.output_file_fp, "exited_ok=%d\n", check_result_info.exited_ok); - fprintf(check_result_info.output_file_fp, "return_code=%d\n", check_result_info.return_code); - fprintf(check_result_info.output_file_fp, "output=%s\n", (checkresult_dbuf.buf == NULL) ? "(null)" : checkresult_dbuf.buf); - - /* close the temp file */ - fclose(check_result_info.output_file_fp); - - /* move check result to queue directory */ - move_check_result_to_queue(check_result_info.output_file); - } - - /* free memory */ - dbuf_free(&checkresult_dbuf); - - /* free check result memory */ - free_check_result(&check_result_info); - - /* return with plugin exit status - not really necessary... */ - _exit(pclose_result); - } -#endif - /******** END EMBEDDED PERL INTERPRETER EXECUTION ********/ - - - /* run the plugin check command */ - fp = popen(processed_command, "r"); - if(fp == NULL) - _exit(STATE_UNKNOWN); - - /* initialize buffer */ - strcpy(output_buffer, ""); - - /* get all lines of plugin output - escape newlines */ - while(fgets(output_buffer, sizeof(output_buffer) - 1, fp)) { - temp_buffer = escape_newlines(output_buffer); - dbuf_strcat(&checkresult_dbuf, temp_buffer); - my_free(temp_buffer); - } - - /* close the process */ - pclose_result = pclose(fp); - - /* reset the alarm and ignore SIGALRM */ - signal(SIGALRM, SIG_IGN); - alarm(0); - - /* get the check finish time */ - gettimeofday(&end_time, NULL); - - /* record check result info */ - check_result_info.finish_time = end_time; - check_result_info.early_timeout = FALSE; - - /* test for execution error */ - if(pclose_result == -1) { - pclose_result = STATE_UNKNOWN; - check_result_info.return_code = STATE_CRITICAL; - check_result_info.exited_ok = FALSE; - } - else { - if(WEXITSTATUS(pclose_result) == 0 && WIFSIGNALED(pclose_result)) - check_result_info.return_code = 128 + WTERMSIG(pclose_result); - else - check_result_info.return_code = WEXITSTATUS(pclose_result); - } - - /* write check result to file */ - if(check_result_info.output_file_fp) { - FILE *fp; - - /* avoid races with signal handling */ - fp = check_result_info.output_file_fp; - check_result_info.output_file_fp = NULL; - - fprintf(fp, "finish_time=%lu.%lu\n", check_result_info.finish_time.tv_sec, check_result_info.finish_time.tv_usec); - fprintf(fp, "early_timeout=%d\n", check_result_info.early_timeout); - fprintf(fp, "exited_ok=%d\n", check_result_info.exited_ok); - fprintf(fp, "return_code=%d\n", check_result_info.return_code); - fprintf(fp, "output=%s\n", (checkresult_dbuf.buf == NULL) ? "(null)" : checkresult_dbuf.buf); - - /* close the temp file */ - fclose(fp); - - /* move check result to queue directory */ - move_check_result_to_queue(check_result_info.output_file); - } - - /* free memory */ - dbuf_free(&checkresult_dbuf); - my_free(processed_command); - - /* free check result memory */ - free_check_result(&check_result_info); - - /* return with plugin exit status - not really necessary... */ - _exit(pclose_result); - } - - /* NOTE: this code is never reached if large install tweaks are enabled... */ - - /* unset environment variables */ - set_all_macro_environment_vars_r(&mac, FALSE); - - /* free allocated memory */ - /* this needs to be done last, so we don't free memory for variables before they're used above */ - if(free_child_process_memory == TRUE) - free_memory(&mac); - - /* parent exits immediately - grandchild process is inherited by the INIT process, so we have no zombie problem... */ - _exit(STATE_OK); - } - - /* else the parent should wait for the first child to return... */ - else if(pid > 0) { - clear_volatile_macros_r(&mac); - - log_debug_info(DEBUGL_CHECKS, 2, "Service check is executing in child process (pid=%lu)\n", (unsigned long)pid); - - /* parent should close output file */ - if(check_result_info.output_file_fp) - fclose(check_result_info.output_file_fp); - - /* should this be done in first child process (after spawning grandchild) as well? */ - /* free memory allocated for IPC functionality */ - free_check_result(&check_result_info); - - /* free memory */ - my_free(processed_command); - - /* wait for the first child to return */ - /* don't do this if large install tweaks are enabled - we'll clean up children in event loop */ - if(child_processes_fork_twice == TRUE) - wait_result = waitpid(pid, NULL, 0); - } - - /* see if we were able to run the check... */ - if(fork_error == TRUE) - return ERROR; - - return OK; + /* paw off the check to a worker to run */ + runchk_result = wproc_run_check(cr, processed_command, &mac); + if (runchk_result == ERROR) { + logit(NSLOG_RUNTIME_ERROR, TRUE, "Unable to run check for service '%s' on host '%s'\n", svc->description, svc->host_name); + } + else { + /* do the book-keeping */ + currently_running_service_checks++; + svc->is_executing = TRUE; + update_check_stats((scheduled_check == TRUE) ? ACTIVE_SCHEDULED_SERVICE_CHECK_STATS : ACTIVE_ONDEMAND_SERVICE_CHECK_STATS, start_time.tv_sec); } + /* free memory */ + my_free(processed_command); + clear_volatile_macros_r(&mac); + + return runchk_result; + } + + +static int get_service_check_return_code(service *temp_service, + check_result *queued_check_result) { + + int rc; + char *temp_plugin_output = NULL; + + log_debug_info(DEBUGL_FUNCTIONS, 0, "get_service_check_return_code()\n"); + + if(NULL == temp_service || NULL == queued_check_result) { + return STATE_UNKNOWN; + } + + /* grab the return code */ + rc = queued_check_result->return_code; + + /* adjust return code (active checks only) */ + if(queued_check_result->check_type == CHECK_TYPE_ACTIVE) { + if(queued_check_result->early_timeout == TRUE) { + logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Check of service '%s' on host '%s' timed out after %.3fs!\n", temp_service->description, temp_service->host_name, temp_service->execution_time); + my_free(temp_service->plugin_output); + my_free(temp_service->long_plugin_output); + my_free(temp_service->perf_data); + asprintf(&temp_service->plugin_output, "(Service check timed out after %.2lf seconds)", temp_service->execution_time); + rc = service_check_timeout_state; + } + /* if there was some error running the command, just skip it (this shouldn't be happening) */ + else if(queued_check_result->exited_ok == FALSE) { + + logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Check of service '%s' on host '%s' did not exit properly!\n", temp_service->description, temp_service->host_name); + + my_free(temp_service->plugin_output); + my_free(temp_service->long_plugin_output); + my_free(temp_service->perf_data); + + temp_service->plugin_output = (char *)strdup("(Service check did not exit properly)"); + + rc = STATE_CRITICAL; + } + + /* make sure the return code is within bounds */ + else if(queued_check_result->return_code < 0 || queued_check_result->return_code > 3) { + + logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Return code of %d for check of service '%s' on host '%s' was out of bounds.%s\n", queued_check_result->return_code, temp_service->description, temp_service->host_name, (queued_check_result->return_code == 126 ? "Make sure the plugin you're trying to run is executable." : (queued_check_result->return_code == 127 ? " Make sure the plugin you're trying to run actually exists." : ""))); + + asprintf(&temp_plugin_output, "(Return code of %d is out of bounds%s : %s)", queued_check_result->return_code, (queued_check_result->return_code == 126 ? " - plugin may not be executable" : (queued_check_result->return_code == 127 ? " - plugin may be missing" : "")), temp_service->plugin_output); + my_free(temp_service->plugin_output); + + asprintf(&temp_service->plugin_output, "%s)", temp_plugin_output); + my_free(temp_plugin_output); + my_free(temp_service->long_plugin_output); + my_free(temp_service->perf_data); + + rc = STATE_CRITICAL; + } + } + + return rc; + } /* handles asynchronous service check results */ @@ -907,13 +399,9 @@ int handle_async_service_check_result(service *temp_service, check_result *queue char *temp_plugin_output = NULL; char *temp_ptr = NULL; servicedependency *temp_dependency = NULL; - objectlist *check_servicelist = NULL; - objectlist *servicelist_item = NULL; service *master_service = NULL; - int run_async_check = TRUE; int state_changes_use_cached_state = TRUE; /* TODO - 09/23/07 move this to a global variable */ int flapping_check_done = FALSE; - void *ptr = NULL; log_debug_info(DEBUGL_FUNCTIONS, 0, "handle_async_service_check_result()\n"); @@ -925,20 +413,25 @@ int handle_async_service_check_result(service *temp_service, check_result *queue /* get the current time */ time(¤t_time); - log_debug_info(DEBUGL_CHECKS, 0, "** Handling check result for service '%s' on host '%s'...\n", temp_service->description, temp_service->host_name); - log_debug_info(DEBUGL_CHECKS, 1, "HOST: %s, SERVICE: %s, CHECK TYPE: %s, OPTIONS: %d, SCHEDULED: %s, RESCHEDULE: %s, EXITED OK: %s, RETURN CODE: %d, OUTPUT: %s\n", temp_service->host_name, temp_service->description, (queued_check_result->check_type == SERVICE_CHECK_ACTIVE) ? "Active" : "Passive", queued_check_result->check_options, (queued_check_result->scheduled_check == TRUE) ? "Yes" : "No", (queued_check_result->reschedule_check == TRUE) ? "Yes" : "No", (queued_check_result->exited_ok == TRUE) ? "Yes" : "No", queued_check_result->return_code, queued_check_result->output); + if (current_time < temp_service->next_check) + next_service_check = temp_service->next_check + check_window(temp_service); + else + next_service_check = current_time + check_window(temp_service); + + log_debug_info(DEBUGL_CHECKS, 0, "** Handling check result for service '%s' on host '%s' from '%s'...\n", temp_service->description, temp_service->host_name, check_result_source(queued_check_result)); + log_debug_info(DEBUGL_CHECKS, 1, "HOST: %s, SERVICE: %s, CHECK TYPE: %s, OPTIONS: %d, SCHEDULED: %s, RESCHEDULE: %s, EXITED OK: %s, RETURN CODE: %d, OUTPUT: %s\n", temp_service->host_name, temp_service->description, (queued_check_result->check_type == CHECK_TYPE_ACTIVE) ? "Active" : "Passive", queued_check_result->check_options, (queued_check_result->scheduled_check == TRUE) ? "Yes" : "No", (queued_check_result->reschedule_check == TRUE) ? "Yes" : "No", (queued_check_result->exited_ok == TRUE) ? "Yes" : "No", queued_check_result->return_code, queued_check_result->output); /* decrement the number of service checks still out there... */ - if(queued_check_result->check_type == SERVICE_CHECK_ACTIVE && currently_running_service_checks > 0) + if(queued_check_result->check_type == CHECK_TYPE_ACTIVE && currently_running_service_checks > 0) currently_running_service_checks--; /* skip this service check results if its passive and we aren't accepting passive check results */ - if(queued_check_result->check_type == SERVICE_CHECK_PASSIVE) { + if(queued_check_result->check_type == CHECK_TYPE_PASSIVE) { if(accept_passive_service_checks == FALSE) { log_debug_info(DEBUGL_CHECKS, 0, "Discarding passive service check result because passive service checks are disabled globally.\n"); return ERROR; } - if(temp_service->accept_passive_service_checks == FALSE) { + if(temp_service->accept_passive_checks == FALSE) { log_debug_info(DEBUGL_CHECKS, 0, "Discarding passive service check result because passive checks are disabled for this service.\n"); return ERROR; } @@ -949,7 +442,7 @@ int handle_async_service_check_result(service *temp_service, check_result *queue temp_service->is_being_freshened = FALSE; /* clear the execution flag if this was an active check */ - if(queued_check_result->check_type == SERVICE_CHECK_ACTIVE) + if(queued_check_result->check_type == CHECK_TYPE_ACTIVE) temp_service->is_executing = FALSE; /* DISCARD INVALID FRESHNESS CHECK RESULTS */ @@ -973,10 +466,10 @@ int handle_async_service_check_result(service *temp_service, check_result *queue temp_service->last_check = queued_check_result->start_time.tv_sec; /* was this check passive or active? */ - temp_service->check_type = (queued_check_result->check_type == SERVICE_CHECK_ACTIVE) ? SERVICE_CHECK_ACTIVE : SERVICE_CHECK_PASSIVE; + temp_service->check_type = (queued_check_result->check_type == CHECK_TYPE_ACTIVE) ? CHECK_TYPE_ACTIVE : CHECK_TYPE_PASSIVE; /* update check statistics for passive checks */ - if(queued_check_result->check_type == SERVICE_CHECK_PASSIVE) + if(queued_check_result->check_type == CHECK_TYPE_PASSIVE) update_check_stats(PASSIVE_SERVICE_CHECK_STATS, queued_check_result->start_time.tv_sec); /* should we reschedule the next service check? NOTE: This may be overridden later... */ @@ -994,56 +487,30 @@ int handle_async_service_check_result(service *temp_service, check_result *queue my_free(temp_service->long_plugin_output); my_free(temp_service->perf_data); - /* if there was some error running the command, just skip it (this shouldn't be happening) */ - if(queued_check_result->exited_ok == FALSE) { + /* parse check output to get: (1) short output, (2) long output, (3) perf data */ + parse_check_output(queued_check_result->output, &temp_service->plugin_output, &temp_service->long_plugin_output, &temp_service->perf_data, TRUE, FALSE); - logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Check of service '%s' on host '%s' did not exit properly!\n", temp_service->description, temp_service->host_name); + /* make sure the plugin output isn't null */ + if(temp_service->plugin_output == NULL) + temp_service->plugin_output = (char *)strdup("(No output returned from plugin)"); - temp_service->plugin_output = (char *)strdup("(Service check did not exit properly)"); - - temp_service->current_state = STATE_CRITICAL; + /* replace semicolons in plugin output (but not performance data) with colons */ + else if((temp_ptr = temp_service->plugin_output)) { + while((temp_ptr = strchr(temp_ptr, ';'))) + * temp_ptr = ':'; } - /* make sure the return code is within bounds */ - else if(queued_check_result->return_code < 0 || queued_check_result->return_code > 3) { + /* grab the return code */ + temp_service->current_state = get_service_check_return_code(temp_service, + queued_check_result); - logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Return code of %d for check of service '%s' on host '%s' was out of bounds.%s\n", queued_check_result->return_code, temp_service->description, temp_service->host_name, (queued_check_result->return_code == 126 ? "Make sure the plugin you're trying to run is executable." : (queued_check_result->return_code == 127 ? " Make sure the plugin you're trying to run actually exists." : ""))); + log_debug_info(DEBUGL_CHECKS, 2, "Parsing check output...\n"); + log_debug_info(DEBUGL_CHECKS, 2, "Short Output: %s\n", (temp_service->plugin_output == NULL) ? "NULL" : temp_service->plugin_output); + log_debug_info(DEBUGL_CHECKS, 2, "Long Output: %s\n", (temp_service->long_plugin_output == NULL) ? "NULL" : temp_service->long_plugin_output); + log_debug_info(DEBUGL_CHECKS, 2, "Perf Data: %s\n", (temp_service->perf_data == NULL) ? "NULL" : temp_service->perf_data); - asprintf(&temp_plugin_output, "\x73\x6f\x69\x67\x61\x6e\x20\x74\x68\x67\x69\x72\x79\x70\x6f\x63\x20\x6e\x61\x68\x74\x65\x20\x64\x61\x74\x73\x6c\x61\x67"); - my_free(temp_plugin_output); - asprintf(&temp_service->plugin_output, "(Return code of %d is out of bounds%s)", queued_check_result->return_code, (queued_check_result->return_code == 126 ? " - plugin may not be executable" : (queued_check_result->return_code == 127 ? " - plugin may be missing" : ""))); - - temp_service->current_state = STATE_CRITICAL; - } - - /* else the return code is okay... */ - else { - - /* parse check output to get: (1) short output, (2) long output, (3) perf data */ - parse_check_output(queued_check_result->output, &temp_service->plugin_output, &temp_service->long_plugin_output, &temp_service->perf_data, TRUE, TRUE); - - /* make sure the plugin output isn't null */ - if(temp_service->plugin_output == NULL) - temp_service->plugin_output = (char *)strdup("(No output returned from plugin)"); - - /* replace semicolons in plugin output (but not performance data) with colons */ - else if((temp_ptr = temp_service->plugin_output)) { - while((temp_ptr = strchr(temp_ptr, ';'))) - * temp_ptr = ':'; - } - - log_debug_info(DEBUGL_CHECKS, 2, "Parsing check output...\n"); - log_debug_info(DEBUGL_CHECKS, 2, "Short Output: %s\n", (temp_service->plugin_output == NULL) ? "NULL" : temp_service->plugin_output); - log_debug_info(DEBUGL_CHECKS, 2, "Long Output: %s\n", (temp_service->long_plugin_output == NULL) ? "NULL" : temp_service->long_plugin_output); - log_debug_info(DEBUGL_CHECKS, 2, "Perf Data: %s\n", (temp_service->perf_data == NULL) ? "NULL" : temp_service->perf_data); - - /* grab the return code */ - temp_service->current_state = queued_check_result->return_code; - } - - - /* record the last state time */ - switch(temp_service->current_state) { + /* record the time the last state ended */ + switch(temp_service->last_state) { case STATE_OK: temp_service->last_time_ok = temp_service->last_check; break; @@ -1061,7 +528,7 @@ int handle_async_service_check_result(service *temp_service, check_result *queue } /* log passive checks - we need to do this here, as some my bypass external commands by getting dropped in checkresults dir */ - if(temp_service->check_type == SERVICE_CHECK_PASSIVE) { + if(temp_service->check_type == CHECK_TYPE_PASSIVE) { if(log_passive_checks == TRUE) logit(NSLOG_PASSIVE_CHECK, FALSE, "PASSIVE SERVICE CHECK: %s;%s;%d;%s\n", temp_service->host_name, temp_service->description, temp_service->current_state, temp_service->plugin_output); } @@ -1078,19 +545,11 @@ int handle_async_service_check_result(service *temp_service, check_result *queue /* set a flag to remember that we launched a check */ first_host_check_initiated = TRUE; - - /* 08/04/07 EG launch an async (parallel) host check unless aggressive host checking is enabled */ - /* previous logic was to simply run a sync (serial) host check */ - /* do NOT allow cached check results to happen here - we need the host to be checked for real... */ - if(use_aggressive_host_checking == TRUE) - perform_on_demand_host_check(temp_host, NULL, CHECK_OPTION_NONE, FALSE, 0L); - else - run_async_host_check_3x(temp_host, CHECK_OPTION_NONE, 0.0, FALSE, FALSE, NULL, NULL); + schedule_host_check(temp_host, current_time, CHECK_OPTION_DEPENDENCY_CHECK); } } - /**** NOTE - THIS WAS MOVED UP FROM LINE 1049 BELOW TO FIX PROBLEMS WHERE CURRENT ATTEMPT VALUE WAS ACTUALLY "LEADING" REAL VALUE ****/ /* increment the current attempt number if this is a soft state (service was rechecked) */ if(temp_service->state_type == SOFT_STATE && (temp_service->current_attempt < temp_service->max_attempts)) temp_service->current_attempt = temp_service->current_attempt + 1; @@ -1149,9 +608,10 @@ int handle_async_service_check_result(service *temp_service, check_result *queue delete_service_acknowledgement_comments(temp_service); } - /* do NOT reset current notification number!!! */ - /* hard changes between non-OK states should continue to be escalated, so don't reset current notification number */ - /*temp_service->current_notification_number=0;*/ + /* + * hard changes between non-OK states should continue + * to be escalated, so don't reset current notification number + */ } /* initialize the last host and service state change times if necessary */ @@ -1181,7 +641,6 @@ int handle_async_service_check_result(service *temp_service, check_result *queue /* update the problem id when transitioning to a problem state */ if(temp_service->last_state == STATE_OK) { /* don't reset last problem id, or it will be zero the next time a problem is encountered */ - /* temp_service->last_problem_id=temp_service->current_problem_id;*/ temp_service->current_problem_id = next_problem_id; next_problem_id++; } @@ -1212,12 +671,7 @@ int handle_async_service_check_result(service *temp_service, check_result *queue log_debug_info(DEBUGL_CHECKS, 1, "Host is NOT UP, so we'll check it to see if it recovered...\n"); - /* 08/04/07 EG launch an async (parallel) host check (possibly cached) unless aggressive host checking is enabled */ - /* previous logic was to simply run a sync (serial) host check */ - if(use_aggressive_host_checking == TRUE) - perform_on_demand_host_check(temp_host, NULL, CHECK_OPTION_NONE, TRUE, cached_host_check_horizon); - /* 09/23/07 EG don't launch a new host check if we already did so earlier */ - else if(first_host_check_initiated == TRUE) + if(first_host_check_initiated == TRUE) log_debug_info(DEBUGL_CHECKS, 1, "First host check was already initiated, so we'll skip a new host check.\n"); else { /* can we use the last cached host state? */ @@ -1230,7 +684,7 @@ int handle_async_service_check_result(service *temp_service, check_result *queue /* else launch an async (parallel) check of the host */ else - run_async_host_check_3x(temp_host, CHECK_OPTION_NONE, 0.0, FALSE, FALSE, NULL, NULL); + schedule_host_check(temp_host, current_time, CHECK_OPTION_DEPENDENCY_CHECK); } } @@ -1294,10 +748,7 @@ int handle_async_service_check_result(service *temp_service, check_result *queue temp_service->current_notification_number = 0; temp_service->problem_has_been_acknowledged = FALSE; temp_service->acknowledgement_type = ACKNOWLEDGEMENT_NONE; - temp_service->notified_on_unknown = FALSE; - temp_service->notified_on_warning = FALSE; - temp_service->notified_on_critical = FALSE; - temp_service->no_more_notifications = FALSE; + temp_service->notified_on = 0; if(reschedule_check == TRUE) next_service_check = (time_t)(temp_service->last_check + (temp_service->check_interval * interval_length)); @@ -1318,69 +769,33 @@ int handle_async_service_check_result(service *temp_service, check_result *queue log_debug_info(DEBUGL_CHECKS, 1, "Host is currently UP, so we'll recheck its state to make sure...\n"); - /* 08/04/07 EG launch an async (parallel) host check (possibly cached) unless aggressive host checking is enabled */ - /* previous logic was to simply run a sync (serial) host check */ - if(use_aggressive_host_checking == TRUE) - perform_on_demand_host_check(temp_host, &route_result, CHECK_OPTION_NONE, TRUE, cached_host_check_horizon); + /* only run a new check if we can and have to */ + if(execute_host_checks && (state_change == TRUE && state_changes_use_cached_state == FALSE) && temp_host->last_check + cached_host_check_horizon < current_time) { + schedule_host_check(temp_host, current_time, CHECK_OPTION_DEPENDENCY_CHECK); + } else { - /* can we use the last cached host state? */ - /* only use cached host state if no service state change has occurred */ - if((state_change == FALSE || state_changes_use_cached_state == TRUE) && temp_host->has_been_checked == TRUE && ((current_time - temp_host->last_check) <= cached_host_check_horizon)) { - /* use current host state as route result */ - route_result = temp_host->current_state; - log_debug_info(DEBUGL_CHECKS, 1, "* Using cached host state: %d\n", temp_host->current_state); - update_check_stats(ACTIVE_ONDEMAND_HOST_CHECK_STATS, current_time); - update_check_stats(ACTIVE_CACHED_HOST_CHECK_STATS, current_time); - } - - /* else launch an async (parallel) check of the host */ - /* CHANGED 02/15/08 only if service changed state since service was last checked */ - else if(state_change == TRUE) { - /* use current host state as route result */ - route_result = temp_host->current_state; - run_async_host_check_3x(temp_host, CHECK_OPTION_NONE, 0.0, FALSE, FALSE, NULL, NULL); - } - - /* ADDED 02/15/08 */ - /* else assume same host state */ - else { - route_result = temp_host->current_state; - log_debug_info(DEBUGL_CHECKS, 1, "* Using last known host state: %d\n", temp_host->current_state); - update_check_stats(ACTIVE_ONDEMAND_HOST_CHECK_STATS, current_time); - update_check_stats(ACTIVE_CACHED_HOST_CHECK_STATS, current_time); - } + log_debug_info(DEBUGL_CHECKS, 1, "* Using cached host state: %d\n", temp_host->current_state); + route_result = temp_host->current_state; + update_check_stats(ACTIVE_ONDEMAND_HOST_CHECK_STATS, current_time); + update_check_stats(ACTIVE_CACHED_HOST_CHECK_STATS, current_time); } } /* else the host is either down or unreachable, so recheck it if necessary */ else { - log_debug_info(DEBUGL_CHECKS, 1, "Host is currently DOWN/UNREACHABLE.\n"); + log_debug_info(DEBUGL_CHECKS, 1, "Host is currently %s.\n", host_state_name(temp_host->current_state)); - /* we're using aggressive host checking, so really do recheck the host... */ - if(use_aggressive_host_checking == TRUE) { - log_debug_info(DEBUGL_CHECKS, 1, "Agressive host checking is enabled, so we'll recheck the host state...\n"); - perform_on_demand_host_check(temp_host, &route_result, CHECK_OPTION_NONE, TRUE, cached_host_check_horizon); + if(execute_host_checks && (state_change == TRUE && state_changes_use_cached_state == FALSE)) { + schedule_host_check(temp_host, current_time, CHECK_OPTION_NONE); } - - /* the service wobbled between non-OK states, so check the host... */ - else if((state_change == TRUE && state_changes_use_cached_state == FALSE) && temp_service->last_hard_state != STATE_OK) { - log_debug_info(DEBUGL_CHECKS, 1, "Service wobbled between non-OK states, so we'll recheck the host state...\n"); - /* 08/04/07 EG launch an async (parallel) host check unless aggressive host checking is enabled */ - /* previous logic was to simply run a sync (serial) host check */ - /* use current host state as route result */ - route_result = temp_host->current_state; - run_async_host_check_3x(temp_host, CHECK_OPTION_NONE, 0.0, FALSE, FALSE, NULL, NULL); - /*perform_on_demand_host_check(temp_host,&route_result,CHECK_OPTION_NONE,TRUE,cached_host_check_horizon);*/ - } - /* else fake the host check, but (possibly) resend host notifications to contacts... */ else { log_debug_info(DEBUGL_CHECKS, 1, "Assuming host is in same state as before...\n"); /* if the host has never been checked before, set the checked flag and last check time */ - /* 03/11/06 EG Note: This probably never evaluates to FALSE, present for historical reasons only, can probably be removed in the future */ + /* This probably never evaluates to FALSE, present for historical reasons only, can probably be removed in the future */ if(temp_host->has_been_checked == FALSE) { temp_host->has_been_checked = TRUE; temp_host->last_check = temp_service->last_check; @@ -1395,32 +810,28 @@ int handle_async_service_check_result(service *temp_service, check_result *queue } /* if the host is down or unreachable ... */ - /* 05/29/2007 NOTE: The host might be in a SOFT problem state due to host check retries/caching. Not sure if we should take that into account and do something different or not... */ if(route_result != HOST_UP) { + if (temp_host->state_type == HARD_STATE) { + log_debug_info(DEBUGL_CHECKS, 2, "Host is not UP, so we mark state changes if appropriate\n"); - log_debug_info(DEBUGL_CHECKS, 2, "Host is not UP, so we mark state changes if appropriate\n"); + /* "fake" a hard state change for the service - well, its not really fake, but it didn't get caught earlier... */ + if(temp_service->last_hard_state != temp_service->current_state) + hard_state_change = TRUE; - /* "fake" a hard state change for the service - well, its not really fake, but it didn't get caught earlier... */ - if(temp_service->last_hard_state != temp_service->current_state) - hard_state_change = TRUE; + /* update last state change times */ + if(state_change == TRUE || hard_state_change == TRUE) + temp_service->last_state_change = temp_service->last_check; + if(hard_state_change == TRUE) { + temp_service->last_hard_state_change = temp_service->last_check; + temp_service->state_type = HARD_STATE; + temp_service->last_hard_state = temp_service->current_state; + } - /* update last state change times */ - if(state_change == TRUE || hard_state_change == TRUE) - temp_service->last_state_change = temp_service->last_check; - if(hard_state_change == TRUE) { - temp_service->last_hard_state_change = temp_service->last_check; - temp_service->state_type = HARD_STATE; - temp_service->last_hard_state = temp_service->current_state; + /* put service into a hard state without attempting check retries and don't send out notifications about it */ + temp_service->host_problem_at_last_check = TRUE; } - - /* put service into a hard state without attempting check retries and don't send out notifications about it */ - temp_service->host_problem_at_last_check = TRUE; - /* Below removed 08/04/2010 EG - http://tracker.nagios.org/view.php?id=128 */ - /* - temp_service->state_type=HARD_STATE; - temp_service->last_hard_state=temp_service->current_state; - temp_service->current_attempt=1; - */ + else if (temp_service->last_state == STATE_OK) + temp_service->state_type = SOFT_STATE; } /* the host is up - it recovered since the last time the service was checked... */ @@ -1441,7 +852,7 @@ int handle_async_service_check_result(service *temp_service, check_result *queue log_debug_info(DEBUGL_CHECKS, 1, "Current/Max Attempt(s): %d/%d\n", temp_service->current_attempt, temp_service->max_attempts); - /* if we should retry the service check, do so (except it the host is down or unreachable!) */ + /* if we should retry the service check, do so (except if the host is down or unreachable!) */ if(temp_service->current_attempt < temp_service->max_attempts) { /* the host is down or unreachable, so don't attempt to retry the service check */ @@ -1483,17 +894,27 @@ int handle_async_service_check_result(service *temp_service, check_result *queue } /* perform dependency checks on the second to last check of the service */ - if(enable_predictive_service_dependency_checks == TRUE && temp_service->current_attempt == (temp_service->max_attempts - 1)) { + if(execute_service_checks && enable_predictive_service_dependency_checks == TRUE && temp_service->current_attempt == (temp_service->max_attempts - 1)) { + objectlist *list; log_debug_info(DEBUGL_CHECKS, 1, "Looking for services to check for predictive dependency checks...\n"); /* check services that THIS ONE depends on for notification AND execution */ /* we do this because we might be sending out a notification soon and we want the dependency logic to be accurate */ - for(temp_dependency = get_first_servicedependency_by_dependent_service(temp_service->host_name, temp_service->description, &ptr); temp_dependency != NULL; temp_dependency = get_next_servicedependency_by_dependent_service(temp_service->host_name, temp_service->description, &ptr)) { + for(list = temp_service->exec_deps; list; list = list->next) { + temp_dependency = (servicedependency *)list->object_ptr; if(temp_dependency->dependent_service_ptr == temp_service && temp_dependency->master_service_ptr != NULL) { master_service = (service *)temp_dependency->master_service_ptr; log_debug_info(DEBUGL_CHECKS, 2, "Predictive check of service '%s' on host '%s' queued.\n", master_service->description, master_service->host_name); - add_object_to_objectlist(&check_servicelist, (void *)master_service); + schedule_service_check(master_service, current_time, CHECK_OPTION_DEPENDENCY_CHECK); + } + } + for(list = temp_service->notify_deps; list; list = list->next) { + temp_dependency = (servicedependency *)list->object_ptr; + if(temp_dependency->dependent_service_ptr == temp_service && temp_dependency->master_service_ptr != NULL) { + master_service = (service *)temp_dependency->master_service_ptr; + log_debug_info(DEBUGL_CHECKS, 2, "Predictive check of service '%s' on host '%s' queued.\n", master_service->description, master_service->host_name); + schedule_service_check(master_service, current_time, CHECK_OPTION_DEPENDENCY_CHECK); } } } @@ -1508,6 +929,11 @@ int handle_async_service_check_result(service *temp_service, check_result *queue /* this is a hard state */ temp_service->state_type = HARD_STATE; + /* check for start of flexible (non-fixed) scheduled downtime if we just had a hard error */ + /* we need to check for both, state_change (SOFT) and hard_state_change (HARD) values */ + if((hard_state_change == TRUE || state_change == TRUE) && temp_service->pending_flex_downtime > 0) + check_pending_flex_service_downtime(temp_service); + /* if we've hard a hard state change... */ if(hard_state_change == TRUE) { @@ -1522,11 +948,6 @@ int handle_async_service_check_result(service *temp_service, check_result *queue state_was_logged = TRUE; } - /* check for start of flexible (non-fixed) scheduled downtime if we just had a hard error */ - /* we need to check for both, state_change (SOFT) and hard_state_change (HARD) values */ - if((hard_state_change == TRUE || state_change == TRUE) && temp_service->pending_flex_downtime > 0) - check_pending_flex_service_downtime(temp_service); - /* 10/04/07 check to see if the service and/or associate host is flapping */ /* this should be done before a notification is sent out to ensure the host didn't just start flapping */ check_for_service_flapping(temp_service, TRUE, TRUE); @@ -1573,6 +994,14 @@ int handle_async_service_check_result(service *temp_service, check_result *queue preferred_time = temp_service->next_check; get_next_valid_time(preferred_time, &next_valid_time, temp_service->check_period_ptr); temp_service->next_check = next_valid_time; + if(next_valid_time > preferred_time) { + /* Next valid time is further in the future because of timeperiod + * constraints. Add a random amount so we don't get all checks + * subject to that timeperiod constraint scheduled at the same time + */ + temp_service->next_check += + ranged_urand(0, check_window(temp_service)); + } /* services with non-recurring intervals do not get rescheduled */ if(temp_service->check_interval == 0) @@ -1590,22 +1019,14 @@ int handle_async_service_check_result(service *temp_service, check_result *queue /* if we're stalking this state type and state was not already logged AND the plugin output changed since last check, log it now.. */ if(temp_service->state_type == HARD_STATE && state_change == FALSE && state_was_logged == FALSE && compare_strings(old_plugin_output, temp_service->plugin_output)) { - if((temp_service->current_state == STATE_OK && temp_service->stalk_on_ok == TRUE)) + if(should_stalk(temp_service)) log_service_event(temp_service); - else if((temp_service->current_state == STATE_WARNING && temp_service->stalk_on_warning == TRUE)) - log_service_event(temp_service); - - else if((temp_service->current_state == STATE_UNKNOWN && temp_service->stalk_on_unknown == TRUE)) - log_service_event(temp_service); - - else if((temp_service->current_state == STATE_CRITICAL && temp_service->stalk_on_critical == TRUE)) - log_service_event(temp_service); } #ifdef USE_EVENT_BROKER /* send data to event broker */ - broker_service_check(NEBTYPE_SERVICECHECK_PROCESSED, NEBFLAG_NONE, NEBATTR_NONE, temp_service, temp_service->check_type, queued_check_result->start_time, queued_check_result->finish_time, NULL, temp_service->latency, temp_service->execution_time, service_check_timeout, queued_check_result->early_timeout, queued_check_result->return_code, NULL, NULL); + broker_service_check(NEBTYPE_SERVICECHECK_PROCESSED, NEBFLAG_NONE, NEBATTR_NONE, temp_service, temp_service->check_type, queued_check_result->start_time, queued_check_result->finish_time, NULL, temp_service->latency, temp_service->execution_time, service_check_timeout, queued_check_result->early_timeout, queued_check_result->return_code, NULL, NULL, queued_check_result); #endif /* set the checked flag */ @@ -1627,29 +1048,6 @@ int handle_async_service_check_result(service *temp_service, check_result *queue my_free(temp_plugin_output); my_free(old_plugin_output); - - /* run async checks of all services we added above */ - /* don't run a check if one is already executing or we can get by with a cached state */ - for(servicelist_item = check_servicelist; servicelist_item != NULL; servicelist_item = servicelist_item->next) { - run_async_check = TRUE; - temp_service = (service *)servicelist_item->object_ptr; - - /* we can get by with a cached state, so don't check the service */ - if((current_time - temp_service->last_check) <= cached_service_check_horizon) { - run_async_check = FALSE; - - /* update check statistics */ - update_check_stats(ACTIVE_CACHED_SERVICE_CHECK_STATS, current_time); - } - - if(temp_service->is_executing == TRUE) - run_async_check = FALSE; - - if(run_async_check == TRUE) - run_async_service_check(temp_service, CHECK_OPTION_NONE, 0.0, FALSE, FALSE, NULL, NULL); - } - free_objectlist(&check_servicelist); - return OK; } @@ -1658,7 +1056,6 @@ int handle_async_service_check_result(service *temp_service, check_result *queue /* schedules an immediate or delayed service check */ void schedule_service_check(service *svc, time_t check_time, int options) { timed_event *temp_event = NULL; - timed_event *new_event = NULL; int use_original_event = TRUE; log_debug_info(DEBUGL_FUNCTIONS, 0, "schedule_service_check()\n"); @@ -1674,6 +1071,14 @@ void schedule_service_check(service *svc, time_t check_time, int options) { return; } + /* we may have to nudge this check a bit */ + if (options == CHECK_OPTION_DEPENDENCY_CHECK) { + if (svc->last_check + cached_service_check_horizon > check_time) { + log_debug_info(DEBUGL_CHECKS, 0, "Last check result is recent enough (%s)", ctime(&svc->last_check)); + return; + } + } + /* default is to use the new event */ use_original_event = FALSE; @@ -1724,39 +1129,39 @@ void schedule_service_check(service *svc, time_t check_time, int options) { /* schedule a new event */ if(use_original_event == FALSE) { - - /* allocate memory for a new event item */ - new_event = (timed_event *)malloc(sizeof(timed_event)); - if(new_event == NULL) { - logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Could not reschedule check of service '%s' on host '%s'!\n", svc->description, svc->host_name); - return; - } - - /* make sure we kill off the old event */ + /* make sure we remove the old event from the queue */ if(temp_event) { - remove_event(temp_event, &event_list_low, &event_list_low_tail); - my_free(temp_event); + remove_event(nagios_squeue, temp_event); } + else { + /* allocate memory for a new event item */ + temp_event = (timed_event *)calloc(1, sizeof(timed_event)); + if(temp_event == NULL) { + logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Could not reschedule check of service '%s' on host '%s'!\n", svc->description, svc->host_name); + return; + } + } + log_debug_info(DEBUGL_CHECKS, 2, "Scheduling new service check event.\n"); /* set the next service check event and time */ - svc->next_check_event = new_event; + svc->next_check_event = temp_event; svc->next_check = check_time; /* save check options for retention purposes */ svc->check_options = options; /* place the new event in the event queue */ - new_event->event_type = EVENT_SERVICE_CHECK; - new_event->event_data = (void *)svc; - new_event->event_args = (void *)NULL; - new_event->event_options = options; - new_event->run_time = svc->next_check; - new_event->recurring = FALSE; - new_event->event_interval = 0L; - new_event->timing_func = NULL; - new_event->compensate_for_time_change = TRUE; - reschedule_event(new_event, &event_list_low, &event_list_low_tail); + temp_event->event_type = EVENT_SERVICE_CHECK; + temp_event->event_data = (void *)svc; + temp_event->event_args = (void *)NULL; + temp_event->event_options = options; + temp_event->run_time = svc->next_check; + temp_event->recurring = FALSE; + temp_event->event_interval = 0L; + temp_event->timing_func = NULL; + temp_event->compensate_for_time_change = TRUE; + add_event(nagios_squeue, temp_event); } else { @@ -1783,6 +1188,7 @@ int check_service_check_viability(service *svc, int check_options, int *time_is_ time_t current_time = 0L; time_t preferred_time = 0L; int check_interval = 0; + host *temp_host = NULL; log_debug_info(DEBUGL_FUNCTIONS, 0, "check_service_check_viability()\n"); @@ -1832,6 +1238,26 @@ int check_service_check_viability(service *svc, int check_options, int *time_is_ } } + /* check if parent service is OK */ + if(check_service_parents(svc) == DEPENDENCIES_FAILED) { + preferred_time = current_time + check_interval; + perform_check = FALSE; + log_debug_info(DEBUGL_CHECKS, 2, "Execution parents for this service failed, so it will not be actively checked.\n"); + } + + /* check if host is up - if not, do not perform check */ + if(host_down_disable_service_checks) { + if((temp_host = svc->host_ptr) == NULL) { + log_debug_info(DEBUGL_CHECKS, 2, "Host pointer NULL in check_service_check_viability().\n"); + return ERROR; + } else { + if(temp_host->current_state != HOST_UP) { + log_debug_info(DEBUGL_CHECKS, 2, "Host state not UP, so service check will not be performed - will be rescheduled as normal.\n"); + perform_check = FALSE; + } + } + } + /* pass back the next viable check time */ if(new_time) *new_time = preferred_time; @@ -1843,23 +1269,59 @@ int check_service_check_viability(service *svc, int check_options, int *time_is_ +/* checks service parents */ +int check_service_parents(service *svc) +{ + servicesmember *temp_servicesmember = NULL; + int state = STATE_OK; + + log_debug_info(DEBUGL_FUNCTIONS, 0, "check_service_parents()\n"); + + /* check all parents... */ + for(temp_servicesmember = svc->parents; temp_servicesmember; temp_servicesmember = temp_servicesmember->next) { + service *parent_service; + + /* find the service we depend on... */ + if((parent_service = temp_servicesmember->service_ptr) == NULL) { + logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: service '%s' on host '%s' is NULL ptr\n", + temp_servicesmember->service_description, temp_servicesmember->host_name); + continue; + } + + state = parent_service->last_hard_state; + + /* is the service we depend on in a state that fails the dependency tests? */ + if((state == STATE_CRITICAL) || (state == STATE_UNKNOWN)) + return DEPENDENCIES_FAILED; + + if(check_service_parents(parent_service) != DEPENDENCIES_OK) + return DEPENDENCIES_FAILED; + } + + return DEPENDENCIES_OK; +} + + + /* checks service dependencies */ int check_service_dependencies(service *svc, int dependency_type) { - servicedependency *temp_dependency = NULL; - service *temp_service = NULL; + objectlist *list; int state = STATE_OK; time_t current_time = 0L; - void *ptr = NULL; log_debug_info(DEBUGL_FUNCTIONS, 0, "check_service_dependencies()\n"); - /* check all dependencies... */ - for(temp_dependency = get_first_servicedependency_by_dependent_service(svc->host_name, svc->description, &ptr); temp_dependency != NULL; temp_dependency = get_next_servicedependency_by_dependent_service(svc->host_name, svc->description, &ptr)) { + /* only check dependencies of the desired type */ + if(dependency_type == NOTIFICATION_DEPENDENCY) + list = svc->notify_deps; + else + list = svc->exec_deps; - /* only check dependencies of the desired type (notification or execution) */ - if(temp_dependency->dependency_type != dependency_type) - continue; + /* check all dependencies of the desired type... */ + for(; list; list = list->next) { + service *temp_service; + servicedependency *temp_dependency = (servicedependency *)list->object_ptr; /* find the service we depend on... */ if((temp_service = temp_dependency->master_service_ptr) == NULL) @@ -1877,15 +1339,7 @@ int check_service_dependencies(service *svc, int dependency_type) { state = temp_service->current_state; /* is the service we depend on in state that fails the dependency tests? */ - if(state == STATE_OK && temp_dependency->fail_on_ok == TRUE) - return DEPENDENCIES_FAILED; - if(state == STATE_WARNING && temp_dependency->fail_on_warning == TRUE) - return DEPENDENCIES_FAILED; - if(state == STATE_UNKNOWN && temp_dependency->fail_on_unknown == TRUE) - return DEPENDENCIES_FAILED; - if(state == STATE_CRITICAL && temp_dependency->fail_on_critical == TRUE) - return DEPENDENCIES_FAILED; - if((state == STATE_OK && temp_service->has_been_checked == FALSE) && temp_dependency->fail_on_pending == TRUE) + if(flag_isset(temp_dependency->failure_options, 1 << state)) return DEPENDENCIES_FAILED; /* immediate dependencies ok at this point - check parent dependencies if necessary */ @@ -1926,9 +1380,12 @@ void check_for_orphaned_services(void) { if(expected_time < current_time) { /* log a warning */ - logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: The check of service '%s' on host '%s' looks like it was orphaned (results never came back). I'm scheduling an immediate check of the service...\n", temp_service->description, temp_service->host_name); + logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: The check of service '%s' on host '%s' looks like it was orphaned (results never came back; last_check=%lu; next_check=%lu). I'm scheduling an immediate check of the service...\n", temp_service->description, temp_service->host_name, temp_service->last_check, temp_service->next_check); log_debug_info(DEBUGL_CHECKS, 1, "Service '%s' on host '%s' was orphaned, so we're scheduling an immediate check...\n", temp_service->description, temp_service->host_name); + log_debug_info(DEBUGL_CHECKS, 1, " next_check=%lu (%s); last_check=%lu (%s);\n", + temp_service->next_check, ctime(&temp_service->next_check), + temp_service->last_check, ctime(&temp_service->last_check)); /* decrement the number of running service checks */ if(currently_running_service_checks > 0) @@ -1978,7 +1435,7 @@ void check_service_result_freshness(void) { continue; /* skip services that have both active and passive checks disabled */ - if(temp_service->checks_enabled == FALSE && temp_service->accept_passive_service_checks == FALSE) + if(temp_service->checks_enabled == FALSE && temp_service->accept_passive_checks == FALSE) continue; /* skip services that are already being freshened */ @@ -2084,12 +1541,13 @@ int is_service_result_fresh(service *temp_service, time_t current_time, int log_ * freshness threshold based on vast heuristical research (ie, "some * guy once told me the golden ratio is good for loads of stuff"). */ - if(temp_service->check_type == SERVICE_CHECK_PASSIVE) { - if(temp_service->last_check < event_start && - event_start - last_program_stop > freshness_threshold * 0.618) { + if (temp_service->check_type == CHECK_TYPE_PASSIVE) { + if (temp_service->last_check < event_start && + event_start - last_program_stop > freshness_threshold * 0.618) + { expiration_time = event_start + freshness_threshold; - } } + } log_debug_info(DEBUGL_CHECKS, 2, "HBC: %d, PS: %lu, ES: %lu, LC: %lu, CT: %lu, ET: %lu\n", temp_service->has_been_checked, (unsigned long)program_start, (unsigned long)event_start, (unsigned long)temp_service->last_check, (unsigned long)current_time, (unsigned long)expiration_time); /* the results for the last check of this service are stale */ @@ -2119,34 +1577,9 @@ int is_service_result_fresh(service *temp_service, time_t current_time, int log_ /*************** COMMON ROUTE/HOST CHECK FUNCTIONS ****************/ /******************************************************************/ -/* execute an on-demand check */ -int perform_on_demand_host_check(host *hst, int *check_return_code, int check_options, int use_cached_result, unsigned long check_timestamp_horizon) { - - log_debug_info(DEBUGL_FUNCTIONS, 0, "perform_on_demand_host_check()\n"); - - perform_on_demand_host_check_3x(hst, check_return_code, check_options, use_cached_result, check_timestamp_horizon); - - return OK; - } - - - -/* execute a scheduled host check using either the 2.x or 3.x logic */ -int perform_scheduled_host_check(host *hst, int check_options, double latency) { - - log_debug_info(DEBUGL_FUNCTIONS, 0, "perform_scheduled_host_check()\n"); - - run_scheduled_host_check_3x(hst, check_options, latency); - - return OK; - } - - - /* schedules an immediate or delayed host check */ void schedule_host_check(host *hst, time_t check_time, int options) { timed_event *temp_event = NULL; - timed_event *new_event = NULL; int use_original_event = TRUE; @@ -2163,6 +1596,13 @@ void schedule_host_check(host *hst, time_t check_time, int options) { return; } + if (options == CHECK_OPTION_DEPENDENCY_CHECK) { + if (hst->last_check + cached_host_check_horizon > check_time) { + log_debug_info(DEBUGL_CHECKS, 0, "Last check result is recent enough (%s)\n", ctime(&hst->last_check)); + return; + } + } + /* default is to use the new event */ use_original_event = FALSE; @@ -2216,35 +1656,34 @@ void schedule_host_check(host *hst, time_t check_time, int options) { log_debug_info(DEBUGL_CHECKS, 2, "Scheduling new host check event.\n"); - /* allocate memory for a new event item */ - if((new_event = (timed_event *)malloc(sizeof(timed_event))) == NULL) { + /* possibly allocate memory for a new event item */ + if (temp_event) { + remove_event(nagios_squeue, temp_event); + } + else if((temp_event = (timed_event *)calloc(1, sizeof(timed_event))) == NULL) { logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Could not reschedule check of host '%s'!\n", hst->name); return; } - if(temp_event) { - remove_event(temp_event, &event_list_low, &event_list_low_tail); - my_free(temp_event); - } /* set the next host check event and time */ - hst->next_check_event = new_event; + hst->next_check_event = temp_event; hst->next_check = check_time; /* save check options for retention purposes */ hst->check_options = options; /* place the new event in the event queue */ - new_event->event_type = EVENT_HOST_CHECK; - new_event->event_data = (void *)hst; - new_event->event_args = (void *)NULL; - new_event->event_options = options; - new_event->run_time = hst->next_check; - new_event->recurring = FALSE; - new_event->event_interval = 0L; - new_event->timing_func = NULL; - new_event->compensate_for_time_change = TRUE; - reschedule_event(new_event, &event_list_low, &event_list_low_tail); + temp_event->event_type = EVENT_HOST_CHECK; + temp_event->event_data = (void *)hst; + temp_event->event_args = (void *)NULL; + temp_event->event_options = options; + temp_event->run_time = hst->next_check; + temp_event->recurring = FALSE; + temp_event->event_interval = 0L; + temp_event->timing_func = NULL; + temp_event->compensate_for_time_change = TRUE; + add_event(nagios_squeue, temp_event); } else { @@ -2266,20 +1705,23 @@ void schedule_host_check(host *hst, time_t check_time, int options) { /* checks host dependencies */ int check_host_dependencies(host *hst, int dependency_type) { hostdependency *temp_dependency = NULL; + objectlist *list; host *temp_host = NULL; int state = HOST_UP; time_t current_time = 0L; - void *ptr = NULL; log_debug_info(DEBUGL_FUNCTIONS, 0, "check_host_dependencies()\n"); - /* check all dependencies... */ - for(temp_dependency = get_first_hostdependency_by_dependent_host(hst->name, &ptr); temp_dependency != NULL; temp_dependency = get_next_hostdependency_by_dependent_host(hst->name, &ptr)) { + if (dependency_type == NOTIFICATION_DEPENDENCY) { + list = hst->notify_deps; + } else { + list = hst->exec_deps; + } - /* only check dependencies of the desired type (notification or execution) */ - if(temp_dependency->dependency_type != dependency_type) - continue; + /* check all dependencies... */ + for(; list; list = list->next) { + temp_dependency = (hostdependency *)list->object_ptr; /* find the host we depend on... */ if((temp_host = temp_dependency->master_host_ptr) == NULL) @@ -2297,13 +1739,7 @@ int check_host_dependencies(host *hst, int dependency_type) { state = temp_host->current_state; /* is the host we depend on in state that fails the dependency tests? */ - if(state == HOST_UP && temp_dependency->fail_on_up == TRUE) - return DEPENDENCIES_FAILED; - if(state == HOST_DOWN && temp_dependency->fail_on_down == TRUE) - return DEPENDENCIES_FAILED; - if(state == HOST_UNREACHABLE && temp_dependency->fail_on_unreachable == TRUE) - return DEPENDENCIES_FAILED; - if((state == HOST_UP && temp_host->has_been_checked == FALSE) && temp_dependency->fail_on_pending == TRUE) + if(flag_isset(temp_dependency->failure_options, 1 << state)) return DEPENDENCIES_FAILED; /* immediate dependencies ok at this point - check parent dependencies if necessary */ @@ -2396,7 +1832,7 @@ void check_host_result_freshness(void) { continue; /* skip hosts that have both active and passive checks disabled */ - if(temp_host->checks_enabled == FALSE && temp_host->accept_passive_host_checks == FALSE) + if(temp_host->checks_enabled == FALSE && temp_host->accept_passive_checks == FALSE) continue; /* skip hosts that are currently executing (problems here will be caught by orphaned host check) */ @@ -2494,12 +1930,13 @@ int is_host_result_fresh(host *temp_host, time_t current_time, int log_this) { * freshness threshold based on vast heuristical research (ie, "some * guy once told me the golden ratio is good for loads of stuff"). */ - if(temp_host->check_type == HOST_CHECK_PASSIVE) { - if(temp_host->last_check < event_start && - event_start - last_program_stop > freshness_threshold * 0.618) { + if (temp_host->check_type == CHECK_TYPE_PASSIVE) { + if (temp_host->last_check < event_start && + event_start - last_program_stop > freshness_threshold * 0.618) + { expiration_time = event_start + freshness_threshold; - } } + } log_debug_info(DEBUGL_CHECKS, 2, "HBC: %d, PS: %lu, ES: %lu, LC: %lu, CT: %lu, ET: %lu\n", temp_host->has_been_checked, (unsigned long)program_start, (unsigned long)event_start, (unsigned long)temp_host->last_check, (unsigned long)current_time, (unsigned long)expiration_time); @@ -2524,316 +1961,8 @@ int is_host_result_fresh(host *temp_host, time_t current_time, int log_this) { } - -/******************************************************************/ -/************* NAGIOS 3.X ROUTE/HOST CHECK FUNCTIONS **************/ -/******************************************************************/ - - -/*** ON-DEMAND HOST CHECKS USE THIS FUNCTION ***/ -/* check to see if we can reach the host */ -int perform_on_demand_host_check_3x(host *hst, int *check_result_code, int check_options, int use_cached_result, unsigned long check_timestamp_horizon) { - int result = OK; - - log_debug_info(DEBUGL_FUNCTIONS, 0, "perform_on_demand_host_check_3x()\n"); - - /* make sure we have a host */ - if(hst == NULL) - return ERROR; - - log_debug_info(DEBUGL_CHECKS, 0, "** On-demand check for host '%s'...\n", hst->name); - - /* check the status of the host */ - result = run_sync_host_check_3x(hst, check_result_code, check_options, use_cached_result, check_timestamp_horizon); - - return result; - } - - - -/* perform a synchronous check of a host */ -/* on-demand host checks will use this... */ -int run_sync_host_check_3x(host *hst, int *check_result_code, int check_options, int use_cached_result, unsigned long check_timestamp_horizon) { - int result = OK; - time_t current_time = 0L; - int host_result = HOST_UP; - char *old_plugin_output = NULL; - struct timeval start_time; - struct timeval end_time; - - - log_debug_info(DEBUGL_FUNCTIONS, 0, "run_sync_host_check_3x()\n"); - - /* make sure we have a host */ - if(hst == NULL) - return ERROR; - - log_debug_info(DEBUGL_CHECKS, 0, "** Run sync check of host '%s'...\n", hst->name); - - /* is the host check viable at this time? */ - /* if not, return current state and bail out */ - if(check_host_check_viability_3x(hst, check_options, NULL, NULL) == ERROR) { - if(check_result_code) - *check_result_code = hst->current_state; - log_debug_info(DEBUGL_CHECKS, 0, "Host check is not viable at this time.\n"); - return OK; - } - - /* get the current time */ - time(¤t_time); - - /* high resolution start time for event broker */ - gettimeofday(&start_time, NULL); - - /* can we use the last cached host state? */ - if(use_cached_result == TRUE && !(check_options & CHECK_OPTION_FORCE_EXECUTION)) { - - /* we can used the cached result, so return it and get out of here... */ - if(hst->has_been_checked == TRUE && ((current_time - hst->last_check) <= check_timestamp_horizon)) { - if(check_result_code) - *check_result_code = hst->current_state; - - log_debug_info(DEBUGL_CHECKS, 1, "* Using cached host state: %d\n", hst->current_state); - - /* update check statistics */ - update_check_stats(ACTIVE_ONDEMAND_HOST_CHECK_STATS, current_time); - update_check_stats(ACTIVE_CACHED_HOST_CHECK_STATS, current_time); - - return OK; - } - } - - - log_debug_info(DEBUGL_CHECKS, 1, "* Running actual host check: old state=%d\n", hst->current_state); - - - /******** GOOD TO GO FOR A REAL HOST CHECK AT THIS POINT ********/ - - /* update check statistics */ - update_check_stats(ACTIVE_ONDEMAND_HOST_CHECK_STATS, current_time); - update_check_stats(SERIAL_HOST_CHECK_STATS, start_time.tv_sec); - - /* reset host check latency, since on-demand checks have none */ - hst->latency = 0.0; - - /* adjust host check attempt */ - adjust_host_check_attempt_3x(hst, TRUE); - - /* save old host state */ - hst->last_state = hst->current_state; - if(hst->state_type == HARD_STATE) - hst->last_hard_state = hst->current_state; - - /* save old plugin output for state stalking */ - if(hst->plugin_output) - old_plugin_output = (char *)strdup(hst->plugin_output); - - /* set the checked flag */ - hst->has_been_checked = TRUE; - - /* clear the freshness flag */ - hst->is_being_freshened = FALSE; - - /* clear check options - we don't want old check options retained */ - hst->check_options = CHECK_OPTION_NONE; - - /* set the check type */ - hst->check_type = HOST_CHECK_ACTIVE; - - - /*********** EXECUTE THE CHECK AND PROCESS THE RESULTS **********/ - -#ifdef USE_EVENT_BROKER - /* send data to event broker */ - end_time.tv_sec = 0L; - end_time.tv_usec = 0L; - broker_host_check(NEBTYPE_HOSTCHECK_INITIATE, NEBFLAG_NONE, NEBATTR_NONE, hst, HOST_CHECK_ACTIVE, hst->current_state, hst->state_type, start_time, end_time, hst->host_check_command, hst->latency, 0.0, host_check_timeout, FALSE, 0, NULL, NULL, NULL, NULL, NULL); -#endif - - /* execute the host check */ - host_result = execute_sync_host_check_3x(hst); - - /* process the host check result */ - process_host_check_result_3x(hst, host_result, old_plugin_output, check_options, FALSE, use_cached_result, check_timestamp_horizon); - - /* free memory */ - my_free(old_plugin_output); - - log_debug_info(DEBUGL_CHECKS, 1, "* Sync host check done: new state=%d\n", hst->current_state); - - /* high resolution end time for event broker */ - gettimeofday(&end_time, NULL); - -#ifdef USE_EVENT_BROKER - /* send data to event broker */ - broker_host_check(NEBTYPE_HOSTCHECK_PROCESSED, NEBFLAG_NONE, NEBATTR_NONE, hst, HOST_CHECK_ACTIVE, hst->current_state, hst->state_type, start_time, end_time, hst->host_check_command, hst->latency, hst->execution_time, host_check_timeout, FALSE, hst->current_state, NULL, hst->plugin_output, hst->long_plugin_output, hst->perf_data, NULL); -#endif - - return result; - } - - - -/* run an "alive" check on a host */ -/* on-demand host checks will use this... */ -int execute_sync_host_check_3x(host *hst) { - nagios_macros mac; - int result = STATE_OK; - int return_result = HOST_UP; - char *processed_command = NULL; - char *raw_command = NULL; - struct timeval start_time; - struct timeval end_time; - char *temp_ptr; - int early_timeout = FALSE; - double exectime; - char *temp_plugin_output = NULL; -#ifdef USE_EVENT_BROKER - int neb_result = OK; -#endif - - - log_debug_info(DEBUGL_FUNCTIONS, 0, "execute_sync_host_check_3x()\n"); - - if(hst == NULL) - return HOST_DOWN; - - log_debug_info(DEBUGL_CHECKS, 0, "** Executing sync check of host '%s'...\n", hst->name); - -#ifdef USE_EVENT_BROKER - /* initialize start/end times */ - start_time.tv_sec = 0L; - start_time.tv_usec = 0L; - end_time.tv_sec = 0L; - end_time.tv_usec = 0L; - - /* send data to event broker */ - neb_result = broker_host_check(NEBTYPE_HOSTCHECK_SYNC_PRECHECK, NEBFLAG_NONE, NEBATTR_NONE, hst, HOST_CHECK_ACTIVE, hst->current_state, hst->state_type, start_time, end_time, hst->host_check_command, hst->latency, 0.0, host_check_timeout, FALSE, 0, NULL, NULL, NULL, NULL, NULL); - - /* neb module wants to cancel the host check - return the current state of the host */ - if(neb_result == NEBERROR_CALLBACKCANCEL) - return hst->current_state; - - /* neb module wants to override the host check - perhaps it will check the host itself */ - /* NOTE: if a module does this, it must check the status of the host and populate the data structures BEFORE it returns from the callback! */ - if(neb_result == NEBERROR_CALLBACKOVERRIDE) - return hst->current_state; -#endif - - /* grab the host macros */ - memset(&mac, 0, sizeof(mac)); - grab_host_macros_r(&mac, hst); - - /* high resolution start time for event broker */ - gettimeofday(&start_time, NULL); - - /* get the last host check time */ - time(&hst->last_check); - - /* get the raw command line */ - get_raw_command_line_r(&mac, hst->check_command_ptr, hst->host_check_command, &raw_command, 0); - if(raw_command == NULL) { - clear_volatile_macros_r(&mac); - return ERROR; - } - - /* process any macros contained in the argument */ - process_macros_r(&mac, raw_command, &processed_command, 0); - if(processed_command == NULL) { - my_free(raw_command); - clear_volatile_macros_r(&mac); - return ERROR; - } - -#ifdef USE_EVENT_BROKER - /* send data to event broker */ - end_time.tv_sec = 0L; - end_time.tv_usec = 0L; - broker_host_check(NEBTYPE_HOSTCHECK_RAW_START, NEBFLAG_NONE, NEBATTR_NONE, hst, HOST_CHECK_ACTIVE, return_result, hst->state_type, start_time, end_time, hst->host_check_command, 0.0, 0.0, host_check_timeout, early_timeout, result, processed_command, hst->plugin_output, hst->long_plugin_output, hst->perf_data, NULL); -#endif - - log_debug_info(DEBUGL_COMMANDS, 1, "Raw host check command: %s\n", raw_command); - log_debug_info(DEBUGL_COMMANDS, 0, "Processed host check ommand: %s\n", processed_command); - my_free(raw_command); - - /* clear plugin output and performance data buffers */ - my_free(hst->plugin_output); - my_free(hst->long_plugin_output); - my_free(hst->perf_data); - - /* run the host check command */ - result = my_system_r(&mac, processed_command, host_check_timeout, &early_timeout, &exectime, &temp_plugin_output, MAX_PLUGIN_OUTPUT_LENGTH); - clear_volatile_macros_r(&mac); - - /* if the check timed out, report an error */ - if(early_timeout == TRUE) { - - my_free(temp_plugin_output); - asprintf(&temp_plugin_output, "Host check timed out after %d seconds\n", host_check_timeout); - - /* log the timeout */ - logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Host check command '%s' for host '%s' timed out after %d seconds\n", processed_command, hst->name, host_check_timeout); - } - - /* calculate total execution time */ - hst->execution_time = exectime; - - /* record check type */ - hst->check_type = HOST_CHECK_ACTIVE; - - /* parse the output: short and long output, and perf data */ - parse_check_output(temp_plugin_output, &hst->plugin_output, &hst->long_plugin_output, &hst->perf_data, TRUE, TRUE); - - /* free memory */ - my_free(temp_plugin_output); - my_free(processed_command); - - /* a NULL host check command means we should assume the host is UP */ - if(hst->host_check_command == NULL) { - my_free(hst->plugin_output); - hst->plugin_output = (char *)strdup("(Host assumed to be UP)"); - result = STATE_OK; - } - - /* make sure we have some data */ - if(hst->plugin_output == NULL || !strcmp(hst->plugin_output, "")) { - my_free(hst->plugin_output); - hst->plugin_output = (char *)strdup("(No output returned from host check)"); - } - - /* replace semicolons in plugin output (but not performance data) with colons */ - if((temp_ptr = hst->plugin_output)) { - while((temp_ptr = strchr(temp_ptr, ';'))) - * temp_ptr = ':'; - } - - /* if we're not doing aggressive host checking, let WARNING states indicate the host is up (fake the result to be STATE_OK) */ - if(use_aggressive_host_checking == FALSE && result == STATE_WARNING) - result = STATE_OK; - - - if(result == STATE_OK) - return_result = HOST_UP; - else - return_result = HOST_DOWN; - - /* high resolution end time for event broker */ - gettimeofday(&end_time, NULL); - -#ifdef USE_EVENT_BROKER - /* send data to event broker */ - broker_host_check(NEBTYPE_HOSTCHECK_RAW_END, NEBFLAG_NONE, NEBATTR_NONE, hst, HOST_CHECK_ACTIVE, return_result, hst->state_type, start_time, end_time, hst->host_check_command, 0.0, exectime, host_check_timeout, early_timeout, result, processed_command, hst->plugin_output, hst->long_plugin_output, hst->perf_data, NULL); -#endif - - log_debug_info(DEBUGL_CHECKS, 0, "** Sync host check done: state=%d\n", return_result); - - return return_result; - } - - - /* run a scheduled host check asynchronously */ -int run_scheduled_host_check_3x(host *hst, int check_options, double latency) { +int run_scheduled_host_check(host *hst, int check_options, double latency) { int result = OK; time_t current_time = 0L; time_t preferred_time = 0L; @@ -2841,7 +1970,7 @@ int run_scheduled_host_check_3x(host *hst, int check_options, double latency) { int time_is_valid = TRUE; - log_debug_info(DEBUGL_FUNCTIONS, 0, "run_scheduled_host_check_3x()\n"); + log_debug_info(DEBUGL_FUNCTIONS, 0, "run_scheduled_host_check()\n"); if(hst == NULL) return ERROR; @@ -2855,7 +1984,7 @@ int run_scheduled_host_check_3x(host *hst, int check_options, double latency) { hst->next_check_event = NULL; /* attempt to run the check */ - result = run_async_host_check_3x(hst, check_options, latency, TRUE, TRUE, &time_is_valid, &preferred_time); + result = run_async_host_check(hst, check_options, latency, TRUE, TRUE, &time_is_valid, &preferred_time); /* an error occurred, so reschedule the check */ if(result == ERROR) { @@ -2876,17 +2005,16 @@ int run_scheduled_host_check_3x(host *hst, int check_options, double latency) { /* make sure we rescheduled the next host check at a valid time */ get_next_valid_time(preferred_time, &next_valid_time, hst->check_period_ptr); - /* the host could not be rescheduled properly - set the next check time for next week */ - if(time_is_valid == FALSE && next_valid_time == preferred_time) { + /* + * If the host really can't be rescheduled properly we + * set next check time to preferred_time and try again then + */ + if(time_is_valid == FALSE && check_time_against_period(next_valid_time, hst->check_period_ptr) == ERROR) { - /* - hst->next_check=(time_t)(next_valid_time+(60*60*24*365)); - hst->should_be_scheduled=FALSE; - */ + hst->next_check = preferred_time + + ranged_urand(0, check_window(hst)); - hst->next_check = (time_t)(next_valid_time + (60 * 60 * 24 * 7)); - - logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Check of host '%s' could not be rescheduled properly. Scheduling check for next week...\n", hst->name); + logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Check of host '%s' could not be rescheduled properly. Scheduling check for %s...\n", hst->name, ctime(&preferred_time)); log_debug_info(DEBUGL_CHECKS, 1, "Unable to find any valid times to reschedule the next host check!\n"); } @@ -2894,6 +2022,14 @@ int run_scheduled_host_check_3x(host *hst, int check_options, double latency) { /* this service could be rescheduled... */ else { hst->next_check = next_valid_time; + if(next_valid_time > preferred_time) { + /* Next valid time is further in the future because of + * timeperiod constraints. Add a random amount so we + * don't get all checks subject to that timeperiod + * constraint scheduled at the same time + */ + hst->next_check += ranged_urand(0, check_window(hst)); + } hst->should_be_scheduled = TRUE; log_debug_info(DEBUGL_CHECKS, 1, "Rescheduled next host check for %s", ctime(&next_valid_time)); @@ -2918,29 +2054,20 @@ int run_scheduled_host_check_3x(host *hst, int check_options, double latency) { /* perform an asynchronous check of a host */ /* scheduled host checks will use this, as will some checks that result from on-demand checks... */ -int run_async_host_check_3x(host *hst, int check_options, double latency, int scheduled_check, int reschedule_check, int *time_is_valid, time_t *preferred_time) { +int run_async_host_check(host *hst, int check_options, double latency, int scheduled_check, int reschedule_check, int *time_is_valid, time_t *preferred_time) { nagios_macros mac; char *raw_command = NULL; char *processed_command = NULL; - char output_buffer[MAX_INPUT_BUFFER] = ""; - char *temp_buffer = NULL; struct timeval start_time, end_time; - pid_t pid = 0; - int fork_error = FALSE; - int wait_result = 0; - FILE *fp = NULL; - int pclose_result = 0; - mode_t new_umask = 077; - mode_t old_umask; - char *output_file = NULL; double old_latency = 0.0; - dbuf checkresult_dbuf; - int dbuf_chunk = 1024; + check_result *cr; + int runchk_result = OK; + int macro_options = STRIP_ILLEGAL_MACRO_CHARS | ESCAPE_MACRO_CHARS; #ifdef USE_EVENT_BROKER int neb_result = OK; #endif - log_debug_info(DEBUGL_FUNCTIONS, 0, "run_async_host_check_3x()\n"); + log_debug_info(DEBUGL_FUNCTIONS, 0, "run_async_host_check(%s ...)\n", hst ? hst->name : "(NULL host!)"); /* make sure we have a host */ if(hst == NULL) @@ -2948,13 +2075,23 @@ int run_async_host_check_3x(host *hst, int check_options, double latency, int sc log_debug_info(DEBUGL_CHECKS, 0, "** Running async check of host '%s'...\n", hst->name); - /* is the host check viable at this time? */ - if(check_host_check_viability_3x(hst, check_options, time_is_valid, preferred_time) == ERROR) - return ERROR; + /* abort if check is already running or was recently completed */ + if (!(check_options & CHECK_OPTION_FORCE_EXECUTION)) { + if(hst->is_executing == TRUE) { + log_debug_info(DEBUGL_CHECKS, 1, "A check of this host is already being executed, so we'll pass for the moment...\n"); + return ERROR; + } - /* 08/04/07 EG don't execute a new host check if one is already running */ - if(hst->is_executing == TRUE && !(check_options & CHECK_OPTION_FORCE_EXECUTION)) { - log_debug_info(DEBUGL_CHECKS, 1, "A check of this host is already being executed, so we'll pass for the moment...\n"); + if (hst->last_check + cached_host_check_horizon > time(NULL)) { + log_debug_info(DEBUGL_CHECKS, 0, "Host '%s' was last checked within its cache horizon. Aborting check\n", hst->name); + return ERROR; + } + } + + log_debug_info(DEBUGL_CHECKS, 0, "Host '%s' passed first hurdle (caching/execution)\n", hst->name); + /* is the host check viable at this time? */ + if(check_host_check_viability(hst, check_options, time_is_valid, preferred_time) == ERROR) { + log_debug_info(DEBUGL_CHECKS, 0, "Host check isn't viable at this point.\n"); return ERROR; } @@ -2968,14 +2105,23 @@ int run_async_host_check_3x(host *hst, int check_options, double latency, int sc end_time.tv_usec = 0L; /* send data to event broker */ - neb_result = broker_host_check(NEBTYPE_HOSTCHECK_ASYNC_PRECHECK, NEBFLAG_NONE, NEBATTR_NONE, hst, HOST_CHECK_ACTIVE, hst->current_state, hst->state_type, start_time, end_time, hst->host_check_command, hst->latency, 0.0, host_check_timeout, FALSE, 0, NULL, NULL, NULL, NULL, NULL); + neb_result = broker_host_check(NEBTYPE_HOSTCHECK_ASYNC_PRECHECK, NEBFLAG_NONE, NEBATTR_NONE, hst, CHECK_TYPE_ACTIVE, hst->current_state, hst->state_type, start_time, end_time, hst->check_command, hst->latency, 0.0, host_check_timeout, FALSE, 0, NULL, NULL, NULL, NULL, NULL, NULL); + if(neb_result == NEBERROR_CALLBACKCANCEL || neb_result == NEBERROR_CALLBACKOVERRIDE) { + log_debug_info(DEBUGL_CHECKS, 0, "Check of host '%s' (id=%u) was %s by a module\n", + hst->name, hst->id, + neb_result == NEBERROR_CALLBACKCANCEL ? "cancelled" : "overridden"); + } /* neb module wants to cancel the host check - the check will be rescheduled for a later time by the scheduling logic */ - if(neb_result == NEBERROR_CALLBACKCANCEL) + if(neb_result == NEBERROR_CALLBACKCANCEL) { + if(preferred_time) + *preferred_time += check_window(hst); return ERROR; + } /* neb module wants to override the host check - perhaps it will check the host itself */ /* NOTE: if a module does this, it has to do a lot of the stuff found below to make sure things don't get whacked out of shape! */ + /* NOTE: if would be easier for modules to override checks when the NEBTYPE_SERVICECHECK_INITIATE event is called (later) */ if(neb_result == NEBERROR_CALLBACKOVERRIDE) return OK; #endif @@ -2988,7 +2134,7 @@ int run_async_host_check_3x(host *hst, int check_options, double latency, int sc hst->check_options = CHECK_OPTION_NONE; /* adjust host check attempt */ - adjust_host_check_attempt_3x(hst, TRUE); + adjust_host_check_attempt(hst, TRUE); /* set latency (temporarily) for macros and event broker */ old_latency = hst->latency; @@ -2999,7 +2145,7 @@ int run_async_host_check_3x(host *hst, int check_options, double latency, int sc grab_host_macros_r(&mac, hst); /* get the raw command line */ - get_raw_command_line_r(&mac, hst->check_command_ptr, hst->host_check_command, &raw_command, 0); + get_raw_command_line_r(&mac, hst->check_command_ptr, hst->check_command, &raw_command, macro_options); if(raw_command == NULL) { clear_volatile_macros_r(&mac); log_debug_info(DEBUGL_CHECKS, 0, "Raw check command for host '%s' was NULL - aborting.\n", hst->name); @@ -3007,7 +2153,7 @@ int run_async_host_check_3x(host *hst, int check_options, double latency, int sc } /* process any macros contained in the argument */ - process_macros_r(&mac, raw_command, &processed_command, 0); + process_macros_r(&mac, raw_command, &processed_command, macro_options); my_free(raw_command); if(processed_command == NULL) { clear_volatile_macros_r(&mac); @@ -3018,264 +2164,134 @@ int run_async_host_check_3x(host *hst, int check_options, double latency, int sc /* get the command start time */ gettimeofday(&start_time, NULL); - /* set check time for on-demand checks, so they're not incorrectly detected as being orphaned - Luke Ross 5/16/08 */ - /* NOTE: 06/23/08 EG not sure if there will be side effects to this or not.... */ - if(scheduled_check == FALSE) - hst->next_check = start_time.tv_sec; - - /* increment number of host checks that are currently running... */ - currently_running_host_checks++; - - /* set the execution flag */ - hst->is_executing = TRUE; - - /* open a temp file for storing check output */ - old_umask = umask(new_umask); - asprintf(&output_file, "%s/checkXXXXXX", temp_path); - check_result_info.output_file_fd = mkstemp(output_file); - if(check_result_info.output_file_fd >= 0) - check_result_info.output_file_fp = fdopen(check_result_info.output_file_fd, "w"); - else { - check_result_info.output_file_fp = NULL; - check_result_info.output_file_fd = -1; - } - umask(old_umask); - - log_debug_info(DEBUGL_CHECKS | DEBUGL_IPC, 1, "Check result output will be written to '%s' (fd=%d)\n", output_file, check_result_info.output_file_fd); + cr = calloc(1, sizeof(*cr)); + if (!cr) { + log_debug_info(DEBUGL_CHECKS, 0, "Failed to allocate checkresult struct\n"); + clear_volatile_macros_r(&mac); + clear_host_macros_r(&mac); + return ERROR; + } + init_check_result(cr); /* save check info */ - check_result_info.object_check_type = HOST_CHECK; - check_result_info.host_name = (char *)strdup(hst->name); - check_result_info.service_description = NULL; - check_result_info.check_type = HOST_CHECK_ACTIVE; - check_result_info.check_options = check_options; - check_result_info.scheduled_check = scheduled_check; - check_result_info.reschedule_check = reschedule_check; - check_result_info.output_file = (check_result_info.output_file_fd < 0 || output_file == NULL) ? NULL : strdup(output_file); - check_result_info.latency = latency; - check_result_info.start_time = start_time; - check_result_info.finish_time = start_time; - check_result_info.early_timeout = FALSE; - check_result_info.exited_ok = TRUE; - check_result_info.return_code = STATE_OK; - check_result_info.output = NULL; - - /* free memory */ - my_free(output_file); - - /* write initial check info to file */ - /* if things go bad later on, the user will at least have something to go on when debugging... */ - if(check_result_info.output_file_fp) { - - fprintf(check_result_info.output_file_fp, "### Active Check Result File ###\n"); - fprintf(check_result_info.output_file_fp, "file_time=%lu\n", (unsigned long)check_result_info.start_time.tv_sec); - fprintf(check_result_info.output_file_fp, "\n"); - - fprintf(check_result_info.output_file_fp, "### Nagios Host Check Result ###\n"); - fprintf(check_result_info.output_file_fp, "# Time: %s", ctime(&check_result_info.start_time.tv_sec)); - fprintf(check_result_info.output_file_fp, "host_name=%s\n", check_result_info.host_name); - fprintf(check_result_info.output_file_fp, "check_type=%d\n", check_result_info.check_type); - fprintf(check_result_info.output_file_fp, "check_options=%d\n", check_result_info.check_options); - fprintf(check_result_info.output_file_fp, "scheduled_check=%d\n", check_result_info.scheduled_check); - fprintf(check_result_info.output_file_fp, "reschedule_check=%d\n", check_result_info.reschedule_check); - fprintf(check_result_info.output_file_fp, "latency=%f\n", hst->latency); - fprintf(check_result_info.output_file_fp, "start_time=%lu.%lu\n", check_result_info.start_time.tv_sec, check_result_info.start_time.tv_usec); - - /* flush buffer or we'll end up writing twice when we fork() */ - fflush(check_result_info.output_file_fp); - } - - /* initialize dynamic buffer for storing plugin output */ - dbuf_init(&checkresult_dbuf, dbuf_chunk); + cr->object_check_type = HOST_CHECK; + cr->host_name = (char *)strdup(hst->name); + cr->service_description = NULL; + cr->check_type = CHECK_TYPE_ACTIVE; + cr->check_options = check_options; + cr->scheduled_check = scheduled_check; + cr->reschedule_check = reschedule_check; + cr->latency = latency; + cr->start_time = start_time; + cr->finish_time = start_time; + cr->early_timeout = FALSE; + cr->exited_ok = TRUE; + cr->return_code = STATE_OK; + cr->output = NULL; #ifdef USE_EVENT_BROKER /* send data to event broker */ - broker_host_check(NEBTYPE_HOSTCHECK_INITIATE, NEBFLAG_NONE, NEBATTR_NONE, hst, HOST_CHECK_ACTIVE, hst->current_state, hst->state_type, start_time, end_time, hst->host_check_command, hst->latency, 0.0, host_check_timeout, FALSE, 0, processed_command, NULL, NULL, NULL, NULL); + neb_result = broker_host_check(NEBTYPE_HOSTCHECK_INITIATE, NEBFLAG_NONE, NEBATTR_NONE, hst, CHECK_TYPE_ACTIVE, hst->current_state, hst->state_type, start_time, end_time, hst->check_command, hst->latency, 0.0, host_check_timeout, FALSE, 0, processed_command, NULL, NULL, NULL, NULL, cr); + + /* neb module wants to override the service check - perhaps it will check the service itself */ + if (neb_result == NEBERROR_CALLBACKOVERRIDE) { + clear_volatile_macros_r(&mac); + hst->latency = old_latency; + free_check_result(cr); + my_free(processed_command); + return OK; + } #endif /* reset latency (permanent value for this check will get set later) */ hst->latency = old_latency; - /* update check statistics */ - update_check_stats((scheduled_check == TRUE) ? ACTIVE_SCHEDULED_HOST_CHECK_STATS : ACTIVE_ONDEMAND_HOST_CHECK_STATS, start_time.tv_sec); - update_check_stats(PARALLEL_HOST_CHECK_STATS, start_time.tv_sec); + runchk_result = wproc_run_check(cr, processed_command, &mac); + if (runchk_result == ERROR) { + logit(NSLOG_RUNTIME_ERROR, TRUE, "Unable to send check for host '%s' to worker (ret=%d)\n", hst->name, runchk_result); + } else { + /* do the book-keeping */ + currently_running_host_checks++; + hst->is_executing = TRUE; + update_check_stats((scheduled_check == TRUE) ? ACTIVE_SCHEDULED_HOST_CHECK_STATS : ACTIVE_ONDEMAND_HOST_CHECK_STATS, start_time.tv_sec); + update_check_stats(PARALLEL_HOST_CHECK_STATS, start_time.tv_sec); + } - /* fork a child process */ - pid = fork(); - /* an error occurred while trying to fork */ - if(pid == -1) { + /* free memory */ + clear_volatile_macros_r(&mac); + my_free(processed_command); - fork_error = TRUE; - - /* log an error */ - logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: The check of host '%s' could not be performed due to a fork() error: '%s'.\n", hst->name, strerror(errno)); - - log_debug_info(DEBUGL_CHECKS, 0, "Check of host '%s' could not be performed due to a fork() error: '%s'!\n", hst->name, strerror(errno)); - } - - /* if we are in the child process... */ - else if(pid == 0) { - - /* set environment variables */ - set_all_macro_environment_vars_r(&mac, TRUE); - - /* ADDED 11/12/07 EG */ - /* close external command file and shut down worker thread */ - close_command_file(); - - /* fork again if we're not in a large installation */ - if(child_processes_fork_twice == TRUE) { - - /* fork again... */ - pid = fork(); - - /* an error occurred while trying to fork again */ - if(pid == -1) - exit(STATE_UNKNOWN); - } - - /* the grandchild (or child if large install tweaks are enabled) process should run the host check... */ - if(pid == 0 || child_processes_fork_twice == FALSE) { - - /* reset signal handling */ - reset_sighandler(); - - /* become the process group leader */ - setpgid(0, 0); - - /* exit on term signals at this process level */ - signal(SIGTERM, SIG_DFL); - - /* catch plugins that don't finish in a timely manner */ - signal(SIGALRM, host_check_sighandler); - alarm(host_check_timeout); - - /* disable rotation of the debug file */ - max_debug_file_size = 0L; - - /* run the plugin check command */ - fp = popen(processed_command, "r"); - if(fp == NULL) - _exit(STATE_UNKNOWN); - - /* initialize buffer */ - strcpy(output_buffer, ""); - - /* get all lines of plugin output - escape newlines */ - while(fgets(output_buffer, sizeof(output_buffer) - 1, fp)) { - temp_buffer = escape_newlines(output_buffer); - dbuf_strcat(&checkresult_dbuf, temp_buffer); - my_free(temp_buffer); - } - - /* close the process */ - pclose_result = pclose(fp); - - /* reset the alarm and signal handling here */ - signal(SIGALRM, SIG_IGN); - alarm(0); - - /* get the check finish time */ - gettimeofday(&end_time, NULL); - - /* record check result info */ - check_result_info.finish_time = end_time; - check_result_info.early_timeout = FALSE; - - /* test for execution error */ - if(pclose_result == -1) { - pclose_result = STATE_UNKNOWN; - check_result_info.return_code = STATE_CRITICAL; - check_result_info.exited_ok = FALSE; - } - else { - if(WEXITSTATUS(pclose_result) == 0 && WIFSIGNALED(pclose_result)) - check_result_info.return_code = 128 + WTERMSIG(pclose_result); - else - check_result_info.return_code = WEXITSTATUS(pclose_result); - } - - /* write check result to file */ - if(check_result_info.output_file_fp) { - FILE *fp; - - /* protect against signal races */ - fp = check_result_info.output_file_fp; - check_result_info.output_file_fp = NULL; - - fprintf(fp, "finish_time=%lu.%lu\n", check_result_info.finish_time.tv_sec, check_result_info.finish_time.tv_usec); - fprintf(fp, "early_timeout=%d\n", check_result_info.early_timeout); - fprintf(fp, "exited_ok=%d\n", check_result_info.exited_ok); - fprintf(fp, "return_code=%d\n", check_result_info.return_code); - fprintf(fp, "output=%s\n", (checkresult_dbuf.buf == NULL) ? "(null)" : checkresult_dbuf.buf); - - /* close the temp file */ - fclose(fp); - - /* move check result to queue directory */ - move_check_result_to_queue(check_result_info.output_file); - } - - /* free memory */ - dbuf_free(&checkresult_dbuf); - my_free(processed_command); - - /* free check result memory */ - free_check_result(&check_result_info); - - /* return with plugin exit status - not really necessary... */ - _exit(pclose_result); - } - - /* NOTE: this code is never reached if large install tweaks are enabled... */ - - /* unset environment variables */ - set_all_macro_environment_vars_r(&mac, FALSE); - - /* free allocated memory */ - /* this needs to be done last, so we don't free memory for variables before they're used above */ - if(free_child_process_memory == TRUE) - free_memory(&mac); - - /* parent exits immediately - grandchild process is inherited by the INIT process, so we have no zombie problem... */ - _exit(STATE_OK); - } - - /* else the parent should wait for the first child to return... */ - else if(pid > 0) { - clear_volatile_macros_r(&mac); - - log_debug_info(DEBUGL_CHECKS, 2, "Host check is executing in child process (pid=%lu)\n", (unsigned long)pid); - - /* parent should close output file */ - if(check_result_info.output_file_fp) - fclose(check_result_info.output_file_fp); - - /* should this be done in first child process (after spawning grandchild) as well? */ - /* free memory allocated for IPC functionality */ - free_check_result(&check_result_info); - - /* free memory */ - my_free(processed_command); - - /* wait for the first child to return */ - /* if large install tweaks are enabled, we'll clean up the zombie process later */ - if(child_processes_fork_twice == TRUE) - wait_result = waitpid(pid, NULL, 0); - } - - /* see if we were able to run the check... */ - if(fork_error == TRUE) - return ERROR; - - return OK; + return runchk_result; } +static int get_host_check_return_code(host *temp_host, + check_result *queued_check_result) { + + int rc; + char *temp_plugin_output = NULL; + + log_debug_info(DEBUGL_FUNCTIONS, 0, "get_host_check_return_code()\n"); + + /* get the unprocessed return code */ + /* NOTE: for passive checks, this is the final/processed state */ + rc = queued_check_result->return_code; + + /* adjust return code (active checks only) */ + if(queued_check_result->check_type == CHECK_TYPE_ACTIVE) { + if(queued_check_result->early_timeout) { + logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Check of host '%s' timed out after %.2lf seconds\n", temp_host->name, temp_host->execution_time); + my_free(temp_host->plugin_output); + my_free(temp_host->long_plugin_output); + my_free(temp_host->perf_data); + asprintf(&temp_host->plugin_output, "(Host check timed out after %.2lf seconds)", temp_host->execution_time); + rc = STATE_UNKNOWN; + } + + /* if there was some error running the command, just skip it (this shouldn't be happening) */ + else if(queued_check_result->exited_ok == FALSE) { + + logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Check of host '%s' did not exit properly!\n", temp_host->name); + + my_free(temp_host->plugin_output); + my_free(temp_host->long_plugin_output); + my_free(temp_host->perf_data); + + temp_host->plugin_output = (char *)strdup("(Host check did not exit properly)"); + + rc = STATE_CRITICAL; + } + + /* make sure the return code is within bounds */ + else if(queued_check_result->return_code < 0 || queued_check_result->return_code > 3) { + + logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Return code of %d for check of host '%s' was out of bounds.%s\n", queued_check_result->return_code, temp_host->name, (queued_check_result->return_code == 126 || queued_check_result->return_code == 127) ? " Make sure the plugin you're trying to run actually exists." : ""); + + asprintf(&temp_plugin_output, "(Return code of %d is out of bounds%s : %s)", queued_check_result->return_code, (queued_check_result->return_code == 126 || queued_check_result->return_code == 127) ? " - plugin may be missing" : "", temp_host->plugin_output); + my_free(temp_host->plugin_output); + + asprintf(&temp_host->plugin_output, "%s)", temp_plugin_output); + my_free(temp_plugin_output); + my_free(temp_host->long_plugin_output); + my_free(temp_host->perf_data); + + rc = STATE_CRITICAL; + } + + /* a NULL host check command means we should assume the host is UP */ + if(temp_host->check_command == NULL) { + my_free(temp_host->plugin_output); + temp_host->plugin_output = (char *)strdup("(Host assumed to be UP)"); + rc = STATE_OK; + } + } + return rc; + } + /* process results of an asynchronous host check */ -int handle_async_host_check_result_3x(host *temp_host, check_result *queued_check_result) { +int handle_async_host_check_result(host *temp_host, check_result *queued_check_result) { time_t current_time; int result = STATE_OK; int reschedule_check = FALSE; @@ -3284,7 +2300,7 @@ int handle_async_host_check_result_3x(host *temp_host, check_result *queued_chec struct timeval start_time_hires; struct timeval end_time_hires; - log_debug_info(DEBUGL_FUNCTIONS, 0, "handle_async_host_check_result_3x()\n"); + log_debug_info(DEBUGL_FUNCTIONS, 0, "handle_async_host_check_result(%s ...)\n", temp_host ? temp_host->name : "(NULL host!)"); /* make sure we have what we need */ if(temp_host == NULL || queued_check_result == NULL) @@ -3292,9 +2308,9 @@ int handle_async_host_check_result_3x(host *temp_host, check_result *queued_chec time(¤t_time); - log_debug_info(DEBUGL_CHECKS, 1, "** Handling async check result for host '%s'...\n", temp_host->name); + log_debug_info(DEBUGL_CHECKS, 1, "** Handling async check result for host '%s' from '%s'...\n", temp_host->name, check_result_source(queued_check_result)); - log_debug_info(DEBUGL_CHECKS, 2, "\tCheck Type: %s\n", (queued_check_result->check_type == HOST_CHECK_ACTIVE) ? "Active" : "Passive"); + log_debug_info(DEBUGL_CHECKS, 2, "\tCheck Type: %s\n", (queued_check_result->check_type == CHECK_TYPE_ACTIVE) ? "Active" : "Passive"); log_debug_info(DEBUGL_CHECKS, 2, "\tCheck Options: %d\n", queued_check_result->check_options); log_debug_info(DEBUGL_CHECKS, 2, "\tScheduled Check?: %s\n", (queued_check_result->scheduled_check == TRUE) ? "Yes" : "No"); log_debug_info(DEBUGL_CHECKS, 2, "\tReschedule Check?: %s\n", (queued_check_result->reschedule_check == TRUE) ? "Yes" : "No"); @@ -3305,16 +2321,16 @@ int handle_async_host_check_result_3x(host *temp_host, check_result *queued_chec log_debug_info(DEBUGL_CHECKS, 2, "\tOutput: %s\n", (queued_check_result == NULL) ? "NULL" : queued_check_result->output); /* decrement the number of host checks still out there... */ - if(queued_check_result->check_type == HOST_CHECK_ACTIVE && currently_running_host_checks > 0) + if(queued_check_result->check_type == CHECK_TYPE_ACTIVE && currently_running_host_checks > 0) currently_running_host_checks--; /* skip this host check results if its passive and we aren't accepting passive check results */ - if(queued_check_result->check_type == HOST_CHECK_PASSIVE) { + if(queued_check_result->check_type == CHECK_TYPE_PASSIVE) { if(accept_passive_host_checks == FALSE) { log_debug_info(DEBUGL_CHECKS, 0, "Discarding passive host check result because passive host checks are disabled globally.\n"); return ERROR; } - if(temp_host->accept_passive_host_checks == FALSE) { + if(temp_host->accept_passive_checks == FALSE) { log_debug_info(DEBUGL_CHECKS, 0, "Discarding passive host check result because passive checks are disabled for this host.\n"); return ERROR; } @@ -3334,10 +2350,10 @@ int handle_async_host_check_result_3x(host *temp_host, check_result *queued_chec } /* was this check passive or active? */ - temp_host->check_type = (queued_check_result->check_type == HOST_CHECK_ACTIVE) ? HOST_CHECK_ACTIVE : HOST_CHECK_PASSIVE; + temp_host->check_type = (queued_check_result->check_type == CHECK_TYPE_ACTIVE) ? CHECK_TYPE_ACTIVE : CHECK_TYPE_PASSIVE; /* update check statistics for passive results */ - if(queued_check_result->check_type == HOST_CHECK_PASSIVE) + if(queued_check_result->check_type == CHECK_TYPE_PASSIVE) update_check_stats(PASSIVE_HOST_CHECK_STATS, queued_check_result->start_time.tv_sec); /* should we reschedule the next check of the host? NOTE: this might be overridden later... */ @@ -3355,14 +2371,14 @@ int handle_async_host_check_result_3x(host *temp_host, check_result *queued_chec temp_host->has_been_checked = TRUE; /* clear the execution flag if this was an active check */ - if(queued_check_result->check_type == HOST_CHECK_ACTIVE) + if(queued_check_result->check_type == CHECK_TYPE_ACTIVE) temp_host->is_executing = FALSE; /* get the last check time */ temp_host->last_check = queued_check_result->start_time.tv_sec; /* was this check passive or active? */ - temp_host->check_type = (queued_check_result->check_type == HOST_CHECK_ACTIVE) ? HOST_CHECK_ACTIVE : HOST_CHECK_PASSIVE; + temp_host->check_type = (queued_check_result->check_type == CHECK_TYPE_ACTIVE) ? CHECK_TYPE_ACTIVE : CHECK_TYPE_PASSIVE; /* save the old host state */ temp_host->last_state = temp_host->current_state; @@ -3379,7 +2395,7 @@ int handle_async_host_check_result_3x(host *temp_host, check_result *queued_chec my_free(temp_host->perf_data); /* parse check output to get: (1) short output, (2) long output, (3) perf data */ - parse_check_output(queued_check_result->output, &temp_host->plugin_output, &temp_host->long_plugin_output, &temp_host->perf_data, TRUE, TRUE); + parse_check_output(queued_check_result->output, &temp_host->plugin_output, &temp_host->long_plugin_output, &temp_host->perf_data, TRUE, FALSE); /* make sure we have some data */ if(temp_host->plugin_output == NULL || !strcmp(temp_host->plugin_output, "")) { @@ -3398,52 +2414,12 @@ int handle_async_host_check_result_3x(host *temp_host, check_result *queued_chec log_debug_info(DEBUGL_CHECKS, 2, "Long Output: %s\n", (temp_host->long_plugin_output == NULL) ? "NULL" : temp_host->long_plugin_output); log_debug_info(DEBUGL_CHECKS, 2, "Perf Data: %s\n", (temp_host->perf_data == NULL) ? "NULL" : temp_host->perf_data); - /* get the unprocessed return code */ - /* NOTE: for passive checks, this is the final/processed state */ - result = queued_check_result->return_code; - - /* adjust return code (active checks only) */ - if(queued_check_result->check_type == HOST_CHECK_ACTIVE) { - - /* if there was some error running the command, just skip it (this shouldn't be happening) */ - if(queued_check_result->exited_ok == FALSE) { - - logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Check of host '%s' did not exit properly!\n", temp_host->name); - - my_free(temp_host->plugin_output); - my_free(temp_host->long_plugin_output); - my_free(temp_host->perf_data); - - temp_host->plugin_output = (char *)strdup("(Host check did not exit properly)"); - - result = STATE_CRITICAL; - } - - /* make sure the return code is within bounds */ - else if(queued_check_result->return_code < 0 || queued_check_result->return_code > 3) { - - logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Return code of %d for check of host '%s' was out of bounds.%s\n", queued_check_result->return_code, temp_host->name, (queued_check_result->return_code == 126 || queued_check_result->return_code == 127) ? " Make sure the plugin you're trying to run actually exists." : ""); - - my_free(temp_host->plugin_output); - my_free(temp_host->long_plugin_output); - my_free(temp_host->perf_data); - - asprintf(&temp_host->plugin_output, "(Return code of %d is out of bounds%s)", queued_check_result->return_code, (queued_check_result->return_code == 126 || queued_check_result->return_code == 127) ? " - plugin may be missing" : ""); - - result = STATE_CRITICAL; - } - - /* a NULL host check command means we should assume the host is UP */ - if(temp_host->host_check_command == NULL) { - my_free(temp_host->plugin_output); - temp_host->plugin_output = (char *)strdup("(Host assumed to be UP)"); - result = STATE_OK; - } - } + /* get the check return code */ + result = get_host_check_return_code(temp_host, queued_check_result); /* translate return code to basic UP/DOWN state - the DOWN/UNREACHABLE state determination is made later */ /* NOTE: only do this for active checks - passive check results already have the final state */ - if(queued_check_result->check_type == HOST_CHECK_ACTIVE) { + if(queued_check_result->check_type == CHECK_TYPE_ACTIVE) { /* if we're not doing aggressive host checking, let WARNING states indicate the host is up (fake the result to be STATE_OK) */ if(use_aggressive_host_checking == FALSE && result == STATE_WARNING) @@ -3462,7 +2438,7 @@ int handle_async_host_check_result_3x(host *temp_host, check_result *queued_chec /******************* PROCESS THE CHECK RESULTS ******************/ /* process the host check result */ - process_host_check_result_3x(temp_host, result, old_plugin_output, CHECK_OPTION_NONE, reschedule_check, TRUE, cached_host_check_horizon); + process_host_check_result(temp_host, result, old_plugin_output, CHECK_OPTION_NONE, reschedule_check, TRUE, cached_host_check_horizon); /* free memory */ my_free(old_plugin_output); @@ -3477,7 +2453,7 @@ int handle_async_host_check_result_3x(host *temp_host, check_result *queued_chec #ifdef USE_EVENT_BROKER /* send data to event broker */ - broker_host_check(NEBTYPE_HOSTCHECK_PROCESSED, NEBFLAG_NONE, NEBATTR_NONE, temp_host, temp_host->check_type, temp_host->current_state, temp_host->state_type, start_time_hires, end_time_hires, temp_host->host_check_command, temp_host->latency, temp_host->execution_time, host_check_timeout, queued_check_result->early_timeout, queued_check_result->return_code, NULL, temp_host->plugin_output, temp_host->long_plugin_output, temp_host->perf_data, NULL); + broker_host_check(NEBTYPE_HOSTCHECK_PROCESSED, NEBFLAG_NONE, NEBATTR_NONE, temp_host, temp_host->check_type, temp_host->current_state, temp_host->state_type, start_time_hires, end_time_hires, temp_host->check_command, temp_host->latency, temp_host->execution_time, host_check_timeout, queued_check_result->early_timeout, queued_check_result->return_code, NULL, temp_host->plugin_output, temp_host->long_plugin_output, temp_host->perf_data, NULL, queued_check_result); #endif return OK; @@ -3486,40 +2462,33 @@ int handle_async_host_check_result_3x(host *temp_host, check_result *queued_chec /* processes the result of a synchronous or asynchronous host check */ -int process_host_check_result_3x(host *hst, int new_state, char *old_plugin_output, int check_options, int reschedule_check, int use_cached_result, unsigned long check_timestamp_horizon) { +int process_host_check_result(host *hst, int new_state, char *old_plugin_output, int check_options, int reschedule_check, int use_cached_result, unsigned long check_timestamp_horizon) { hostsmember *temp_hostsmember = NULL; host *child_host = NULL; host *parent_host = NULL; host *master_host = NULL; - host *temp_host = NULL; - hostdependency *temp_dependency = NULL; - objectlist *check_hostlist = NULL; - objectlist *hostlist_item = NULL; - int parent_state = HOST_UP; time_t current_time = 0L; time_t next_check = 0L; time_t preferred_time = 0L; time_t next_valid_time = 0L; - int run_async_check = TRUE; - void *ptr = NULL; - log_debug_info(DEBUGL_FUNCTIONS, 0, "process_host_check_result_3x()\n"); + log_debug_info(DEBUGL_FUNCTIONS, 0, "process_host_check_result()\n"); - log_debug_info(DEBUGL_CHECKS, 1, "HOST: %s, ATTEMPT=%d/%d, CHECK TYPE=%s, STATE TYPE=%s, OLD STATE=%d, NEW STATE=%d\n", hst->name, hst->current_attempt, hst->max_attempts, (hst->check_type == HOST_CHECK_ACTIVE) ? "ACTIVE" : "PASSIVE", (hst->state_type == HARD_STATE) ? "HARD" : "SOFT", hst->current_state, new_state); + log_debug_info(DEBUGL_CHECKS, 1, "HOST: %s, ATTEMPT=%d/%d, CHECK TYPE=%s, STATE TYPE=%s, OLD STATE=%d, NEW STATE=%d\n", hst->name, hst->current_attempt, hst->max_attempts, (hst->check_type == CHECK_TYPE_ACTIVE) ? "ACTIVE" : "PASSIVE", (hst->state_type == HARD_STATE) ? "HARD" : "SOFT", hst->current_state, new_state); /* get the current time */ time(¤t_time); /* default next check time */ - next_check = (unsigned long)(current_time + (hst->check_interval * interval_length)); + next_check = current_time + normal_check_window(hst); /* we have to adjust current attempt # for passive checks, as it isn't done elsewhere */ - if(hst->check_type == HOST_CHECK_PASSIVE && passive_host_checks_are_soft == TRUE) - adjust_host_check_attempt_3x(hst, FALSE); + if(hst->check_type == CHECK_TYPE_PASSIVE && passive_host_checks_are_soft == TRUE) + adjust_host_check_attempt(hst, FALSE); /* log passive checks - we need to do this here, as some my bypass external commands by getting dropped in checkresults dir */ - if(hst->check_type == HOST_CHECK_PASSIVE) { + if(hst->check_type == CHECK_TYPE_PASSIVE) { if(log_passive_checks == TRUE) logit(NSLOG_PASSIVE_CHECK, FALSE, "PASSIVE HOST CHECK: %s;%d;%s\n", hst->name, new_state, hst->plugin_output); } @@ -3528,7 +2497,7 @@ int process_host_check_result_3x(host *hst, int new_state, char *old_plugin_outp /******* HOST WAS DOWN/UNREACHABLE INITIALLY *******/ if(hst->current_state != HOST_UP) { - log_debug_info(DEBUGL_CHECKS, 1, "Host was DOWN/UNREACHABLE.\n"); + log_debug_info(DEBUGL_CHECKS, 1, "Host was %s.\n", host_state_name(hst->current_state)); /***** HOST IS NOW UP *****/ /* the host just recovered! */ @@ -3539,7 +2508,7 @@ int process_host_check_result_3x(host *hst, int new_state, char *old_plugin_outp /* set the state type */ /* set state type to HARD for passive checks and active checks that were previously in a HARD STATE */ - if(hst->state_type == HARD_STATE || (hst->check_type == HOST_CHECK_PASSIVE && passive_host_checks_are_soft == FALSE)) + if(hst->state_type == HARD_STATE || (hst->check_type == CHECK_TYPE_PASSIVE && passive_host_checks_are_soft == FALSE)) hst->state_type = HARD_STATE; else hst->state_type = SOFT_STATE; @@ -3553,38 +2522,35 @@ int process_host_check_result_3x(host *hst, int new_state, char *old_plugin_outp /* propagate checks to immediate parents if they are not already UP */ /* we do this because a parent host (or grandparent) may have recovered somewhere and we should catch the recovery as soon as possible */ log_debug_info(DEBUGL_CHECKS, 1, "Propagating checks to parent host(s)...\n"); - for(temp_hostsmember = hst->parent_hosts; temp_hostsmember != NULL; temp_hostsmember = temp_hostsmember->next) { - if((parent_host = temp_hostsmember->host_ptr) == NULL) - continue; + parent_host = temp_hostsmember->host_ptr; if(parent_host->current_state != HOST_UP) { log_debug_info(DEBUGL_CHECKS, 1, "Check of parent host '%s' queued.\n", parent_host->name); - add_object_to_objectlist(&check_hostlist, (void *)parent_host); + schedule_host_check(parent_host, current_time, CHECK_OPTION_DEPENDENCY_CHECK); } } /* propagate checks to immediate children if they are not already UP */ /* we do this because children may currently be UNREACHABLE, but may (as a result of this recovery) switch to UP or DOWN states */ log_debug_info(DEBUGL_CHECKS, 1, "Propagating checks to child host(s)...\n"); - for(temp_hostsmember = hst->child_hosts; temp_hostsmember != NULL; temp_hostsmember = temp_hostsmember->next) { - if((child_host = temp_hostsmember->host_ptr) == NULL) - continue; + child_host = temp_hostsmember->host_ptr; if(child_host->current_state != HOST_UP) { log_debug_info(DEBUGL_CHECKS, 1, "Check of child host '%s' queued.\n", child_host->name); - add_object_to_objectlist(&check_hostlist, (void *)child_host); + schedule_host_check(child_host, current_time, CHECK_OPTION_DEPENDENCY_CHECK); } } + } /***** HOST IS STILL DOWN/UNREACHABLE *****/ /* we're still in a problem state... */ else { - log_debug_info(DEBUGL_CHECKS, 1, "Host is still DOWN/UNREACHABLE.\n"); + log_debug_info(DEBUGL_CHECKS, 1, "Host is still %s.\n", host_state_name(hst->current_state)); /* passive checks are treated as HARD states by default... */ - if(hst->check_type == HOST_CHECK_PASSIVE && passive_host_checks_are_soft == FALSE) { + if(hst->check_type == CHECK_TYPE_PASSIVE && passive_host_checks_are_soft == FALSE) { /* set the state type */ hst->state_type = HARD_STATE; @@ -3601,8 +2567,10 @@ int process_host_check_result_3x(host *hst, int new_state, char *old_plugin_outp if(hst->current_attempt == hst->max_attempts) hst->state_type = HARD_STATE; /* the host was in a hard problem state before, so it still is now */ - else if(hst->current_attempt == 1) + /* 2015-07-23 with the change adjust_host_check_attempt, this can no longer happen + else if(hst->current_attempt == 1) hst->state_type = HARD_STATE; + */ /* the host is in a soft state and the check will be retried */ else hst->state_type = SOFT_STATE; @@ -3611,7 +2579,7 @@ int process_host_check_result_3x(host *hst, int new_state, char *old_plugin_outp /* make a determination of the host's state */ /* translate host state between DOWN/UNREACHABLE (only for passive checks if enabled) */ hst->current_state = new_state; - if(hst->check_type == HOST_CHECK_ACTIVE || translate_passive_host_checks == TRUE) + if(hst->check_type == CHECK_TYPE_ACTIVE || translate_passive_host_checks == TRUE) hst->current_state = determine_host_reachability(hst); /* reschedule the next check if the host state changed */ @@ -3657,193 +2625,107 @@ int process_host_check_result_3x(host *hst, int new_state, char *old_plugin_outp /***** HOST IS NOW DOWN/UNREACHABLE *****/ else { - log_debug_info(DEBUGL_CHECKS, 1, "Host is now DOWN/UNREACHABLE.\n"); + log_debug_info(DEBUGL_CHECKS, 1, "Host is now %s.\n", host_state_name(hst->current_state)); - /***** SPECIAL CASE FOR HOSTS WITH MAX_ATTEMPTS==1 *****/ - if(hst->max_attempts == 1) { + /* active and (in some cases) passive check results are treated as SOFT states */ + if(hst->check_type == CHECK_TYPE_ACTIVE || passive_host_checks_are_soft == TRUE) { - log_debug_info(DEBUGL_CHECKS, 1, "Max attempts = 1!.\n"); + /* set the state type */ + hst->state_type = SOFT_STATE; + } + + /* by default, passive check results are treated as HARD states */ + else { /* set the state type */ hst->state_type = HARD_STATE; - /* host has maxed out on retries, so reschedule the next check at the normal interval */ - reschedule_check = TRUE; + /* reset the current attempt */ + hst->current_attempt = 1; + } + + /* make a (in some cases) preliminary determination of the host's state */ + /* translate host state between DOWN/UNREACHABLE (for passive checks only if enabled) */ + hst->current_state = new_state; + if(hst->check_type == CHECK_TYPE_ACTIVE || translate_passive_host_checks == TRUE) + hst->current_state = determine_host_reachability(hst); + + /* reschedule a check of the host */ + reschedule_check = TRUE; + + /* schedule a re-check of the host at the retry interval because we can't determine its final state yet... */ + if(hst->check_type == CHECK_TYPE_ACTIVE || passive_host_checks_are_soft == TRUE) + next_check = (unsigned long)(current_time + (hst->retry_interval * interval_length)); + + /* schedule a re-check of the host at the normal interval */ + else next_check = (unsigned long)(current_time + (hst->check_interval * interval_length)); - /* we need to run SYNCHRONOUS checks of all parent hosts to accurately determine the state of this host */ - /* this is extremely inefficient (reminiscent of Nagios 2.x logic), but there's no other good way around it */ - /* check all parent hosts to see if we're DOWN or UNREACHABLE */ - /* only do this for ACTIVE checks, as PASSIVE checks contain a pre-determined state */ - if(hst->check_type == HOST_CHECK_ACTIVE) { + /* propagate checks to immediate parents if they are UP */ + /* we do this because a parent host (or grandparent) may have gone down and blocked our route */ + /* checking the parents ASAP will allow us to better determine the final state (DOWN/UNREACHABLE) of this host later */ + log_debug_info(DEBUGL_CHECKS, 1, "Propagating checks to immediate parent hosts that are UP...\n"); - log_debug_info(DEBUGL_CHECKS, 1, "** WARNING: Max attempts = 1, so we have to run serial checks of all parent hosts!\n"); - - for(temp_hostsmember = hst->parent_hosts; temp_hostsmember != NULL; temp_hostsmember = temp_hostsmember->next) { - - if((parent_host = temp_hostsmember->host_ptr) == NULL) - continue; - - log_debug_info(DEBUGL_CHECKS, 1, "Running serial check parent host '%s'...\n", parent_host->name); - - /* run an immediate check of the parent host */ - run_sync_host_check_3x(parent_host, &parent_state, check_options, use_cached_result, check_timestamp_horizon); - - /* bail out as soon as we find one parent host that is UP */ - if(parent_state == HOST_UP) { - - log_debug_info(DEBUGL_CHECKS, 1, "Parent host is UP, so this one is DOWN.\n"); - - /* set the current state */ - hst->current_state = HOST_DOWN; - break; - } - } - - if(temp_hostsmember == NULL) { - /* host has no parents, so its up */ - if(hst->parent_hosts == NULL) { - log_debug_info(DEBUGL_CHECKS, 1, "Host has no parents, so it's DOWN.\n"); - hst->current_state = HOST_DOWN; - } - else { - /* no parents were up, so this host is UNREACHABLE */ - log_debug_info(DEBUGL_CHECKS, 1, "No parents were UP, so this host is UNREACHABLE.\n"); - hst->current_state = HOST_UNREACHABLE; - } - } - } - - /* set the host state for passive checks */ - else { - /* set the state */ - hst->current_state = new_state; - - /* translate host state between DOWN/UNREACHABLE for passive checks (if enabled) */ - /* make a determination of the host's state */ - if(translate_passive_host_checks == TRUE) - hst->current_state = determine_host_reachability(hst); - - } - - /* propagate checks to immediate children if they are not UNREACHABLE */ - /* we do this because we may now be blocking the route to child hosts */ - log_debug_info(DEBUGL_CHECKS, 1, "Propagating check to immediate non-UNREACHABLE child hosts...\n"); - - for(temp_hostsmember = hst->child_hosts; temp_hostsmember != NULL; temp_hostsmember = temp_hostsmember->next) { - if((child_host = temp_hostsmember->host_ptr) == NULL) - continue; - if(child_host->current_state != HOST_UNREACHABLE) { - log_debug_info(DEBUGL_CHECKS, 1, "Check of child host '%s' queued.\n", child_host->name); - add_object_to_objectlist(&check_hostlist, (void *)child_host); - } + for(temp_hostsmember = hst->parent_hosts; temp_hostsmember != NULL; temp_hostsmember = temp_hostsmember->next) { + parent_host = temp_hostsmember->host_ptr; + if(parent_host->current_state == HOST_UP) { + schedule_host_check(parent_host, current_time, CHECK_OPTION_DEPENDENCY_CHECK); + log_debug_info(DEBUGL_CHECKS, 1, "Check of host '%s' queued.\n", parent_host->name); } } - /***** MAX ATTEMPTS > 1 *****/ - else { - - /* active and (in some cases) passive check results are treated as SOFT states */ - if(hst->check_type == HOST_CHECK_ACTIVE || passive_host_checks_are_soft == TRUE) { - - /* set the state type */ - hst->state_type = SOFT_STATE; + /* propagate checks to immediate children if they are not UNREACHABLE */ + /* we do this because we may now be blocking the route to child hosts */ + log_debug_info(DEBUGL_CHECKS, 1, "Propagating checks to immediate non-UNREACHABLE child hosts...\n"); + for(temp_hostsmember = hst->child_hosts; temp_hostsmember != NULL; temp_hostsmember = temp_hostsmember->next) { + child_host = temp_hostsmember->host_ptr; + if(child_host->current_state != HOST_UNREACHABLE) { + log_debug_info(DEBUGL_CHECKS, 1, "Check of child host '%s' queued.\n", child_host->name); + schedule_host_check(child_host, current_time, CHECK_OPTION_NONE); } + } - /* by default, passive check results are treated as HARD states */ - else { + /* check dependencies on second to last host check */ + if(enable_predictive_host_dependency_checks == TRUE && hst->current_attempt == (hst->max_attempts - 1)) { + objectlist *list; - /* set the state type */ - hst->state_type = HARD_STATE; + /* propagate checks to hosts that THIS ONE depends on for notifications AND execution */ + /* we do to help ensure that the dependency checks are accurate before it comes time to notify */ + log_debug_info(DEBUGL_CHECKS, 1, "Propagating predictive dependency checks to hosts this one depends on...\n"); - /* reset the current attempt */ - hst->current_attempt = 1; - } - - /* make a (in some cases) preliminary determination of the host's state */ - /* translate host state between DOWN/UNREACHABLE (for passive checks only if enabled) */ - hst->current_state = new_state; - if(hst->check_type == HOST_CHECK_ACTIVE || translate_passive_host_checks == TRUE) - hst->current_state = determine_host_reachability(hst); - - /* reschedule a check of the host */ - reschedule_check = TRUE; - - /* schedule a re-check of the host at the retry interval because we can't determine its final state yet... */ - if(hst->check_type == HOST_CHECK_ACTIVE || passive_host_checks_are_soft == TRUE) - next_check = (unsigned long)(current_time + (hst->retry_interval * interval_length)); - - /* schedule a re-check of the host at the normal interval */ - else - next_check = (unsigned long)(current_time + (hst->check_interval * interval_length)); - - /* propagate checks to immediate parents if they are UP */ - /* we do this because a parent host (or grandparent) may have gone down and blocked our route */ - /* checking the parents ASAP will allow us to better determine the final state (DOWN/UNREACHABLE) of this host later */ - log_debug_info(DEBUGL_CHECKS, 1, "Propagating checks to immediate parent hosts that are UP...\n"); - - for(temp_hostsmember = hst->parent_hosts; temp_hostsmember != NULL; temp_hostsmember = temp_hostsmember->next) { - if((parent_host = temp_hostsmember->host_ptr) == NULL) - continue; - if(parent_host->current_state == HOST_UP) { - add_object_to_objectlist(&check_hostlist, (void *)parent_host); - log_debug_info(DEBUGL_CHECKS, 1, "Check of host '%s' queued.\n", parent_host->name); + for(list = hst->notify_deps; list; list = list->next) { + hostdependency *dep = (hostdependency *)list->object_ptr; + if(dep->dependent_host_ptr == hst && dep->master_host_ptr != NULL) { + master_host = (host *)dep->master_host_ptr; + log_debug_info(DEBUGL_CHECKS, 1, "Check of host '%s' queued.\n", master_host->name); + schedule_host_check(master_host, current_time, CHECK_OPTION_NONE); } } - - /* propagate checks to immediate children if they are not UNREACHABLE */ - /* we do this because we may now be blocking the route to child hosts */ - log_debug_info(DEBUGL_CHECKS, 1, "Propagating checks to immediate non-UNREACHABLE child hosts...\n"); - - for(temp_hostsmember = hst->child_hosts; temp_hostsmember != NULL; temp_hostsmember = temp_hostsmember->next) { - if((child_host = temp_hostsmember->host_ptr) == NULL) - continue; - if(child_host->current_state != HOST_UNREACHABLE) { - log_debug_info(DEBUGL_CHECKS, 1, "Check of child host '%s' queued.\n", child_host->name); - add_object_to_objectlist(&check_hostlist, (void *)child_host); - } - } - - /* check dependencies on second to last host check */ - if(enable_predictive_host_dependency_checks == TRUE && hst->current_attempt == (hst->max_attempts - 1)) { - - /* propagate checks to hosts that THIS ONE depends on for notifications AND execution */ - /* we do to help ensure that the dependency checks are accurate before it comes time to notify */ - log_debug_info(DEBUGL_CHECKS, 1, "Propagating predictive dependency checks to hosts this one depends on...\n"); - - for(temp_dependency = get_first_hostdependency_by_dependent_host(hst->name, &ptr); temp_dependency != NULL; temp_dependency = get_next_hostdependency_by_dependent_host(hst->name, &ptr)) { - if(temp_dependency->dependent_host_ptr == hst && temp_dependency->master_host_ptr != NULL) { - master_host = (host *)temp_dependency->master_host_ptr; - log_debug_info(DEBUGL_CHECKS, 1, "Check of host '%s' queued.\n", master_host->name); - add_object_to_objectlist(&check_hostlist, (void *)master_host); - } + for(list = hst->exec_deps; list; list = list->next) { + hostdependency *dep = (hostdependency *)list->object_ptr; + if(dep->dependent_host_ptr == hst && dep->master_host_ptr != NULL) { + master_host = (host *)dep->master_host_ptr; + log_debug_info(DEBUGL_CHECKS, 1, "Check of host '%s' queued.\n", master_host->name); + schedule_host_check(master_host, current_time, CHECK_OPTION_NONE); } } } } } - log_debug_info(DEBUGL_CHECKS, 1, "Pre-handle_host_state() Host: %s, Attempt=%d/%d, Type=%s, Final State=%d\n", hst->name, hst->current_attempt, hst->max_attempts, (hst->state_type == HARD_STATE) ? "HARD" : "SOFT", hst->current_state); + log_debug_info(DEBUGL_CHECKS, 1, "Pre-handle_host_state() Host: %s, Attempt=%d/%d, Type=%s, Final State=%d (%s)\n", hst->name, hst->current_attempt, hst->max_attempts, (hst->state_type == HARD_STATE) ? "HARD" : "SOFT", hst->current_state, host_state_name(hst->current_state)); /* handle the host state */ handle_host_state(hst); - log_debug_info(DEBUGL_CHECKS, 1, "Post-handle_host_state() Host: %s, Attempt=%d/%d, Type=%s, Final State=%d\n", hst->name, hst->current_attempt, hst->max_attempts, (hst->state_type == HARD_STATE) ? "HARD" : "SOFT", hst->current_state); + log_debug_info(DEBUGL_CHECKS, 1, "Post-handle_host_state() Host: %s, Attempt=%d/%d, Type=%s, Final State=%d (%s)\n", hst->name, hst->current_attempt, hst->max_attempts, (hst->state_type == HARD_STATE) ? "HARD" : "SOFT", hst->current_state, host_state_name(hst->current_state)); /******************** POST-PROCESSING STUFF *********************/ /* if the plugin output differs from previous check and no state change, log the current state/output if state stalking is enabled */ - if(hst->last_state == hst->current_state && compare_strings(old_plugin_output, hst->plugin_output)) { - - if(hst->current_state == HOST_UP && hst->stalk_on_up == TRUE) - log_host_event(hst); - - else if(hst->current_state == HOST_DOWN && hst->stalk_on_down == TRUE) - log_host_event(hst); - - else if(hst->current_state == HOST_UNREACHABLE && hst->stalk_on_unreachable == TRUE) - log_host_event(hst); + if(hst->last_state == hst->current_state && should_stalk(hst) && compare_strings(old_plugin_output, hst->plugin_output)) { + log_host_event(hst); } /* check to see if the associated host is flapping */ @@ -3870,6 +2752,13 @@ int process_host_check_result_3x(host *hst, int new_state, char *old_plugin_outp preferred_time = hst->next_check; get_next_valid_time(preferred_time, &next_valid_time, hst->check_period_ptr); hst->next_check = next_valid_time; + if(next_valid_time > preferred_time) { + /* Next valid time is further in the future because of timeperiod + * constraints. Add a random amount so we don't get all checks + * subject to that timeperiod constraint scheduled at the same time + */ + hst->next_check += ranged_urand(0, check_window(hst)); + } /* hosts with non-recurring intervals do not get rescheduled if we're in a HARD or UP state */ if(hst->check_interval == 0 && (hst->state_type == HARD_STATE || hst->current_state == HOST_UP)) @@ -3888,37 +2777,20 @@ int process_host_check_result_3x(host *hst, int new_state, char *old_plugin_outp /* update host status - for both active (scheduled) and passive (non-scheduled) hosts */ update_host_status(hst, FALSE); - /* run async checks of all hosts we added above */ - /* don't run a check if one is already executing or we can get by with a cached state */ - for(hostlist_item = check_hostlist; hostlist_item != NULL; hostlist_item = hostlist_item->next) { - run_async_check = TRUE; - temp_host = (host *)hostlist_item->object_ptr; - - log_debug_info(DEBUGL_CHECKS, 2, "ASYNC CHECK OF HOST: %s, CURRENTTIME: %lu, LASTHOSTCHECK: %lu, CACHEDTIMEHORIZON: %lu, USECACHEDRESULT: %d, ISEXECUTING: %d\n", temp_host->name, current_time, temp_host->last_check, check_timestamp_horizon, use_cached_result, temp_host->is_executing); - - if(use_cached_result == TRUE && ((current_time - temp_host->last_check) <= check_timestamp_horizon)) - run_async_check = FALSE; - if(temp_host->is_executing == TRUE) - run_async_check = FALSE; - if(run_async_check == TRUE) - run_async_host_check_3x(temp_host, CHECK_OPTION_NONE, 0.0, FALSE, FALSE, NULL, NULL); - } - free_objectlist(&check_hostlist); - return OK; } /* checks viability of performing a host check */ -int check_host_check_viability_3x(host *hst, int check_options, int *time_is_valid, time_t *new_time) { +int check_host_check_viability(host *hst, int check_options, int *time_is_valid, time_t *new_time) { int result = OK; int perform_check = TRUE; time_t current_time = 0L; time_t preferred_time = 0L; int check_interval = 0; - log_debug_info(DEBUGL_FUNCTIONS, 0, "check_host_check_viability_3x()\n"); + log_debug_info(DEBUGL_FUNCTIONS, 0, "check_host_check_viability()\n"); /* make sure we have a host */ if(hst == NULL) @@ -3951,6 +2823,7 @@ int check_host_check_viability_3x(host *hst, int check_options, int *time_is_val /* make sure this is a valid time to check the host */ if(check_time_against_period((unsigned long)current_time, hst->check_period_ptr) == ERROR) { + log_debug_info(DEBUGL_CHECKS, 0, "Timeperiod check failed\n"); preferred_time = current_time; if(time_is_valid) *time_is_valid = FALSE; @@ -3959,6 +2832,7 @@ int check_host_check_viability_3x(host *hst, int check_options, int *time_is_val /* check host dependencies for execution */ if(check_host_dependencies(hst, EXECUTION_DEPENDENCY) == DEPENDENCIES_FAILED) { + log_debug_info(DEBUGL_CHECKS, 0, "Host check dependencies failed\n"); preferred_time = current_time + check_interval; perform_check = FALSE; } @@ -3976,9 +2850,9 @@ int check_host_check_viability_3x(host *hst, int check_options, int *time_is_val /* adjusts current host check attempt before a new check is performed */ -int adjust_host_check_attempt_3x(host *hst, int is_active) { +int adjust_host_check_attempt(host *hst, int is_active) { - log_debug_info(DEBUGL_FUNCTIONS, 0, "adjust_host_check_attempt_3x()\n"); + log_debug_info(DEBUGL_FUNCTIONS, 0, "adjust_host_check_attempt()\n"); if(hst == NULL) return ERROR; @@ -3986,7 +2860,8 @@ int adjust_host_check_attempt_3x(host *hst, int is_active) { log_debug_info(DEBUGL_CHECKS, 2, "Adjusting check attempt number for host '%s': current attempt=%d/%d, state=%d, state type=%d\n", hst->name, hst->current_attempt, hst->max_attempts, hst->current_state, hst->state_type); /* if host is in a hard state, reset current attempt number */ - if(hst->state_type == HARD_STATE) + /* 2015-07-23 only reset current_attempt if host is up */ + if(hst->state_type == HARD_STATE && hst->current_state == HOST_UP) hst->current_attempt = 1; /* if host is in a soft UP state, reset current attempt number (active checks only) */ @@ -4007,53 +2882,48 @@ int adjust_host_check_attempt_3x(host *hst, int is_active) { /* determination of the host's state based on route availability*/ /* used only to determine difference between DOWN and UNREACHABLE states */ int determine_host_reachability(host *hst) { - int state = HOST_DOWN; host *parent_host = NULL; hostsmember *temp_hostsmember = NULL; - log_debug_info(DEBUGL_FUNCTIONS, 0, "determine_host_reachability()\n"); + log_debug_info(DEBUGL_FUNCTIONS, 0, "determine_host_reachability(host=%s)\n", hst ? hst->name : "(NULL host!)"); if(hst == NULL) return HOST_DOWN; - log_debug_info(DEBUGL_CHECKS, 2, "Determining state of host '%s': current state=%d\n", hst->name, hst->current_state); + log_debug_info(DEBUGL_CHECKS, 2, "Determining state of host '%s': current state=%d (%s)\n", hst->name, hst->current_state, host_state_name(hst->current_state)); /* host is UP - no translation needed */ if(hst->current_state == HOST_UP) { - state = HOST_UP; log_debug_info(DEBUGL_CHECKS, 2, "Host is UP, no state translation needed.\n"); + return HOST_UP; } /* host has no parents, so it is DOWN */ + if(hst->check_type == CHECK_TYPE_PASSIVE && hst->current_state == HOST_UNREACHABLE) { + log_debug_info(DEBUGL_CHECKS, 2, "Passive check so keep it UNREACHABLE.\n"); + return HOST_UNREACHABLE; + } else if(hst->parent_hosts == NULL) { - state = HOST_DOWN; log_debug_info(DEBUGL_CHECKS, 2, "Host has no parents, so it is DOWN.\n"); + return HOST_DOWN; } /* check all parent hosts to see if we're DOWN or UNREACHABLE */ else { - for(temp_hostsmember = hst->parent_hosts; temp_hostsmember != NULL; temp_hostsmember = temp_hostsmember->next) { - - if((parent_host = temp_hostsmember->host_ptr) == NULL) - continue; - + parent_host = temp_hostsmember->host_ptr; + log_debug_info(DEBUGL_CHECKS, 2, " Parent '%s' is %s\n", parent_host->name, host_state_name(parent_host->current_state)); /* bail out as soon as we find one parent host that is UP */ if(parent_host->current_state == HOST_UP) { /* set the current state */ - state = HOST_DOWN; log_debug_info(DEBUGL_CHECKS, 2, "At least one parent (%s) is up, so host is DOWN.\n", parent_host->name); - break; + return HOST_DOWN; } } - /* no parents were up, so this host is UNREACHABLE */ - if(temp_hostsmember == NULL) { - state = HOST_UNREACHABLE; - log_debug_info(DEBUGL_CHECKS, 2, "No parents were up, so host is UNREACHABLE.\n"); - } } - return state; + log_debug_info(DEBUGL_CHECKS, 2, "No parents were up, so host is UNREACHABLE.\n"); + return HOST_UNREACHABLE; } @@ -4081,8 +2951,8 @@ int handle_host_state(host *hst) { /* update performance data */ update_host_performance_data(hst); - /* record latest time for current state */ - switch(hst->current_state) { + /* record the time the last state ended */ + switch(hst->last_state) { case HOST_UP: hst->last_time_up = current_time; break; @@ -4107,8 +2977,8 @@ int handle_host_state(host *hst) { if(state_change == TRUE || hard_state_change == TRUE) { /* reset the next and last notification times */ - hst->last_host_notification = (time_t)0; - hst->next_host_notification = (time_t)0; + hst->last_notification = (time_t)0; + hst->next_notification = (time_t)0; /* reset notification suppression option */ hst->no_more_notifications = FALSE; @@ -4152,7 +3022,6 @@ int handle_host_state(host *hst) { /* update the problem id when transitioning to a problem state */ if(hst->last_state == HOST_UP) { /* don't reset last problem id, or it will be zero the next time a problem is encountered */ - /*hst->last_problem_id=hst->current_problem_id;*/ hst->current_problem_id = next_problem_id; next_problem_id++; } @@ -4168,8 +3037,7 @@ int handle_host_state(host *hst) { log_host_event(hst); /* check for start of flexible (non-fixed) scheduled downtime */ - /* CHANGED 08-05-2010 EG flex downtime can now start on soft states */ - /*if(hst->state_type==HARD_STATE)*/ + /* It can start on soft states */ check_pending_flex_host_downtime(hst); /* notify contacts about the recovery or problem if its a "hard" state */ @@ -4186,8 +3054,7 @@ int handle_host_state(host *hst) { /* the host recovered, so reset the current notification number and state flags (after the recovery notification has gone out) */ if(hst->current_state == HOST_UP) { hst->current_notification_number = 0; - hst->notified_on_down = FALSE; - hst->notified_on_unreachable = FALSE; + hst->notified_on = 0; } } @@ -4207,199 +3074,145 @@ int handle_host_state(host *hst) { } -/* parse raw plugin output and return: short and long output, perf data */ +/* Parses raw plugin output and returns: short and long output, perf data. */ int parse_check_output(char *buf, char **short_output, char **long_output, char **perf_data, int escape_newlines_please, int newlines_are_escaped) { int current_line = 0; - int found_newline = FALSE; int eof = FALSE; - int used_buf = 0; - int dbuf_chunk = 1024; - dbuf db1; - dbuf db2; - char *ptr = NULL; int in_perf_data = FALSE; - char *tempbuf = NULL; - register int x = 0; - register int y = 0; + const int dbuf_chunk = 1024; + dbuf long_text; + dbuf perf_text; + char *ptr = NULL; + int x = 0; + int y = 0; - /* initialize values */ - if(short_output) + /* Initialize output values. */ + if (short_output) *short_output = NULL; - if(long_output) + if (long_output) *long_output = NULL; - if(perf_data) + if (perf_data) *perf_data = NULL; - /* nothing to do */ - if(buf == NULL || !strcmp(buf, "")) + /* No input provided or no output requested, nothing to do. */ + if (!buf || !*buf || (!short_output && !long_output && !perf_data)) return OK; - used_buf = strlen(buf) + 1; - /* initialize dynamic buffers (1KB chunk size) */ - dbuf_init(&db1, dbuf_chunk); - dbuf_init(&db2, dbuf_chunk); + /* Initialize dynamic buffers (1KB chunk size). */ + dbuf_init(&long_text, dbuf_chunk); + dbuf_init(&perf_text, dbuf_chunk); - /* unescape newlines and escaped backslashes first */ - if(newlines_are_escaped == TRUE) { - for(x = 0, y = 0; buf[x] != '\x0'; x++) { - if(buf[x] == '\\' && buf[x + 1] == '\\') { + /* We should never need to worry about unescaping here again. We assume a + * common internal plugin output format that is newline delimited. */ + if (newlines_are_escaped) { + for (x = 0, y = 0; buf[x]; x++) { + if (buf[x] == '\\' && buf[x + 1] == '\\') { x++; buf[y++] = buf[x]; } - else if(buf[x] == '\\' && buf[x + 1] == 'n') { + else if (buf[x] == '\\' && buf[x + 1] == 'n') { x++; buf[y++] = '\n'; } else buf[y++] = buf[x]; } - buf[y] = '\x0'; + buf[y] = '\0'; } - /* process each line of input */ - for(x = 0; eof == FALSE; x++) { + /* Process each line of input. */ + for (x = 0; !eof && buf[0]; x++) { - /* we found the end of a line */ - if(buf[x] == '\n') - found_newline = TRUE; - else if(buf[x] == '\\' && buf[x + 1] == 'n' && newlines_are_escaped == TRUE) { - found_newline = TRUE; - buf[x] = '\x0'; - x++; - } - else if(buf[x] == '\x0') { - found_newline = TRUE; + /* Continue on until we reach the end of a line (or input). */ + if (buf[x] == '\n') + buf[x] = '\0'; + else if (buf[x] == '\0') eof = TRUE; - } else - found_newline = FALSE; + continue; - if(found_newline == TRUE) { + /* Handle this line of input. */ + current_line++; - current_line++; + /* The first line contains short plugin output and optional perf data. */ + if (current_line == 1) { - /* handle this line of input */ - buf[x] = '\x0'; - if((tempbuf = (char *)strdup(buf))) { - - /* first line contains short plugin output and optional perf data */ - if(current_line == 1) { - - /* get the short plugin output */ - if((ptr = strtok(tempbuf, "|"))) { - if(short_output) - *short_output = (char *)strdup(ptr); - - /* get the optional perf data */ - if((ptr = strtok(NULL, "\n"))) - dbuf_strcat(&db2, ptr); - } + /* Get the short plugin output. If buf[0] is '|', strtok() will + * return buf+1 or NULL if buf[1] is '\0'. We use my_strtok() + * instead which returns a pointer to '\0' in this case. */ + if ((ptr = my_strtok(buf, "|"))) { + if (short_output) { + strip(ptr); /* Remove leading and trailing whitespace. */ + *short_output = strdup(ptr); } - /* additional lines contain long plugin output and optional perf data */ - else { - - /* rest of the output is perf data */ - if(in_perf_data == TRUE) { - dbuf_strcat(&db2, tempbuf); - dbuf_strcat(&db2, " "); - } - - /* we're still in long output */ - else { - - /* perf data separator has been found */ - if(strstr(tempbuf, "|")) { - - /* NOTE: strtok() causes problems if first character of tempbuf='|', so use my_strtok() instead */ - /* get the remaining long plugin output */ - if((ptr = my_strtok(tempbuf, "|"))) { - - if(current_line > 2) - dbuf_strcat(&db1, "\n"); - dbuf_strcat(&db1, ptr); - - /* get the perf data */ - if((ptr = my_strtok(NULL, "\n"))) { - dbuf_strcat(&db2, ptr); - dbuf_strcat(&db2, " "); - } - } - - /* set the perf data flag */ - in_perf_data = TRUE; - } - - /* just long output */ - else { - if(current_line > 2) - dbuf_strcat(&db1, "\n"); - dbuf_strcat(&db1, tempbuf); - } - } - } - - my_free(tempbuf); - tempbuf = NULL; + /* Get the optional perf data. */ + if ((ptr = my_strtok(NULL, "\n"))) + dbuf_strcat(&perf_text, ptr); } - - /* shift data back to front of buffer and adjust counters */ - memmove((void *)&buf[0], (void *)&buf[x + 1], (size_t)((int)used_buf - x - 1)); - used_buf -= (x + 1); - buf[used_buf] = '\x0'; - x = -1; } - } + /* Additional lines contain long plugin output and optional perf data. + * Once we've hit perf data, the rest of the output is perf data. */ + else if (in_perf_data) { + if (perf_text.buf && *perf_text.buf) + dbuf_strcat(&perf_text, " "); + dbuf_strcat(&perf_text, buf); - /* save long output */ - if(long_output && (db1.buf && strcmp(db1.buf, ""))) { + } + /* Look for the perf data separator. */ + else if (strchr(buf, '|')) { + in_perf_data = TRUE; - if(escape_newlines_please == FALSE) - *long_output = (char *)strdup(db1.buf); + if ((ptr = my_strtok(buf, "|"))) { + /* Get the remaining long plugin output. */ + if (current_line > 2) + dbuf_strcat(&long_text, "\n"); + dbuf_strcat(&long_text, ptr); + + /* Get the perf data. */ + if ((ptr = my_strtok(NULL, "\n"))) { + if (perf_text.buf && *perf_text.buf) + dbuf_strcat(&perf_text, " "); + dbuf_strcat(&perf_text, ptr); + } + } + + } + /* Otherwise it's still just long output. */ else { - - /* escape newlines (and backslashes) in long output */ - if((tempbuf = (char *)malloc((strlen(db1.buf) * 2) + 1))) { - - for(x = 0, y = 0; db1.buf[x] != '\x0'; x++) { - - if(db1.buf[x] == '\n') { - tempbuf[y++] = '\\'; - tempbuf[y++] = 'n'; - } - else if(db1.buf[x] == '\\') { - tempbuf[y++] = '\\'; - tempbuf[y++] = '\\'; - } - else - tempbuf[y++] = db1.buf[x]; - } - - tempbuf[y] = '\x0'; - *long_output = (char *)strdup(tempbuf); - my_free(tempbuf); - } + if (current_line > 2) + dbuf_strcat(&long_text, "\n"); + dbuf_strcat(&long_text, buf); } + + /* Point buf to the start of the next line. *(buf+x+1) will be a valid + * memory reference on our next iteration or we are at the end of input + * (eof == TRUE) and *(buf+x+1) will never be referenced. */ + buf += x + 1; + x = -1; /* x will be incremented to 0 by the loop update. */ } - /* save perf data */ - if(perf_data && (db2.buf && strcmp(db2.buf, ""))) - *perf_data = (char *)strdup(db2.buf); + /* Save long output. */ + if (long_output && long_text.buf && *long_text.buf) { + /* Escape newlines (and backslashes) in long output if requested. */ + if (escape_newlines_please) + *long_output = escape_newlines(long_text.buf); + else + *long_output = strdup(long_text.buf); + } - /* strip short output and perf data */ - if(short_output) - strip(*short_output); - if(perf_data) - strip(*perf_data); + /* Save perf data. */ + if (perf_data && perf_text.buf && *perf_text.buf) { + strip(perf_text.buf); /* Remove leading and trailing whitespace. */ + *perf_data = strdup(perf_text.buf); + } /* free dynamic buffers */ - dbuf_free(&db1); - dbuf_free(&db2); + dbuf_free(&long_text); + dbuf_free(&perf_text); return OK; } - - diff --git a/base/commands.c b/base/commands.c index 48640d5..1381317 100644 --- a/base/commands.c +++ b/base/commands.c @@ -2,8 +2,6 @@ * * COMMANDS.C - External command functions for Nagios * - * Copyright (c) 1999-2008 Ethan Galstad (egalstad@nagios.org) - * Last Modified: 11-30-2008 * * License: * @@ -31,145 +29,310 @@ #include "../include/sretention.h" #include "../include/broker.h" #include "../include/nagios.h" +#include "../include/workers.h" -extern char *config_file; -extern char *log_file; -extern char *command_file; -extern char *temp_file; -extern char *temp_path; -extern int sigshutdown; -extern int sigrestart; +extern int sigrestart; -extern int check_external_commands; - -extern int ipc_pipe[2]; - -extern time_t last_command_check; -extern time_t last_command_status_update; - -extern int command_check_interval; - -extern int enable_notifications; -extern int execute_service_checks; -extern int accept_passive_service_checks; -extern int execute_host_checks; -extern int accept_passive_host_checks; -extern int enable_event_handlers; -extern int obsess_over_services; -extern int obsess_over_hosts; -extern int check_service_freshness; -extern int check_host_freshness; -extern int enable_failure_prediction; -extern int process_performance_data; - -extern int log_external_commands; -extern int log_passive_checks; - -extern unsigned long modified_host_process_attributes; -extern unsigned long modified_service_process_attributes; - -extern char *global_host_event_handler; -extern char *global_service_event_handler; -extern command *global_host_event_handler_ptr; -extern command *global_service_event_handler_ptr; - -extern host *host_list; -extern service *service_list; - -extern FILE *command_file_fp; -extern int command_file_fd; - -passive_check_result *passive_check_result_list = NULL; -passive_check_result *passive_check_result_list_tail = NULL; - -extern pthread_t worker_threads[TOTAL_WORKER_THREADS]; -extern circular_buffer external_command_buffer; -extern int external_command_buffer_slots; +static int command_file_fd; +static FILE *command_file_fp; +static int command_file_created = FALSE; +/* The command file worker process */ +static struct { + /* these must come first for check source detection */ + const char *type; + const char *source_name; + int pid; + int sd; + iocache *ioc; +} command_worker = { "command file", "command file worker", 0, 0, NULL }; /******************************************************************/ -/****************** EXTERNAL COMMAND PROCESSING *******************/ +/************* EXTERNAL COMMAND WORKER CONTROLLERS ****************/ /******************************************************************/ -/* checks for the existence of the external command file and processes all commands found in it */ -int check_for_external_commands(void) { - char *buffer = NULL; - int update_status = FALSE; +/* creates external command file as a named pipe (FIFO) and opens it for reading (non-blocked mode) */ +int open_command_file(void) { + struct stat st; + int result = 0; - log_debug_info(DEBUGL_FUNCTIONS, 0, "check_for_external_commands()\n"); - - /* bail out if we shouldn't be checking for external commands */ + /* if we're not checking external commands, don't do anything */ if(check_external_commands == FALSE) - return ERROR; + return OK; - /* update last command check time */ - last_command_check = time(NULL); + /* the command file was already created */ + if(command_file_created == TRUE) + return OK; - /* update the status log with new program information */ - /* go easy on the frequency of this if we're checking often - only update program status every 10 seconds.... */ - if(last_command_check < (last_command_status_update + 10)) - update_status = FALSE; - else - update_status = TRUE; - if(update_status == TRUE) { - last_command_status_update = last_command_check; - update_program_status(FALSE); - } + /* reset umask (group needs write permissions) */ + umask(S_IWOTH); - /* reset passive check result list pointers */ - passive_check_result_list = NULL; - passive_check_result_list_tail = NULL; + /* use existing FIFO if possible */ + if(!(stat(command_file, &st) != -1 && (st.st_mode & S_IFIFO))) { - /* process all commands found in the buffer */ - while(1) { + /* create the external command file as a named pipe (FIFO) */ + if((result = mkfifo(command_file, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP)) != 0) { - /* get a lock on the buffer */ - pthread_mutex_lock(&external_command_buffer.buffer_lock); - - /* if no items present, bail out */ - if(external_command_buffer.items <= 0) { - pthread_mutex_unlock(&external_command_buffer.buffer_lock); - break; + logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Could not create external command file '%s' as named pipe: (%d) -> %s. If this file already exists and you are sure that another copy of Nagios is not running, you should delete this file.\n", command_file, errno, strerror(errno)); + return ERROR; } - - if(external_command_buffer.buffer[external_command_buffer.tail]) - buffer = strdup(((char **)external_command_buffer.buffer)[external_command_buffer.tail]); - - /* free memory allocated for buffer slot */ - my_free(((char **)external_command_buffer.buffer)[external_command_buffer.tail]); - - /* adjust tail counter and number of items */ - external_command_buffer.tail = (external_command_buffer.tail + 1) % external_command_buffer_slots; - external_command_buffer.items--; - - /* release the lock on the buffer */ - pthread_mutex_unlock(&external_command_buffer.buffer_lock); - - /* process the command */ - process_external_command1(buffer); - - /* free memory */ - my_free(buffer); } - /**** PROCESS ALL PASSIVE HOST AND SERVICE CHECK RESULTS AT ONE TIME ****/ - if(passive_check_result_list != NULL) - process_passive_checks(); + /* open the command file for reading (non-blocked) - O_TRUNC flag cannot be used due to errors on some systems */ + /* NOTE: file must be opened read-write for poll() to work */ + if((command_file_fd = open(command_file, O_RDWR | O_NONBLOCK)) < 0) { + + logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Could not open external command file for reading via open(): (%d) -> %s\n", errno, strerror(errno)); + + return ERROR; + } + + /* set a flag to remember we already created the file */ + command_file_created = TRUE; return OK; } +/* closes the external command file FIFO and deletes it */ +int close_command_file(void) { + + /* if we're not checking external commands, don't do anything */ + if(check_external_commands == FALSE) + return OK; + + /* the command file wasn't created or was already cleaned up */ + if(command_file_created == FALSE) + return OK; + + /* reset our flag */ + command_file_created = FALSE; + + /* close the command file */ + fclose(command_file_fp); + + return OK; + } + + +/* shutdown command file worker thread */ +int shutdown_command_file_worker(void) { + if (!command_worker.pid) + return 0; + + iocache_destroy(command_worker.ioc); + command_worker.ioc = NULL; + iobroker_close(nagios_iobs, command_worker.sd); + command_worker.sd = -1; + kill(command_worker.pid, SIGKILL); + command_worker.pid = 0; + return 0; + } + + +static int command_input_handler(int sd, int events, void *discard) { + int ret, cmd_ret; + char *buf; + unsigned long size; + + if (sigrestart) + return 0; + + ret = iocache_read(command_worker.ioc, sd); + log_debug_info(DEBUGL_COMMANDS, 2, "Read %d bytes from command worker\n", ret); + if (ret == 0) { + logit(NSLOG_RUNTIME_WARNING, TRUE, "Command file worker seems to have died. Respawning\n"); + shutdown_command_file_worker(); + launch_command_file_worker(); + return 0; + } + while ((buf = iocache_use_delim(command_worker.ioc, "\n", 1, &size))) { + if (buf[0] == '[') { + /* raw external command */ + buf[size] = 0; + log_debug_info(DEBUGL_COMMANDS, 1, "Read raw external command '%s'\n", buf); + } + + if ((cmd_ret = process_external_command1(buf)) != CMD_ERROR_OK) { + logit(NSLOG_EXTERNAL_COMMAND | NSLOG_RUNTIME_WARNING, TRUE, "External command error: %s\n", cmd_error_strerror(cmd_ret)); + } + + } + return 0; + } + + +/* main controller of command file helper process */ +static int command_file_worker(int sd) { + iocache *ioc; + + if (open_command_file() == ERROR) + return (EXIT_FAILURE); + + ioc = iocache_create(65536); + if (!ioc) + exit(EXIT_FAILURE); + + while(1) { + struct pollfd pfd; + int pollval, ret; + char *buf; + unsigned long size; + + /* if our master has gone away, we need to die */ + if (kill(nagios_pid, 0) < 0 && errno == ESRCH) { + return EXIT_SUCCESS; + } + + errno = 0; + /* wait for data to arrive */ + /* select seems to not work, so we have to use poll instead */ + /* 10-15-08 EG check into implementing William's patch @ http://blog.netways.de/2008/08/15/nagios-unter-mac-os-x-installieren/ */ + /* 10-15-08 EG poll() seems broken on OSX - see Jonathan's patch a few lines down */ + pfd.fd = command_file_fd; + pfd.events = POLLIN; + pollval = poll(&pfd, 1, 500); + + /* loop if no data */ + if(pollval == 0) + continue; + + /* check for errors */ + if(pollval == -1) { + /* @todo printf("Failed to poll() command file pipe: %m\n"); */ + if (errno == EINTR) + continue; + return EXIT_FAILURE; + } + + errno = 0; + ret = iocache_read(ioc, command_file_fd); + if (ret < 1) { + if (errno == EINTR) + continue; + return EXIT_FAILURE; + } + + size = iocache_available(ioc); + buf = iocache_use_size(ioc, size); + ret = write(sd, buf, size); + /* + * @todo Add libio to get io_write_all(), which handles + * EINTR and EAGAIN properly instead of just exiting. + */ + if (ret < 0 && errno != EINTR) + return EXIT_FAILURE; + } /* while(1) */ + } + + +int launch_command_file_worker(void) { + int ret, sv[2]; + char *str; +#ifdef HAVE_SIGACTION + struct sigaction sig_action; +#endif + + /* + * if we're restarting, we may well already have a command + * file worker process attached. Keep it if that's so. + */ + if (command_worker.pid && kill(command_worker.pid, 0) == 0 && + iobroker_is_registered(nagios_iobs, command_worker.sd)) + { + return 0; + } + + if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) < 0) { + logit(NSLOG_RUNTIME_ERROR, TRUE, "Failed to create socketpair for command file worker: %m\n"); + return ERROR; + } + + command_worker.pid = fork(); + if (command_worker.pid < 0) { + logit(NSLOG_RUNTIME_ERROR, TRUE, "Failed to fork() command file worker: %m\n"); + goto err_close; + } + + if (command_worker.pid) { + command_worker.ioc = iocache_create(512 * 1024); + if (!command_worker.ioc) { + logit(NSLOG_RUNTIME_ERROR, TRUE, "Failed to create I/O cache for command file worker: %m\n"); + goto err_close; + } + + command_worker.sd = sv[0]; + ret = iobroker_register(nagios_iobs, command_worker.sd, NULL, command_input_handler); + if (ret < 0) { + logit(NSLOG_RUNTIME_ERROR, TRUE, "Failed to register command file worker socket %d with io broker %p: %s; errno=%d: %s\n", + command_worker.sd, nagios_iobs, iobroker_strerror(ret), errno, strerror(errno)); + iocache_destroy(command_worker.ioc); + goto err_close; + } + logit(NSLOG_INFO_MESSAGE, TRUE, "Successfully launched command file worker with pid %d\n", + command_worker.pid); + return OK; + } + + /* child goes here */ + close(sv[0]); + + /* make our own process-group so we can be traced into and stuff */ + setpgid(0, 0); + + /* we must preserve command_file before nuking memory */ + (void)chdir("/tmp"); + (void)chdir("nagios-cfw"); + str = strdup(command_file); + free_memory(get_global_macros()); + command_file = str; +#ifdef HAVE_SIGACTION + sig_action.sa_sigaction = NULL; + sig_action.sa_handler = SIG_IGN; + sigemptyset(&sig_action.sa_mask); + sig_action.sa_flags = 0; + sigaction(SIGPIPE, &sig_action, NULL); +#else + signal(SIGPIPE, SIG_IGN); +#endif + exit(command_file_worker(sv[1])); + + /* error conditions for parent */ +err_close: + close(sv[0]); + close(sv[1]); + command_worker.pid = 0; + command_worker.sd = -1; + return ERROR; + } + +/******************************************************************/ +/****************** EXTERNAL COMMAND PROCESSING *******************/ +/******************************************************************/ + +/*** stupid helpers ****/ +static host *find_host_by_name_or_address(const char *name) +{ + host *h; + + if ((h = find_host(name)) || !name) + return h; + + for (h = host_list; h; h = h->next) + if (!strcmp(h->address, name)) + return h; + + return NULL; +} /* processes all external commands in a (regular) file */ int process_external_commands_from_file(char *fname, int delete_file) { mmapfile *thefile = NULL; char *input = NULL; - log_debug_info(DEBUGL_FUNCTIONS, 0, "process_external_commands_from_file()\n"); if(fname == NULL) @@ -217,11 +380,12 @@ int process_external_command1(char *cmd) { time_t entry_time = 0L; int command_type = CMD_NONE; char *temp_ptr = NULL; + int external_command_ret = OK; log_debug_info(DEBUGL_FUNCTIONS, 0, "process_external_command1()\n"); if(cmd == NULL) - return ERROR; + return CMD_ERROR_MALFORMED_COMMAND; /* strip the command of newlines and carriage returns */ strip(cmd); @@ -230,16 +394,16 @@ int process_external_command1(char *cmd) { /* get the command entry time */ if((temp_ptr = my_strtok(cmd, "[")) == NULL) - return ERROR; + return CMD_ERROR_MALFORMED_COMMAND; if((temp_ptr = my_strtok(NULL, "]")) == NULL) - return ERROR; + return CMD_ERROR_MALFORMED_COMMAND; entry_time = (time_t)strtoul(temp_ptr, NULL, 10); /* get the command identifier */ if((temp_ptr = my_strtok(NULL, ";")) == NULL) - return ERROR; + return CMD_ERROR_MALFORMED_COMMAND; if((command_id = (char *)strdup(temp_ptr + 1)) == NULL) - return ERROR; + return CMD_ERROR_INTERNAL_ERROR; /* get the command arguments */ if((temp_ptr = my_strtok(NULL, "\n")) == NULL) @@ -248,7 +412,7 @@ int process_external_command1(char *cmd) { args = (char *)strdup(temp_ptr); if(args == NULL) { my_free(command_id); - return ERROR; + return CMD_ERROR_INTERNAL_ERROR; } /* decide what type of command this is... */ @@ -277,14 +441,6 @@ int process_external_command1(char *cmd) { else if(!strcmp(command_id, "DISABLE_EVENT_HANDLERS")) command_type = CMD_DISABLE_EVENT_HANDLERS; - else if(!strcmp(command_id, "FLUSH_PENDING_COMMANDS")) - command_type = CMD_FLUSH_PENDING_COMMANDS; - - else if(!strcmp(command_id, "ENABLE_FAILURE_PREDICTION")) - command_type = CMD_ENABLE_FAILURE_PREDICTION; - else if(!strcmp(command_id, "DISABLE_FAILURE_PREDICTION")) - command_type = CMD_DISABLE_FAILURE_PREDICTION; - else if(!strcmp(command_id, "ENABLE_PERFORMANCE_DATA")) command_type = CMD_ENABLE_PERFORMANCE_DATA; else if(!strcmp(command_id, "DISABLE_PERFORMANCE_DATA")) @@ -470,6 +626,8 @@ int process_external_command1(char *cmd) { else if(!strcmp(command_id, "CHANGE_HOST_MODATTR")) command_type = CMD_CHANGE_HOST_MODATTR; + else if (!strcmp(command_id,"CLEAR_HOST_FLAPPING_STATE")) + command_type = CMD_CLEAR_HOST_FLAPPING_STATE; /************************************/ /**** HOSTGROUP-RELATED COMMANDS ****/ @@ -608,6 +766,8 @@ int process_external_command1(char *cmd) { else if(!strcmp(command_id, "CHANGE_SVC_MODATTR")) command_type = CMD_CHANGE_SVC_MODATTR; + else if (!strcmp(command_id,"CLEAR_SVC_FLAPPING_STATE")) + command_type = CMD_CLEAR_SVC_FLAPPING_STATE; /***************************************/ /**** SERVICEGROUP-RELATED COMMANDS ****/ @@ -718,7 +878,7 @@ int process_external_command1(char *cmd) { my_free(command_id); my_free(args); - return ERROR; + return CMD_ERROR_UNKNOWN_COMMAND; } /* update statistics for external commands */ @@ -743,7 +903,11 @@ int process_external_command1(char *cmd) { #endif /* process the command */ - process_external_command2(command_type, entry_time, args); + external_command_ret = (process_external_command2(command_type, entry_time, args) == OK) ? CMD_ERROR_OK : CMD_ERROR_FAILURE; + if (external_command_ret != CMD_ERROR_OK) { + logit(NSLOG_EXTERNAL_COMMAND | NSLOG_RUNTIME_WARNING, TRUE, "Error: External command failed -> %s;%s\n", command_id, args); + } + #ifdef USE_EVENT_BROKER /* send data to event broker */ @@ -754,14 +918,29 @@ int process_external_command1(char *cmd) { my_free(command_id); my_free(args); - return OK; + return external_command_ret; } - +const char *cmd_error_strerror(int code) { + switch(code) { + case CMD_ERROR_OK: + return "No error"; + case CMD_ERROR_FAILURE: + return "Command failed"; + case CMD_ERROR_INTERNAL_ERROR: + return "Internal error"; + case CMD_ERROR_UNKNOWN_COMMAND: + return "Unknown or unsupported command"; + case CMD_ERROR_MALFORMED_COMMAND: + return "Malformed command"; + } + return "Unknown error"; + } /* top-level processor for a single external command */ int process_external_command2(int cmd, time_t entry_time, char *args) { + int ret = OK; log_debug_info(DEBUGL_FUNCTIONS, 0, "process_external_command2()\n"); log_debug_info(DEBUGL_EXTERNALCOMMANDS, 1, "External Command Type: %d\n", cmd); @@ -777,15 +956,15 @@ int process_external_command2(int cmd, time_t entry_time, char *args) { case CMD_SHUTDOWN_PROCESS: case CMD_RESTART_PROCESS: - cmd_signal_process(cmd, args); + ret = cmd_signal_process(cmd, args); break; case CMD_SAVE_STATE_INFORMATION: - save_state_information(FALSE); + ret = save_state_information(FALSE); break; case CMD_READ_STATE_INFORMATION: - read_initial_state_information(); + ret = read_initial_state_information(); break; case CMD_ENABLE_NOTIFICATIONS: @@ -876,14 +1055,6 @@ int process_external_command2(int cmd, time_t entry_time, char *args) { disable_host_freshness_checks(); break; - case CMD_ENABLE_FAILURE_PREDICTION: - enable_all_failure_prediction(); - break; - - case CMD_DISABLE_FAILURE_PREDICTION: - disable_all_failure_prediction(); - break; - case CMD_ENABLE_PERFORMANCE_DATA: enable_performance_data(); break; @@ -919,7 +1090,8 @@ int process_external_command2(int cmd, time_t entry_time, char *args) { case CMD_STOP_OBSESSING_OVER_HOST: case CMD_SET_HOST_NOTIFICATION_NUMBER: case CMD_SEND_CUSTOM_HOST_NOTIFICATION: - process_host_command(cmd, entry_time, args); + case CMD_CLEAR_HOST_FLAPPING_STATE: + ret = process_host_command(cmd, entry_time, args); break; @@ -939,7 +1111,7 @@ int process_external_command2(int cmd, time_t entry_time, char *args) { case CMD_DISABLE_HOSTGROUP_SVC_CHECKS: case CMD_ENABLE_HOSTGROUP_PASSIVE_SVC_CHECKS: case CMD_DISABLE_HOSTGROUP_PASSIVE_SVC_CHECKS: - process_hostgroup_command(cmd, entry_time, args); + ret = process_hostgroup_command(cmd, entry_time, args); break; @@ -961,7 +1133,8 @@ int process_external_command2(int cmd, time_t entry_time, char *args) { case CMD_STOP_OBSESSING_OVER_SVC: case CMD_SET_SVC_NOTIFICATION_NUMBER: case CMD_SEND_CUSTOM_SVC_NOTIFICATION: - process_service_command(cmd, entry_time, args); + case CMD_CLEAR_SVC_FLAPPING_STATE: + ret = process_service_command(cmd, entry_time, args); break; @@ -981,7 +1154,7 @@ int process_external_command2(int cmd, time_t entry_time, char *args) { case CMD_DISABLE_SERVICEGROUP_SVC_CHECKS: case CMD_ENABLE_SERVICEGROUP_PASSIVE_SVC_CHECKS: case CMD_DISABLE_SERVICEGROUP_PASSIVE_SVC_CHECKS: - process_servicegroup_command(cmd, entry_time, args); + ret = process_servicegroup_command(cmd, entry_time, args); break; @@ -993,7 +1166,7 @@ int process_external_command2(int cmd, time_t entry_time, char *args) { case CMD_DISABLE_CONTACT_HOST_NOTIFICATIONS: case CMD_ENABLE_CONTACT_SVC_NOTIFICATIONS: case CMD_DISABLE_CONTACT_SVC_NOTIFICATIONS: - process_contact_command(cmd, entry_time, args); + ret = process_contact_command(cmd, entry_time, args); break; @@ -1005,7 +1178,7 @@ int process_external_command2(int cmd, time_t entry_time, char *args) { case CMD_DISABLE_CONTACTGROUP_HOST_NOTIFICATIONS: case CMD_ENABLE_CONTACTGROUP_SVC_NOTIFICATIONS: case CMD_DISABLE_CONTACTGROUP_SVC_NOTIFICATIONS: - process_contactgroup_command(cmd, entry_time, args); + ret = process_contactgroup_command(cmd, entry_time, args); break; @@ -1016,50 +1189,50 @@ int process_external_command2(int cmd, time_t entry_time, char *args) { case CMD_ADD_HOST_COMMENT: case CMD_ADD_SVC_COMMENT: - cmd_add_comment(cmd, entry_time, args); + ret= cmd_add_comment(cmd, entry_time, args); break; case CMD_DEL_HOST_COMMENT: case CMD_DEL_SVC_COMMENT: - cmd_delete_comment(cmd, args); + ret = cmd_delete_comment(cmd, args); break; case CMD_DELAY_HOST_NOTIFICATION: case CMD_DELAY_SVC_NOTIFICATION: - cmd_delay_notification(cmd, args); + ret = cmd_delay_notification(cmd, args); break; case CMD_SCHEDULE_SVC_CHECK: case CMD_SCHEDULE_FORCED_SVC_CHECK: - cmd_schedule_check(cmd, args); + ret =cmd_schedule_check(cmd, args); break; case CMD_SCHEDULE_HOST_SVC_CHECKS: case CMD_SCHEDULE_FORCED_HOST_SVC_CHECKS: - cmd_schedule_check(cmd, args); + ret = cmd_schedule_check(cmd, args); break; case CMD_DEL_ALL_HOST_COMMENTS: case CMD_DEL_ALL_SVC_COMMENTS: - cmd_delete_all_comments(cmd, args); + ret = cmd_delete_all_comments(cmd, args); break; case CMD_PROCESS_SERVICE_CHECK_RESULT: - cmd_process_service_check_result(cmd, entry_time, args); + ret = cmd_process_service_check_result(cmd, entry_time, args); break; case CMD_PROCESS_HOST_CHECK_RESULT: - cmd_process_host_check_result(cmd, entry_time, args); + ret = cmd_process_host_check_result(cmd, entry_time, args); break; case CMD_ACKNOWLEDGE_HOST_PROBLEM: case CMD_ACKNOWLEDGE_SVC_PROBLEM: - cmd_acknowledge_problem(cmd, args); + ret = cmd_acknowledge_problem(cmd, args); break; case CMD_REMOVE_HOST_ACKNOWLEDGEMENT: case CMD_REMOVE_SVC_ACKNOWLEDGEMENT: - cmd_remove_acknowledgement(cmd, args); + ret = cmd_remove_acknowledgement(cmd, args); break; case CMD_SCHEDULE_HOST_DOWNTIME: @@ -1071,33 +1244,29 @@ int process_external_command2(int cmd, time_t entry_time, char *args) { case CMD_SCHEDULE_SERVICEGROUP_SVC_DOWNTIME: case CMD_SCHEDULE_AND_PROPAGATE_HOST_DOWNTIME: case CMD_SCHEDULE_AND_PROPAGATE_TRIGGERED_HOST_DOWNTIME: - cmd_schedule_downtime(cmd, entry_time, args); + ret = cmd_schedule_downtime(cmd, entry_time, args); break; case CMD_DEL_HOST_DOWNTIME: case CMD_DEL_SVC_DOWNTIME: - cmd_delete_downtime(cmd, args); + ret = cmd_delete_downtime(cmd, args); break; case CMD_DEL_DOWNTIME_BY_HOST_NAME: - cmd_delete_downtime_by_host_name(cmd, args); + ret = cmd_delete_downtime_by_host_name(cmd, args); break; case CMD_DEL_DOWNTIME_BY_HOSTGROUP_NAME: - cmd_delete_downtime_by_hostgroup_name(cmd, args); + ret = cmd_delete_downtime_by_hostgroup_name(cmd, args); break; case CMD_DEL_DOWNTIME_BY_START_TIME_COMMENT: - cmd_delete_downtime_by_start_time_comment(cmd, args); - break; - - case CMD_CANCEL_ACTIVE_HOST_SVC_DOWNTIME: - case CMD_CANCEL_PENDING_HOST_SVC_DOWNTIME: + ret = cmd_delete_downtime_by_start_time_comment(cmd, args); break; case CMD_SCHEDULE_HOST_CHECK: case CMD_SCHEDULE_FORCED_HOST_CHECK: - cmd_schedule_check(cmd, args); + ret = cmd_schedule_check(cmd, args); break; case CMD_CHANGE_GLOBAL_HOST_EVENT_HANDLER: @@ -1112,7 +1281,7 @@ int process_external_command2(int cmd, time_t entry_time, char *args) { case CMD_CHANGE_SVC_NOTIFICATION_TIMEPERIOD: case CMD_CHANGE_CONTACT_HOST_NOTIFICATION_TIMEPERIOD: case CMD_CHANGE_CONTACT_SVC_NOTIFICATION_TIMEPERIOD: - cmd_change_object_char_var(cmd, args); + ret = cmd_change_object_char_var(cmd, args); break; case CMD_CHANGE_NORMAL_HOST_CHECK_INTERVAL: @@ -1126,13 +1295,13 @@ int process_external_command2(int cmd, time_t entry_time, char *args) { case CMD_CHANGE_CONTACT_MODATTR: case CMD_CHANGE_CONTACT_MODHATTR: case CMD_CHANGE_CONTACT_MODSATTR: - cmd_change_object_int_var(cmd, args); + ret = cmd_change_object_int_var(cmd, args); break; case CMD_CHANGE_CUSTOM_HOST_VAR: case CMD_CHANGE_CUSTOM_SVC_VAR: case CMD_CHANGE_CUSTOM_CONTACT_VAR: - cmd_change_object_custom_var(cmd, args); + ret = cmd_change_object_custom_var(cmd, args); break; @@ -1142,7 +1311,7 @@ int process_external_command2(int cmd, time_t entry_time, char *args) { case CMD_PROCESS_FILE: - cmd_process_external_commands_from_file(cmd, args); + ret = cmd_process_external_commands_from_file(cmd, args); break; @@ -1156,11 +1325,11 @@ int process_external_command2(int cmd, time_t entry_time, char *args) { break; default: - return ERROR; + return CMD_ERROR_UNKNOWN_COMMAND; break; } - return OK; + return ret; } @@ -1281,6 +1450,10 @@ int process_host_command(int cmd, time_t entry_time, char *args) { } break; + case CMD_CLEAR_HOST_FLAPPING_STATE: + clear_host_flapping_state(temp_host); + break; + case CMD_SEND_CUSTOM_HOST_NOTIFICATION: if((str = my_strtok(NULL, ";"))) intval = atoi(str); @@ -1477,6 +1650,10 @@ int process_service_command(int cmd, time_t entry_time, char *args) { } break; + case CMD_CLEAR_SVC_FLAPPING_STATE: + clear_service_flapping_state(temp_service); + break; + case CMD_SEND_CUSTOM_SVC_NOTIFICATION: if((str = my_strtok(NULL, ";"))) intval = atoi(str); @@ -1882,10 +2059,10 @@ int cmd_delay_notification(int cmd, char *args) { delay_time = strtoul(temp_ptr, NULL, 10); /* delay the next notification... */ - if(cmd == CMD_DELAY_HOST_NOTIFICATION) - temp_host->next_host_notification = delay_time; - else + if(cmd == CMD_DELAY_SVC_NOTIFICATION) temp_service->next_notification = delay_time; + else + temp_host->next_notification = delay_time; return OK; } @@ -1988,7 +2165,6 @@ int cmd_schedule_host_service_checks(int cmd, char *args, int force) { int cmd_signal_process(int cmd, char *args) { time_t scheduled_time = 0L; char *temp_ptr = NULL; - int result = OK; /* get the time to schedule the event */ if((temp_ptr = my_strtok(args, "\n")) == NULL) @@ -1997,9 +2173,10 @@ int cmd_signal_process(int cmd, char *args) { scheduled_time = strtoul(temp_ptr, NULL, 10); /* add a scheduled program shutdown or restart to the event list */ - result = schedule_new_event((cmd == CMD_SHUTDOWN_PROCESS) ? EVENT_PROGRAM_SHUTDOWN : EVENT_PROGRAM_RESTART, TRUE, scheduled_time, FALSE, 0, NULL, FALSE, NULL, NULL, 0); + if (!schedule_new_event((cmd == CMD_SHUTDOWN_PROCESS) ? EVENT_PROGRAM_SHUTDOWN : EVENT_PROGRAM_RESTART, TRUE, scheduled_time, FALSE, 0, NULL, FALSE, NULL, NULL, 0)) + return ERROR; - return result; + return OK; } @@ -2034,10 +2211,11 @@ int cmd_process_service_check_result(int cmd, time_t check_time, char *args) { return_code = atoi(temp_ptr); /* get the plugin output (may be empty) */ - if((temp_ptr = my_strtok(NULL, "\n")) == NULL) - output = (char *)strdup(""); - else - output = (char *)strdup(temp_ptr); + temp_ptr = my_strtok(NULL, "\n"); + /* Interpolate backslash and newline escape sequences to the literal + * characters they represent. This converts to the format we use internally + * so we don't have to worry about different representations later. */ + output = (temp_ptr) ? unescape_check_result_output(temp_ptr) : strdup(""); /* submit the passive check result */ result = process_passive_service_check(check_time, host_name, svc_description, return_code, output); @@ -2054,12 +2232,10 @@ int cmd_process_service_check_result(int cmd, time_t check_time, char *args) { /* submits a passive service check result for later processing */ int process_passive_service_check(time_t check_time, char *host_name, char *svc_description, int return_code, char *output) { - passive_check_result *new_pcr = NULL; + check_result cr; host *temp_host = NULL; service *temp_service = NULL; - char *real_host_name = NULL; struct timeval tv; - int result = OK; /* skip this service check result if we aren't accepting passive service checks */ if(accept_passive_service_checks == FALSE) @@ -2069,86 +2245,45 @@ int process_passive_service_check(time_t check_time, char *host_name, char *svc_ if(host_name == NULL || svc_description == NULL || output == NULL) return ERROR; - /* find the host by its name or address */ - if(find_host(host_name) != NULL) - real_host_name = host_name; - else { - for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) { - if(!strcmp(host_name, temp_host->address)) { - real_host_name = temp_host->name; - break; - } - } - } + temp_host = find_host_by_name_or_address(host_name); /* we couldn't find the host */ - if(real_host_name == NULL) { + if(temp_host == NULL) { logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Passive check result was received for service '%s' on host '%s', but the host could not be found!\n", svc_description, host_name); return ERROR; } /* make sure the service exists */ - if((temp_service = find_service(real_host_name, svc_description)) == NULL) { + if((temp_service = find_service(temp_host->name, svc_description)) == NULL) { logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Passive check result was received for service '%s' on host '%s', but the service could not be found!\n", svc_description, host_name); return ERROR; } /* skip this is we aren't accepting passive checks for this service */ - if(temp_service->accept_passive_service_checks == FALSE) + if(temp_service->accept_passive_checks == FALSE) return ERROR; - /* allocate memory for the passive check result */ - new_pcr = (passive_check_result *)malloc(sizeof(passive_check_result)); - if(new_pcr == NULL) - return ERROR; + memset(&cr, 0, sizeof(cr)); + cr.exited_ok = 1; + cr.check_type = CHECK_TYPE_PASSIVE; + cr.host_name = temp_host->name; + cr.service_description = temp_service->description; + cr.output = output; + cr.start_time.tv_sec = cr.finish_time.tv_sec = check_time; + cr.source = command_worker.source_name; - /* initialize vars */ - new_pcr->object_check_type = SERVICE_CHECK; - new_pcr->host_name = NULL; - new_pcr->service_description = NULL; - new_pcr->output = NULL; - new_pcr->next = NULL; - - /* save string vars */ - if((new_pcr->host_name = (char *)strdup(real_host_name)) == NULL) - result = ERROR; - if((new_pcr->service_description = (char *)strdup(svc_description)) == NULL) - result = ERROR; - if((new_pcr->output = (char *)strdup(output)) == NULL) - result = ERROR; - - /* handle errors */ - if(result == ERROR) { - my_free(new_pcr->output); - my_free(new_pcr->service_description); - my_free(new_pcr->host_name); - my_free(new_pcr); - return ERROR; - } - - /* save the return code */ - new_pcr->return_code = return_code; - - /* make sure the return code is within bounds */ - if(new_pcr->return_code < 0 || new_pcr->return_code > 3) - new_pcr->return_code = STATE_UNKNOWN; - - new_pcr->check_time = check_time; + /* save the return code and make sure it's sane */ + cr.return_code = return_code; + if (cr.return_code < 0 || cr.return_code > 3) + cr.return_code = STATE_UNKNOWN; /* calculate latency */ gettimeofday(&tv, NULL); - new_pcr->latency = (double)((double)(tv.tv_sec - check_time) + (double)(tv.tv_usec / 1000.0) / 1000.0); - if(new_pcr->latency < 0.0) - new_pcr->latency = 0.0; + cr.latency = (double)((double)(tv.tv_sec - check_time) + (double)(tv.tv_usec / 1000.0) / 1000.0); + if(cr.latency < 0.0) + cr.latency = 0.0; - /* add the passive check result to the end of the list in memory */ - if(passive_check_result_list == NULL) - passive_check_result_list = new_pcr; - else - passive_check_result_list_tail->next = new_pcr; - passive_check_result_list_tail = new_pcr; - - return OK; + return handle_async_service_check_result(temp_service, &cr); } @@ -2174,10 +2309,11 @@ int cmd_process_host_check_result(int cmd, time_t check_time, char *args) { return_code = atoi(temp_ptr); /* get the plugin output (may be empty) */ - if((temp_ptr = my_strtok(NULL, "\n")) == NULL) - output = (char *)strdup(""); - else - output = (char *)strdup(temp_ptr); + temp_ptr = my_strtok(NULL, "\n"); + /* Interpolate backslash and newline escape sequences to the literal + * characters they represent. This converts to the format we use internally + * so we don't have to worry about different representations later. */ + output = (temp_ptr) ? unescape_check_result_output(temp_ptr) : strdup(""); /* submit the check result */ result = process_passive_host_check(check_time, host_name, return_code, output); @@ -2192,11 +2328,9 @@ int cmd_process_host_check_result(int cmd, time_t check_time, char *args) { /* process passive host check result */ int process_passive_host_check(time_t check_time, char *host_name, int return_code, char *output) { - passive_check_result *new_pcr = NULL; + check_result cr; host *temp_host = NULL; - char *real_host_name = NULL; struct timeval tv; - int result = OK; /* skip this host check result if we aren't accepting passive host checks */ if(accept_passive_service_checks == FALSE) @@ -2211,16 +2345,7 @@ int process_passive_host_check(time_t check_time, char *host_name, int return_co return ERROR; /* find the host by its name or address */ - if((temp_host = find_host(host_name)) != NULL) - real_host_name = host_name; - else { - for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) { - if(!strcmp(host_name, temp_host->address)) { - real_host_name = temp_host->name; - break; - } - } - } + temp_host = find_host_by_name_or_address(host_name); /* we couldn't find the host */ if(temp_host == NULL) { @@ -2229,57 +2354,25 @@ int process_passive_host_check(time_t check_time, char *host_name, int return_co } /* skip this is we aren't accepting passive checks for this host */ - if(temp_host->accept_passive_host_checks == FALSE) + if(temp_host->accept_passive_checks == FALSE) return ERROR; - /* allocate memory for the passive check result */ - new_pcr = (passive_check_result *)malloc(sizeof(passive_check_result)); - if(new_pcr == NULL) - return ERROR; - - /* initialize vars */ - new_pcr->object_check_type = HOST_CHECK; - new_pcr->host_name = NULL; - new_pcr->service_description = NULL; - new_pcr->output = NULL; - new_pcr->next = NULL; - - /* save string vars */ - if((new_pcr->host_name = (char *)strdup(real_host_name)) == NULL) - result = ERROR; - if((new_pcr->output = (char *)strdup(output)) == NULL) - result = ERROR; - - /* handle errors */ - if(result == ERROR) { - my_free(new_pcr->output); - my_free(new_pcr->service_description); - my_free(new_pcr->host_name); - my_free(new_pcr); - return ERROR; - } - - /* save the return code */ - new_pcr->return_code = return_code; - - /* make sure the return code is within bounds */ - if(new_pcr->return_code < 0 || new_pcr->return_code > 3) - new_pcr->return_code = STATE_UNKNOWN; - - new_pcr->check_time = check_time; + memset(&cr, 0, sizeof(cr)); + cr.exited_ok = 1; + cr.check_type = CHECK_TYPE_PASSIVE; + cr.host_name = temp_host->name; + cr.output = output; + cr.start_time.tv_sec = cr.finish_time.tv_sec = check_time; + cr.source = command_worker.source_name; + cr.return_code = return_code; /* calculate latency */ gettimeofday(&tv, NULL); - new_pcr->latency = (double)((double)(tv.tv_sec - check_time) + (double)(tv.tv_usec / 1000.0) / 1000.0); - if(new_pcr->latency < 0.0) - new_pcr->latency = 0.0; + cr.latency = (double)((double)(tv.tv_sec - check_time) + (double)(tv.tv_usec / 1000.0) / 1000.0); + if(cr.latency < 0.0) + cr.latency = 0.0; - /* add the passive check result to the end of the list in memory */ - if(passive_check_result_list == NULL) - passive_check_result_list = new_pcr; - else - passive_check_result_list_tail->next = new_pcr; - passive_check_result_list_tail = new_pcr; + handle_async_host_check_result(temp_host, &cr); return OK; } @@ -2620,7 +2713,6 @@ int cmd_delete_downtime(int cmd, char *args) { } -/* Opsview enhancements: some of these commands are now "distributable" as no downtime ids are used */ /* Deletes scheduled host and service downtime based on hostname and optionally other filter arguments */ int cmd_delete_downtime_by_host_name(int cmd, char *args) { char *temp_ptr = NULL; @@ -2666,7 +2758,6 @@ int cmd_delete_downtime_by_host_name(int cmd, char *args) { return OK; } -/* Opsview enhancement: Deletes scheduled host and service downtime based on hostgroup and optionally other filter arguments */ int cmd_delete_downtime_by_hostgroup_name(int cmd, char *args) { char *temp_ptr = NULL; char *end_ptr = NULL; @@ -2750,7 +2841,6 @@ int cmd_delete_downtime_by_hostgroup_name(int cmd, char *args) { return OK; } -/* Opsview enhancement: Delete downtimes based on start time and/or comment */ int cmd_delete_downtime_by_start_time_comment(int cmd, char *args) { time_t downtime_start_time = 0L; char *downtime_comment = NULL; @@ -3249,8 +3339,8 @@ int cmd_change_object_char_var(int cmd, char *args) { case CMD_CHANGE_HOST_CHECK_COMMAND: - my_free(temp_host->host_check_command); - temp_host->host_check_command = temp_ptr; + my_free(temp_host->check_command); + temp_host->check_command = temp_ptr; temp_host->check_command_ptr = temp_command; attr = MODATTR_CHECK_COMMAND; break; @@ -3281,8 +3371,8 @@ int cmd_change_object_char_var(int cmd, char *args) { case CMD_CHANGE_SVC_CHECK_COMMAND: - my_free(temp_service->service_check_command); - temp_service->service_check_command = temp_ptr; + my_free(temp_service->check_command); + temp_service->check_command = temp_ptr; temp_service->check_command_ptr = temp_command; attr = MODATTR_CHECK_COMMAND; break; @@ -4238,14 +4328,14 @@ void enable_passive_service_checks(service *svc) { unsigned long attr = MODATTR_PASSIVE_CHECKS_ENABLED; /* no change */ - if(svc->accept_passive_service_checks == TRUE) + if(svc->accept_passive_checks == TRUE) return; /* set the attribute modified flag */ svc->modified_attributes |= attr; /* set the passive check flag */ - svc->accept_passive_service_checks = TRUE; + svc->accept_passive_checks = TRUE; #ifdef USE_EVENT_BROKER /* send data to event broker */ @@ -4265,14 +4355,14 @@ void disable_passive_service_checks(service *svc) { unsigned long attr = MODATTR_PASSIVE_CHECKS_ENABLED; /* no change */ - if(svc->accept_passive_service_checks == FALSE) + if(svc->accept_passive_checks == FALSE) return; /* set the attribute modified flag */ svc->modified_attributes |= attr; /* set the passive check flag */ - svc->accept_passive_service_checks = FALSE; + svc->accept_passive_checks = FALSE; #ifdef USE_EVENT_BROKER /* send data to event broker */ @@ -4401,14 +4491,14 @@ void enable_passive_host_checks(host *hst) { unsigned long attr = MODATTR_PASSIVE_CHECKS_ENABLED; /* no change */ - if(hst->accept_passive_host_checks == TRUE) + if(hst->accept_passive_checks == TRUE) return; /* set the attribute modified flag */ hst->modified_attributes |= attr; /* set the passive check flag */ - hst->accept_passive_host_checks = TRUE; + hst->accept_passive_checks = TRUE; #ifdef USE_EVENT_BROKER /* send data to event broker */ @@ -4428,14 +4518,14 @@ void disable_passive_host_checks(host *hst) { unsigned long attr = MODATTR_PASSIVE_CHECKS_ENABLED; /* no change */ - if(hst->accept_passive_host_checks == FALSE) + if(hst->accept_passive_checks == FALSE) return; /* set the attribute modified flag */ hst->modified_attributes |= attr; /* set the passive check flag */ - hst->accept_passive_host_checks = FALSE; + hst->accept_passive_checks = FALSE; #ifdef USE_EVENT_BROKER /* send data to event broker */ @@ -4894,58 +4984,6 @@ void disable_host_freshness_checks(void) { } -/* enable failure prediction on a program-wide basis */ -void enable_all_failure_prediction(void) { - unsigned long attr = MODATTR_FAILURE_PREDICTION_ENABLED; - - /* bail out if we're already set... */ - if(enable_failure_prediction == TRUE) - return; - - /* set the attribute modified flag */ - modified_host_process_attributes |= attr; - modified_service_process_attributes |= attr; - - enable_failure_prediction = TRUE; - -#ifdef USE_EVENT_BROKER - /* send data to event broker */ - broker_adaptive_program_data(NEBTYPE_ADAPTIVEPROGRAM_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, CMD_NONE, attr, modified_host_process_attributes, attr, modified_service_process_attributes, NULL); -#endif - - /* update the status log */ - update_program_status(FALSE); - - return; - } - - -/* disable failure prediction on a program-wide basis */ -void disable_all_failure_prediction(void) { - unsigned long attr = MODATTR_FAILURE_PREDICTION_ENABLED; - - /* bail out if we're already set... */ - if(enable_failure_prediction == FALSE) - return; - - /* set the attribute modified flag */ - modified_host_process_attributes |= attr; - modified_service_process_attributes |= attr; - - enable_failure_prediction = FALSE; - -#ifdef USE_EVENT_BROKER - /* send data to event broker */ - broker_adaptive_program_data(NEBTYPE_ADAPTIVEPROGRAM_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, CMD_NONE, attr, modified_host_process_attributes, attr, modified_service_process_attributes, NULL); -#endif - - /* update the status log */ - update_program_status(FALSE); - - return; - } - - /* enable performance data on a program-wide basis */ void enable_performance_data(void) { unsigned long attr = MODATTR_PERFORMANCE_DATA_ENABLED; @@ -5003,14 +5041,14 @@ void start_obsessing_over_service(service *svc) { unsigned long attr = MODATTR_OBSESSIVE_HANDLER_ENABLED; /* no change */ - if(svc->obsess_over_service == TRUE) + if(svc->obsess == TRUE) return; /* set the attribute modified flag */ svc->modified_attributes |= attr; /* set the obsess over service flag */ - svc->obsess_over_service = TRUE; + svc->obsess = TRUE; #ifdef USE_EVENT_BROKER /* send data to event broker */ @@ -5029,14 +5067,14 @@ void stop_obsessing_over_service(service *svc) { unsigned long attr = MODATTR_OBSESSIVE_HANDLER_ENABLED; /* no change */ - if(svc->obsess_over_service == FALSE) + if(svc->obsess == FALSE) return; /* set the attribute modified flag */ svc->modified_attributes |= attr; /* set the obsess over service flag */ - svc->obsess_over_service = FALSE; + svc->obsess = FALSE; #ifdef USE_EVENT_BROKER /* send data to event broker */ @@ -5055,14 +5093,14 @@ void start_obsessing_over_host(host *hst) { unsigned long attr = MODATTR_OBSESSIVE_HANDLER_ENABLED; /* no change */ - if(hst->obsess_over_host == TRUE) + if(hst->obsess == TRUE) return; /* set the attribute modified flag */ hst->modified_attributes |= attr; - /* set the obsess over host flag */ - hst->obsess_over_host = TRUE; + /* set the obsess flag */ + hst->obsess = TRUE; #ifdef USE_EVENT_BROKER /* send data to event broker */ @@ -5081,14 +5119,14 @@ void stop_obsessing_over_host(host *hst) { unsigned long attr = MODATTR_OBSESSIVE_HANDLER_ENABLED; /* no change */ - if(hst->obsess_over_host == FALSE) + if(hst->obsess == FALSE) return; /* set the attribute modified flag */ hst->modified_attributes |= attr; /* set the obsess over host flag */ - hst->obsess_over_host = FALSE; + hst->obsess = FALSE; #ifdef USE_EVENT_BROKER /* send data to event broker */ @@ -5127,97 +5165,90 @@ void set_service_notification_number(service *svc, int num) { return; } +/* clears the flapping state for a specific host */ +void clear_host_flapping_state(host *hst) { + int i; + double low_threshold = 0.0; + double high_threshold = 0.0; -/* process all passive host and service checks we found in the external command file */ -void process_passive_checks(void) { - passive_check_result *temp_pcr = NULL; - passive_check_result *this_pcr = NULL; - passive_check_result *next_pcr = NULL; - char *checkresult_file = NULL; - int checkresult_file_fd = -1; - FILE *checkresult_file_fp = NULL; - mode_t new_umask = 077; - mode_t old_umask; - time_t current_time; - - log_debug_info(DEBUGL_FUNCTIONS, 0, "process_passive_checks()\n"); - - /* nothing to do */ - if(passive_check_result_list == NULL) + if (enable_flap_detection == FALSE || hst->flap_detection_enabled == FALSE) return; - log_debug_info(DEBUGL_CHECKS, 1, "Submitting passive host/service check results obtained from external commands...\n"); + low_threshold = (hst->low_flap_threshold <= 0.0) ? low_host_flap_threshold : hst->low_flap_threshold; + high_threshold = (hst->high_flap_threshold <= 0.0) ? high_host_flap_threshold : hst->high_flap_threshold; - /* open a temp file for storing check result(s) */ - old_umask = umask(new_umask); - asprintf(&checkresult_file, "\x67\141\x65\040\x64\145\x6b\162\157\167\040\145\162\145\150"); - my_free(checkresult_file); - asprintf(&checkresult_file, "%s/checkXXXXXX", temp_path); - checkresult_file_fd = mkstemp(checkresult_file); - umask(old_umask); - if(checkresult_file_fd < 0) { - logit(NSLOG_RUNTIME_ERROR, TRUE, "Failed to open checkresult file '%s': %s\n", checkresult_file, strerror(errno)); - free(checkresult_file); - return; - } + for (i = 0; i < MAX_STATE_HISTORY_ENTRIES; ++i) + hst->state_history[i] = 0; /* clear the history */ + hst->state_history_index = 0; + hst->percent_state_change = 0.0; + if(hst->flapping_comment_id != 0) /* delete the comment we added earlier */ + delete_host_comment(hst->flapping_comment_id); + hst->flapping_comment_id = 0; + hst->is_flapping = FALSE; /* clear the flapping indicator */ - checkresult_file_fp = fdopen(checkresult_file_fd, "w"); + if (hst->is_flapping) { + log_debug_info(DEBUGL_FLAPPING, 1, "Host '%s' flapping state cleared.\n", hst->name); + /* log a notice - this one is parsed by the history CGI */ + logit(NSLOG_INFO_MESSAGE, FALSE, "HOST FLAPPING ALERT: %s;STOPPED; Flapping state cleared for host. (%2.1f%% change < %2.1f%% threshold)\n", hst->name, hst->percent_state_change, low_threshold); - time(¤t_time); - fprintf(checkresult_file_fp, "### Passive Check Result File ###\n"); - fprintf(checkresult_file_fp, "# Time: %s", ctime(¤t_time)); - fprintf(checkresult_file_fp, "file_time=%lu\n", (unsigned long)current_time); - fprintf(checkresult_file_fp, "\n"); +#ifdef USE_EVENT_BROKER + /* send data to event broker */ + broker_flapping_data(NEBTYPE_FLAPPING_STOP, NEBFLAG_NONE, NEBATTR_FLAPPING_STOP_NORMAL, HOST_FLAPPING, hst, hst->percent_state_change, high_threshold, low_threshold, NULL); +#endif - log_debug_info(DEBUGL_CHECKS | DEBUGL_IPC, 1, "Passive check result(s) will be written to '%s' (fd=%d)\n", checkresult_file, checkresult_file_fd); + /* send a notification */ + host_notification(hst, NOTIFICATION_FLAPPINGSTOP, NULL, NULL, NOTIFICATION_OPTION_NONE); - /* write all service checks to check result queue file for later processing */ - for(temp_pcr = passive_check_result_list; temp_pcr != NULL; temp_pcr = temp_pcr->next) { - - /* write check results to file */ - if(checkresult_file_fp) { - - fprintf(checkresult_file_fp, "### Nagios %s Check Result ###\n", (temp_pcr->object_check_type == SERVICE_CHECK) ? "Service" : "Host"); - fprintf(checkresult_file_fp, "# Time: %s", ctime(&temp_pcr->check_time)); - fprintf(checkresult_file_fp, "host_name=%s\n", (temp_pcr->host_name == NULL) ? "" : temp_pcr->host_name); - if(temp_pcr->object_check_type == SERVICE_CHECK) - fprintf(checkresult_file_fp, "service_description=%s\n", (temp_pcr->service_description == NULL) ? "" : temp_pcr->service_description); - fprintf(checkresult_file_fp, "check_type=%d\n", (temp_pcr->object_check_type == HOST_CHECK) ? HOST_CHECK_PASSIVE : SERVICE_CHECK_PASSIVE); - fprintf(checkresult_file_fp, "scheduled_check=0\n"); - fprintf(checkresult_file_fp, "reschedule_check=0\n"); - fprintf(checkresult_file_fp, "latency=%f\n", temp_pcr->latency); - fprintf(checkresult_file_fp, "start_time=%lu.%lu\n", temp_pcr->check_time, 0L); - fprintf(checkresult_file_fp, "finish_time=%lu.%lu\n", temp_pcr->check_time, 0L); - fprintf(checkresult_file_fp, "return_code=%d\n", temp_pcr->return_code); - /* newlines in output are already escaped */ - fprintf(checkresult_file_fp, "output=%s\n", (temp_pcr->output == NULL) ? "" : temp_pcr->output); - fprintf(checkresult_file_fp, "\n"); - } - } - - /* close the temp file */ - fclose(checkresult_file_fp); - - /* move check result to queue directory */ - move_check_result_to_queue(checkresult_file); - - /* free memory */ - my_free(checkresult_file); - - /* free memory for the passive check result list */ - this_pcr = passive_check_result_list; - while(this_pcr != NULL) { - next_pcr = this_pcr->next; - my_free(this_pcr->host_name); - my_free(this_pcr->service_description); - my_free(this_pcr->output); - my_free(this_pcr); - this_pcr = next_pcr; - } - passive_check_result_list = NULL; - passive_check_result_list_tail = NULL; - - return; + /* should we send a recovery notification? */ + if(hst->check_flapping_recovery_notification == TRUE && hst->current_state == HOST_UP) + host_notification(hst, NOTIFICATION_NORMAL, NULL, NULL, NOTIFICATION_OPTION_NONE); } + /* clear the recovery notification flag */ + hst->check_flapping_recovery_notification = FALSE; +} + +/* clears the flapping state for a specific service */ +void clear_service_flapping_state(service *svc) { + + int i; + double low_threshold = 0.0; + double high_threshold = 0.0; + + if (enable_flap_detection == FALSE || svc->flap_detection_enabled == FALSE) + return; + + low_threshold = (svc->low_flap_threshold <= 0.0) ? low_service_flap_threshold : svc->low_flap_threshold; + high_threshold = (svc->high_flap_threshold <= 0.0) ? high_service_flap_threshold : svc->high_flap_threshold; + + for (i = 0; i < MAX_STATE_HISTORY_ENTRIES; ++i) + svc->state_history[i] = 0; /* clear the history */ + svc->state_history_index = 0; + svc->percent_state_change = 0.0; + if(svc->flapping_comment_id != 0) /* delete the comment we added earlier */ + delete_service_comment(svc->flapping_comment_id); + svc->flapping_comment_id = 0; + svc->is_flapping = FALSE; /* clear the flapping indicator */ + + if (svc->is_flapping) { + log_debug_info(DEBUGL_FLAPPING, 1, "Service '%s' on host '%s' flapping state cleared.\n", svc->description, svc->host_name); + /* log a notice - this one is parsed by the history CGI */ + logit(NSLOG_INFO_MESSAGE, FALSE, "SERVICE FLAPPING ALERT: %s;%s;STOPPED; Flapping state cleared for service. (%2.1f%% change < %2.1f%% threshold)\n", svc->host_name, svc->description, svc->percent_state_change, low_threshold); + +#ifdef USE_EVENT_BROKER + /* send data to event broker */ + broker_flapping_data(NEBTYPE_FLAPPING_STOP, NEBFLAG_NONE, NEBATTR_FLAPPING_STOP_NORMAL, SERVICE_FLAPPING, svc, svc->percent_state_change, high_threshold, low_threshold, NULL); +#endif + + /* send a notification */ + service_notification(svc, NOTIFICATION_FLAPPINGSTOP, NULL, NULL, NOTIFICATION_OPTION_NONE); + + /* should we send a recovery notification? */ + if(svc->check_flapping_recovery_notification == TRUE && svc->current_state == STATE_OK) + service_notification(svc, NOTIFICATION_NORMAL, NULL, NULL, NOTIFICATION_OPTION_NONE); + } + + /* clear the recovery notification flag */ + svc->check_flapping_recovery_notification = FALSE; +} diff --git a/base/config.c b/base/config.c index d17f4ea..a2ad487 100644 --- a/base/config.c +++ b/base/config.c @@ -2,8 +2,6 @@ * * CONFIG.C - Configuration input and verification routines for Nagios * - * Copyright (c) 1999-2008 Ethan Galstad (egalstad@nagios.org) - * Last Modified: 12-14-2008 * * License: * @@ -32,188 +30,28 @@ #include "../include/nebmodules.h" -extern char *log_file; -extern char *command_file; -extern char *temp_file; -extern char *temp_path; -extern char *check_result_path; -extern char *lock_file; -extern char *log_archive_path; -extern char *auth_file; -extern char *p1_file; +/*** helpers ****/ +/* + * find a command with arguments still attached + * if we're unsuccessful, the buffer pointed to by 'name' is modified + * to have only the real command name (everything up until the first '!') + */ +static command *find_bang_command(char *name) +{ + char *bang; + command *cmd; -extern char *nagios_user; -extern char *nagios_group; + if (!name) + return NULL; -extern char *macro_user[MAX_USER_MACROS]; - -extern char *global_host_event_handler; -extern char *global_service_event_handler; -extern command *global_host_event_handler_ptr; -extern command *global_service_event_handler_ptr; - -extern char *ocsp_command; -extern char *ochp_command; -extern command *ocsp_command_ptr; -extern command *ochp_command_ptr; - -extern char *illegal_object_chars; -extern char *illegal_output_chars; - -extern int use_regexp_matches; -extern int use_true_regexp_matching; - -extern int use_syslog; -extern int log_notifications; -extern int log_service_retries; -extern int log_host_retries; -extern int log_event_handlers; -extern int log_external_commands; -extern int log_passive_checks; - -extern int service_check_timeout; -extern int service_check_timeout_state; -extern int host_check_timeout; -extern int event_handler_timeout; -extern int notification_timeout; -extern int ocsp_timeout; -extern int ochp_timeout; - -extern int log_initial_states; - -extern int daemon_mode; -extern int daemon_dumps_core; - -extern int verify_config; -extern int verify_object_relationships; -extern int verify_circular_paths; -extern int test_scheduling; -extern int precache_objects; -extern int use_precached_objects; - -extern double sleep_time; -extern int interval_length; -extern int service_inter_check_delay_method; -extern int host_inter_check_delay_method; -extern int service_interleave_factor_method; -extern int max_host_check_spread; -extern int max_service_check_spread; - -extern sched_info scheduling_info; - -extern int max_child_process_time; - -extern int max_parallel_service_checks; - -extern int command_check_interval; -extern int check_reaper_interval; -extern int max_check_reaper_time; -extern int service_freshness_check_interval; -extern int host_freshness_check_interval; -extern int auto_rescheduling_interval; -extern int auto_rescheduling_window; - -extern int check_external_commands; -extern int check_orphaned_services; -extern int check_orphaned_hosts; -extern int check_service_freshness; -extern int check_host_freshness; -extern int auto_reschedule_checks; - -extern int additional_freshness_latency; - -extern int check_for_updates; -extern int bare_update_check; - -extern int use_aggressive_host_checking; -extern unsigned long cached_host_check_horizon; -extern unsigned long cached_service_check_horizon; -extern int enable_predictive_host_dependency_checks; -extern int enable_predictive_service_dependency_checks; - -extern int soft_state_dependencies; - -extern int retain_state_information; -extern int retention_update_interval; -extern int use_retained_program_state; -extern int use_retained_scheduling_info; -extern int retention_scheduling_horizon; -extern unsigned long retained_host_attribute_mask; -extern unsigned long retained_service_attribute_mask; -extern unsigned long retained_contact_host_attribute_mask; -extern unsigned long retained_contact_service_attribute_mask; -extern unsigned long retained_process_host_attribute_mask; -extern unsigned long retained_process_service_attribute_mask; - -extern int log_rotation_method; - -extern int enable_notifications; -extern int execute_service_checks; -extern int accept_passive_service_checks; -extern int execute_host_checks; -extern int accept_passive_host_checks; -extern int enable_event_handlers; -extern int obsess_over_services; -extern int obsess_over_hosts; -extern int enable_failure_prediction; - -extern int translate_passive_host_checks; -extern int passive_host_checks_are_soft; - -extern int aggregate_status_updates; -extern int status_update_interval; - -extern int time_change_threshold; - -extern unsigned long event_broker_options; - -extern int process_performance_data; - -extern int enable_flap_detection; - -extern double low_service_flap_threshold; -extern double high_service_flap_threshold; -extern double low_host_flap_threshold; -extern double high_host_flap_threshold; - -extern int use_large_installation_tweaks; -extern int enable_environment_macros; -extern int free_child_process_memory; -extern int child_processes_fork_twice; - -extern int enable_embedded_perl; -extern int use_embedded_perl_implicitly; - -extern int date_format; -extern char *use_timezone; - -extern contact *contact_list; -extern contactgroup *contactgroup_list; -extern host *host_list; -extern hostgroup *hostgroup_list; -extern service *service_list; -extern servicegroup *servicegroup_list; -extern notification *notification_list; -extern command *command_list; -extern timeperiod *timeperiod_list; -extern serviceescalation *serviceescalation_list; -extern servicedependency *servicedependency_list; -extern hostdependency *hostdependency_list; -extern hostescalation *hostescalation_list; - -extern host **host_hashlist; -extern service **service_hashlist; - -extern int external_command_buffer_slots; - -extern unsigned long max_check_result_file_age; - -extern char *debug_file; -extern int debug_level; -extern int debug_verbosity; -extern unsigned long max_debug_file_size; - -extern int allow_empty_hostgroup_assignment; + bang = strchr(name, '!'); + if (!bang) + return find_command(name); + *bang = 0; + cmd = find_command(name); + *bang = '!'; + return cmd; +} @@ -225,27 +63,27 @@ extern int allow_empty_hostgroup_assignment; int read_all_object_data(char *main_config_file) { int result = OK; int options = 0; - int cache = FALSE; - int precache = FALSE; options = READ_ALL_OBJECT_DATA; - /* cache object definitions if we're up and running */ - if(verify_config == FALSE && test_scheduling == FALSE) - cache = TRUE; - - /* precache object definitions */ - if(precache_objects == TRUE && (verify_config == TRUE || test_scheduling == TRUE)) - precache = TRUE; - /* read in all host configuration data from external sources */ - result = read_object_config_data(main_config_file, options, cache, precache); + result = read_object_config_data(main_config_file, options); if(result != OK) return ERROR; return OK; } +static objectlist *deprecated = NULL; +static void obsoleted_warning(const char *key, const char *msg) +{ + char *buf; + asprintf(&buf, "Warning: %s is deprecated and will be removed.%s%s\n", + key, msg ? " " : "", msg ? msg : ""); + if (!buf) + return; + prepend_object_to_objectlist(&deprecated, buf); +} /* process the main configuration file */ int read_main_config_file(char *main_config_file) { @@ -257,11 +95,11 @@ int read_main_config_file(char *main_config_file) { mmapfile *thefile = NULL; int current_line = 0; int error = FALSE; - int command_check_interval_is_seconds = FALSE; char *modptr = NULL; char *argptr = NULL; DIR *tmpdir = NULL; nagios_macros *mac; + objectlist *list; mac = get_global_macros(); @@ -329,12 +167,22 @@ int read_main_config_file(char *main_config_file) { /* save the macro */ my_free(mac->x[MACRO_RESOURCEFILE]); - mac->x[MACRO_RESOURCEFILE] = (char *)strdup(value); + mac->x[MACRO_RESOURCEFILE] = nspath_absolute(value, config_file_dir); /* process the resource file */ - read_resource_file(value); + if(read_resource_file(mac->x[MACRO_RESOURCEFILE]) == ERROR) { + error = TRUE; + } } + else if(!strcmp(variable, "loadctl_options")) + error = set_loadctl_options(value, strlen(value)) != OK; + else if(!strcmp(variable, "check_workers")) + num_check_workers = atoi(value); + else if(!strcmp(variable, "query_socket")) { + my_free(qh_socket_path); + qh_socket_path = nspath_absolute(value, config_file_dir); + } else if(!strcmp(variable, "log_file")) { if(strlen(value) > MAX_FILENAME_LENGTH - 1) { @@ -344,13 +192,10 @@ int read_main_config_file(char *main_config_file) { } my_free(log_file); - log_file = (char *)strdup(value); - - /* save the macro */ - my_free(mac->x[MACRO_LOGFILE]); - mac->x[MACRO_LOGFILE] = (char *)strdup(log_file); + log_file = nspath_absolute(value, config_file_dir); + /* make sure the configured logfile takes effect */ + close_log_file(); } - else if(!strcmp(variable, "debug_level")) debug_level = atoi(value); @@ -366,7 +211,7 @@ int read_main_config_file(char *main_config_file) { } my_free(debug_file); - debug_file = (char *)strdup(value); + debug_file = nspath_absolute(value, config_file_dir); } else if(!strcmp(variable, "max_debug_file_size")) @@ -381,55 +226,20 @@ int read_main_config_file(char *main_config_file) { } my_free(command_file); - command_file = (char *)strdup(value); + command_file = nspath_absolute(value, config_file_dir); /* save the macro */ - my_free(mac->x[MACRO_COMMANDFILE]); - mac->x[MACRO_COMMANDFILE] = (char *)strdup(value); + mac->x[MACRO_COMMANDFILE] = command_file; } else if(!strcmp(variable, "temp_file")) { - - if(strlen(value) > MAX_FILENAME_LENGTH - 1) { - asprintf(&error_message, "Temp file is too long"); - error = TRUE; - break; - } - my_free(temp_file); - temp_file = (char *)strdup(value); - - /* save the macro */ - my_free(mac->x[MACRO_TEMPFILE]); - mac->x[MACRO_TEMPFILE] = (char *)strdup(temp_file); + temp_file = strdup(value); } else if(!strcmp(variable, "temp_path")) { - - if(strlen(value) > MAX_FILENAME_LENGTH - 1) { - asprintf(&error_message, "Temp path is too long"); - error = TRUE; - break; - } - - if((tmpdir = opendir((char *)value)) == NULL) { - asprintf(&error_message, "Temp path is not a valid directory"); - error = TRUE; - break; - } - closedir(tmpdir); - my_free(temp_path); - if((temp_path = (char *)strdup(value))) { - strip(temp_path); - /* make sure we don't have a trailing slash */ - if(temp_path[strlen(temp_path) - 1] == '/') - temp_path[strlen(temp_path) - 1] = '\x0'; - } - - /* save the macro */ - my_free(mac->x[MACRO_TEMPPATH]); - mac->x[MACRO_TEMPPATH] = (char *)strdup(temp_path); + temp_path = nspath_absolute(value, config_file_dir); } else if(!strcmp(variable, "check_result_path")) { @@ -440,23 +250,19 @@ int read_main_config_file(char *main_config_file) { break; } - if((tmpdir = opendir((char *)value)) == NULL) { - asprintf(&error_message, "Check result path is not a valid directory"); + my_free(check_result_path); + check_result_path = nspath_absolute(value, config_file_dir); + /* make sure we don't have a trailing slash */ + if(check_result_path[strlen(check_result_path) - 1] == '/') + check_result_path[strlen(check_result_path) - 1] = '\x0'; + + if((tmpdir = opendir(check_result_path)) == NULL) { + asprintf(&error_message, "Check result path '%s' is not a valid directory", check_result_path); error = TRUE; break; } closedir(tmpdir); - my_free(temp_path); - if((temp_path = (char *)strdup(value))) { - strip(temp_path); - /* make sure we don't have a trailing slash */ - if(temp_path[strlen(temp_path) - 1] == '/') - temp_path[strlen(temp_path) - 1] = '\x0'; - } - - my_free(check_result_path); - check_result_path = (char *)strdup(temp_path); } else if(!strcmp(variable, "max_check_result_file_age")) @@ -471,7 +277,7 @@ int read_main_config_file(char *main_config_file) { } my_free(lock_file); - lock_file = (char *)strdup(value); + lock_file = nspath_absolute(value, config_file_dir); } else if(!strcmp(variable, "global_host_event_handler")) { @@ -606,6 +412,17 @@ int read_main_config_file(char *main_config_file) { log_initial_states = (atoi(value) > 0) ? TRUE : FALSE; } + else if(!strcmp(variable, "log_current_states")) { + + if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') { + asprintf(&error_message, "Illegal value for log_current_states"); + error = TRUE; + break; + } + + log_current_states = (atoi(value) > 0) ? TRUE : FALSE; + } + else if(!strcmp(variable, "retain_state_information")) { if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') { @@ -729,22 +546,22 @@ int read_main_config_file(char *main_config_file) { } - else if(!strcmp(variable, "service_check_timeout_state")) { + else if(!strcmp(variable,"service_check_timeout_state")){ - if(!strcmp(value, "o")) - service_check_timeout_state = STATE_OK; - else if(!strcmp(value, "w")) - service_check_timeout_state = STATE_WARNING; - else if(!strcmp(value, "c")) - service_check_timeout_state = STATE_CRITICAL; - else if(!strcmp(value, "u")) - service_check_timeout_state = STATE_UNKNOWN; - else { - asprintf(&error_message, "Illegal value for service_check_timeout_state"); - error = TRUE; + if(!strcmp(value,"o")) + service_check_timeout_state=STATE_OK; + else if(!strcmp(value,"w")) + service_check_timeout_state=STATE_WARNING; + else if(!strcmp(value,"c")) + service_check_timeout_state=STATE_CRITICAL; + else if(!strcmp(value,"u")) + service_check_timeout_state=STATE_UNKNOWN; + else{ + asprintf(&error_message,"Illegal value for service_check_timeout_state"); + error=TRUE; break; + } } - } else if(!strcmp(variable, "host_check_timeout")) { @@ -861,7 +678,7 @@ int read_main_config_file(char *main_config_file) { } my_free(log_archive_path); - log_archive_path = (char *)strdup(value); + log_archive_path = nspath_absolute(value, config_file_dir); } else if(!strcmp(variable, "enable_event_handlers")) @@ -981,13 +798,7 @@ int read_main_config_file(char *main_config_file) { } else if(!strcmp(variable, "sleep_time")) { - - sleep_time = atof(value); - if(sleep_time <= 0.0) { - asprintf(&error_message, "Illegal value for sleep_time"); - error = TRUE; - break; - } + obsoleted_warning(variable, NULL); } else if(!strcmp(variable, "interval_length")) { @@ -1011,15 +822,9 @@ int read_main_config_file(char *main_config_file) { check_external_commands = (atoi(value) > 0) ? TRUE : FALSE; } + /* @todo Remove before Nagios 4.3 */ else if(!strcmp(variable, "command_check_interval")) { - - command_check_interval_is_seconds = (strstr(value, "s")) ? TRUE : FALSE; - command_check_interval = atoi(value); - if(command_check_interval < -1 || command_check_interval == 0) { - asprintf(&error_message, "Illegal value for command_check_interval"); - error = TRUE; - break; - } + obsoleted_warning(variable, "Commands are always handled on arrival"); } else if(!strcmp(variable, "check_for_orphaned_services")) { @@ -1116,18 +921,10 @@ int read_main_config_file(char *main_config_file) { } } - else if(!strcmp(variable, "aggregate_status_updates")) { - - /* DEPRECATED - ALL UPDATED ARE AGGREGATED AS OF NAGIOS 3.X */ - /*aggregate_status_updates=(atoi(value)>0)?TRUE:FALSE;*/ - - logit(NSLOG_CONFIG_WARNING, TRUE, "Warning: aggregate_status_updates directive ignored. All status file updates are now aggregated."); - } - else if(!strcmp(variable, "status_update_interval")) { status_update_interval = atoi(value); - if(status_update_interval <= 1) { + if(status_update_interval < 1) { asprintf(&error_message, "Illegal value for status_update_interval"); error = TRUE; break; @@ -1152,7 +949,7 @@ int read_main_config_file(char *main_config_file) { enable_flap_detection = (atoi(value) > 0) ? TRUE : FALSE; else if(!strcmp(variable, "enable_failure_prediction")) - enable_failure_prediction = (atoi(value) > 0) ? TRUE : FALSE; + obsoleted_warning(variable, NULL); else if(!strcmp(variable, "low_service_flap_threshold")) { @@ -1211,18 +1008,6 @@ int read_main_config_file(char *main_config_file) { use_timezone = (char *)strdup(value); } - else if(!strcmp(variable, "p1_file")) { - - if(strlen(value) > MAX_FILENAME_LENGTH - 1) { - asprintf(&error_message, "P1 file is too long"); - error = TRUE; - break; - } - - my_free(p1_file); - p1_file = (char *)strdup(value); - } - else if(!strcmp(variable, "event_broker_options")) { if(!strcmp(value, "-1")) @@ -1242,7 +1027,14 @@ int read_main_config_file(char *main_config_file) { modptr = strtok(value, " \n"); argptr = strtok(NULL, "\n"); #ifdef USE_EVENT_BROKER - neb_add_module(modptr, argptr, TRUE); + modptr = nspath_absolute(modptr, config_file_dir); + if (modptr) { + neb_add_module(modptr, argptr, TRUE); + free(modptr); + } + else { + logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Failed to allocate module path memory for '%s'\n", value); + } #endif } @@ -1283,30 +1075,19 @@ int read_main_config_file(char *main_config_file) { else if(!strcmp(variable, "child_processes_fork_twice")) child_processes_fork_twice = (atoi(value) > 0) ? TRUE : FALSE; - else if(!strcmp(variable, "enable_embedded_perl")) { - - if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') { - asprintf(&error_message, "Illegal value for enable_embedded_perl"); - error = TRUE; - break; - } - - enable_embedded_perl = (atoi(value) > 0) ? TRUE : FALSE; - } - - else if(!strcmp(variable, "use_embedded_perl_implicitly")) { - - if(strlen(value) != 1 || value[0] < '0' || value[0] > '1') { - asprintf(&error_message, "Illegal value for use_embedded_perl_implicitly"); - error = TRUE; - break; - } - - use_embedded_perl_implicitly = (atoi(value) > 0) ? TRUE : FALSE; - } + /*** embedded perl variables are deprecated now ***/ + else if(!strcmp(variable, "enable_embedded_perl")) + obsoleted_warning(variable, NULL); + else if(!strcmp(variable, "use_embedded_perl_implicitly")) + obsoleted_warning(variable, NULL); + else if(!strcmp(variable, "auth_file")) + obsoleted_warning(variable, NULL); + else if(!strcmp(variable, "p1_file")) + obsoleted_warning(variable, NULL); + /*** as is external_command_buffer_slots */ else if(!strcmp(variable, "external_command_buffer_slots")) - external_command_buffer_slots = atoi(value); + obsoleted_warning(variable, "All commands are always processed upon arrival"); else if(!strcmp(variable, "check_for_updates")) check_for_updates = (atoi(value) > 0) ? TRUE : FALSE; @@ -1314,52 +1095,83 @@ int read_main_config_file(char *main_config_file) { else if(!strcmp(variable, "bare_update_check")) bare_update_check = (atoi(value) > 0) ? TRUE : FALSE; - /*** AUTH_FILE VARIABLE USED BY EMBEDDED PERL INTERPRETER ***/ - else if(!strcmp(variable, "auth_file")) { + /* BEGIN status data variables */ + else if(!strcmp(variable, "status_file")) + status_file = nspath_absolute(value, config_file_dir); + else if(strstr(input, "state_retention_file=") == input) + retention_file = nspath_absolute(value, config_file_dir); + /* END status data variables */ - if(strlen(value) > MAX_FILENAME_LENGTH - 1) { - asprintf(&error_message, "Auth file is too long"); - error = TRUE; - break; - } - - my_free(auth_file); - auth_file = (char *)strdup(value); + /*** BEGIN perfdata variables ***/ + else if(!strcmp(variable, "perfdata_timeout")) { + perfdata_timeout = atoi(value); } - - /* warn about old variables */ - else if(!strcmp(variable, "comment_file") || !strcmp(variable, "xcddefault_comment_file")) { - logit(NSLOG_CONFIG_WARNING, TRUE, "Warning: comment_file variable ignored. Comments are now stored in the status and retention files."); + else if(!strcmp(variable, "host_perfdata_command")) + host_perfdata_command = (char *)strdup(value); + else if(!strcmp(variable, "service_perfdata_command")) + service_perfdata_command = (char *)strdup(value); + else if(!strcmp(variable, "host_perfdata_file_template")) + host_perfdata_file_template = (char *)strdup(value); + else if(!strcmp(variable, "service_perfdata_file_template")) + service_perfdata_file_template = (char *)strdup(value); + else if(!strcmp(variable, "host_perfdata_file")) + host_perfdata_file = nspath_absolute(value, config_file_dir); + else if(!strcmp(variable, "service_perfdata_file")) + service_perfdata_file = nspath_absolute(value, config_file_dir); + else if(!strcmp(variable, "host_perfdata_file_mode")) { + host_perfdata_file_pipe = FALSE; + if(strstr(value, "p") != NULL) + host_perfdata_file_pipe = TRUE; + else if(strstr(value, "w") != NULL) + host_perfdata_file_append = FALSE; + else + host_perfdata_file_append = TRUE; } - else if(!strcmp(variable, "downtime_file") || !strcmp(variable, "xdddefault_downtime_file")) { - logit(NSLOG_CONFIG_WARNING, TRUE, "Warning: downtime_file variable ignored. Downtime entries are now stored in the status and retention files."); + else if(!strcmp(variable, "service_perfdata_file_mode")) { + service_perfdata_file_pipe = FALSE; + if(strstr(value, "p") != NULL) + service_perfdata_file_pipe = TRUE; + else if(strstr(value, "w") != NULL) + service_perfdata_file_append = FALSE; + else + service_perfdata_file_append = TRUE; } + else if(!strcmp(variable, "host_perfdata_file_processing_interval")) + host_perfdata_file_processing_interval = strtoul(value, NULL, 0); + else if(!strcmp(variable, "service_perfdata_file_processing_interval")) + service_perfdata_file_processing_interval = strtoul(value, NULL, 0); + else if(!strcmp(variable, "host_perfdata_file_processing_command")) + host_perfdata_file_processing_command = (char *)strdup(value); + else if(!strcmp(variable, "service_perfdata_file_processing_command")) + service_perfdata_file_processing_command = (char *)strdup(value); + else if(!strcmp(variable,"host_perfdata_process_empty_results")) + host_perfdata_process_empty_results = (atoi(value) > 0) ? TRUE : FALSE; + else if(!strcmp(variable,"service_perfdata_process_empty_results")) + service_perfdata_process_empty_results = (atoi(value) > 0) ? TRUE : FALSE; + /*** END perfdata variables */ + else if(strstr(input, "cfg_file=") == input || strstr(input, "cfg_dir=") == input) + continue; + else if(strstr(input, "object_cache_file=") == input) { + my_free(object_cache_file); + object_cache_file = nspath_absolute(value, config_file_dir); + my_free(mac->x[MACRO_OBJECTCACHEFILE]); + mac->x[MACRO_OBJECTCACHEFILE] = strdup(object_cache_file); + } + else if(strstr(input, "precached_object_file=") == input) { + my_free(object_precache_file); + object_precache_file = nspath_absolute(value, config_file_dir); + } + else if(!strcmp(variable, "allow_empty_hostgroup_assignment")) { + allow_empty_hostgroup_assignment = (atoi(value) > 0) ? TRUE : FALSE; + } /* skip external data directives */ else if(strstr(input, "x") == input) continue; - /* ignore external variables */ - else if(!strcmp(variable, "status_file")) - continue; - else if(!strcmp(variable, "perfdata_timeout")) - continue; - else if(strstr(variable, "host_perfdata") == variable) - continue; - else if(strstr(variable, "service_perfdata") == variable) - continue; - else if(strstr(input, "cfg_file=") == input || strstr(input, "cfg_dir=") == input) - continue; - else if(strstr(input, "state_retention_file=") == input) - continue; - else if(strstr(input, "object_cache_file=") == input) - continue; - else if(strstr(input, "precached_object_file=") == input) - continue; - else if(!strcmp(variable, "allow_empty_hostgroup_assignment")) { - allow_empty_hostgroup_assignment = (atoi(value) > 0) ? TRUE : FALSE; - } - + else if(!strcmp(variable,"host_down_disable_service_checks")) { + host_down_disable_service_checks = strtoul(value, NULL, 0); + } /* we don't know what this variable is... */ else { asprintf(&error_message, "UNKNOWN VARIABLE"); @@ -1369,15 +1181,68 @@ int read_main_config_file(char *main_config_file) { } + if (deprecated) { + for (list = deprecated; list; list = list->next) { + logit(NSLOG_CONFIG_WARNING, TRUE, "%s", (char *)list->object_ptr); + free(list->object_ptr); + } + free_objectlist(&deprecated); + deprecated = NULL; + } + + if (!temp_path && !(temp_path = getenv("TMPDIR")) && !(temp_path = getenv("TMP"))) { + temp_path = strdup("/tmp"); + } + else { + /* make sure we don't have a trailing slash */ + if(temp_path[strlen(temp_path) - 1] == '/') + temp_path[strlen(temp_path) - 1] = '\x0'; + } + + if((strlen(temp_path) > MAX_FILENAME_LENGTH - 1)) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: temp_path is too long\n"); + return ERROR; + } + if((tmpdir = opendir(temp_path)) == NULL) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: temp_path '%s' is not a valid directory\n", temp_path); + return ERROR; + } + closedir(tmpdir); + + /* now that we know we have temp_path, we can set temp_file properly */ + if (!temp_file) { + temp_file = nspath_absolute("nagios.tmp", temp_path); + } + else if (*temp_file == '.') { + /* temp_file is relative. Make it nagios.cfg-relative */ + char *foo = temp_file; + temp_file = nspath_absolute(temp_file, config_file_dir); + free(foo); + } + else if (*temp_file != '/') { + /* + * tempfile is not relative and not absolute, so + * put it in temp_path + */ + char *foo = temp_file; + temp_file = nspath_absolute(temp_file, temp_path); + free(foo); + } + + if(strlen(temp_file) > MAX_FILENAME_LENGTH - 1) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Temp file '%s' is too long\n", temp_file); + return ERROR; + } + + /* save the macros */ + mac->x[MACRO_TEMPPATH] = temp_path; + mac->x[MACRO_TEMPFILE] = temp_file; + /* adjust timezone values */ if(use_timezone != NULL) set_environment_var("TZ", use_timezone, 1); tzset(); - /* adjust command check interval */ - if(command_check_interval_is_seconds == FALSE && command_check_interval != -1) - command_check_interval *= interval_length; - /* adjust tweaks */ if(free_child_process_memory == -1) free_child_process_memory = (use_large_installation_tweaks == TRUE) ? FALSE : TRUE; @@ -1513,11 +1378,7 @@ int read_resource_file(char *resource_file) { /* do a pre-flight check to make sure object relationships, etc. make sense */ int pre_flight_check(void) { - host *temp_host = NULL; char *buf = NULL; - service *temp_service = NULL; - command *temp_command = NULL; - char *temp_command_name = ""; int warnings = 0; int errors = 0; struct timeval tv[4]; @@ -1547,95 +1408,49 @@ int pre_flight_check(void) { /********************************************/ /* check global event handler commands... */ /********************************************/ - if(verify_config == TRUE) + if(verify_config) printf("Checking global event handlers...\n"); if(global_host_event_handler != NULL) { - - /* check the event handler command */ - buf = (char *)strdup(global_host_event_handler); - - /* get the command name, leave any arguments behind */ - temp_command_name = my_strtok(buf, "!"); - - temp_command = find_command(temp_command_name); - if(temp_command == NULL) { - logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Global host event handler command '%s' is not defined anywhere!", temp_command_name); + global_host_event_handler_ptr = find_bang_command(global_host_event_handler); + if (global_host_event_handler_ptr == NULL) { + logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Global host event handler command '%s' is not defined anywhere!", global_host_event_handler); errors++; } - - /* save the pointer to the command for later */ - global_host_event_handler_ptr = temp_command; - - my_free(buf); } if(global_service_event_handler != NULL) { - - /* check the event handler command */ - buf = (char *)strdup(global_service_event_handler); - - /* get the command name, leave any arguments behind */ - temp_command_name = my_strtok(buf, "!"); - - temp_command = find_command(temp_command_name); - if(temp_command == NULL) { - logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Global service event handler command '%s' is not defined anywhere!", temp_command_name); + global_service_event_handler_ptr = find_bang_command(global_service_event_handler); + if (global_service_event_handler_ptr == NULL) { + logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Global service event handler command '%s' is not defined anywhere!", global_service_event_handler); errors++; } - - /* save the pointer to the command for later */ - global_service_event_handler_ptr = temp_command; - - my_free(buf); } /**************************************************/ /* check obsessive processor commands... */ /**************************************************/ - if(verify_config == TRUE) + if(verify_config) printf("Checking obsessive compulsive processor commands...\n"); if(ocsp_command != NULL) { - - buf = (char *)strdup(ocsp_command); - - /* get the command name, leave any arguments behind */ - temp_command_name = my_strtok(buf, "!"); - - temp_command = find_command(temp_command_name); - if(temp_command == NULL) { - logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Obsessive compulsive service processor command '%s' is not defined anywhere!", temp_command_name); + ocsp_command_ptr = find_bang_command(ocsp_command); + if (!ocsp_command_ptr) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: OCSP command '%s' is not defined anywhere!\n", ocsp_command); errors++; } - - /* save the pointer to the command for later */ - ocsp_command_ptr = temp_command; - - my_free(buf); } if(ochp_command != NULL) { - - buf = (char *)strdup(ochp_command); - - /* get the command name, leave any arguments behind */ - temp_command_name = my_strtok(buf, "!"); - - temp_command = find_command(temp_command_name); - if(temp_command == NULL) { - logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Obsessive compulsive host processor command '%s' is not defined anywhere!", temp_command_name); + ochp_command_ptr = find_bang_command(ochp_command); + if (!ochp_command_ptr) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: OCHP command '%s' is not defined anywhere!\n", ochp_command); errors++; } - - /* save the pointer to the command for later */ - ochp_command_ptr = temp_command; - - my_free(buf); } /**************************************************/ /* check various settings... */ /**************************************************/ - if(verify_config == TRUE) + if(verify_config) printf("Checking misc settings...\n"); /* check if we can write to temp_path */ @@ -1667,16 +1482,14 @@ int pre_flight_check(void) { logit(NSLOG_VERIFICATION_WARNING, TRUE, "%s", "Warning: Nothing specified for illegal_macro_output_chars variable!\n"); warnings++; } - - /* count number of services associated with each host (we need this for flap detection)... */ - for(temp_service = service_list; temp_service != NULL; temp_service = temp_service->next) { - if((temp_host = find_host(temp_service->host_name))) { - temp_host->total_services++; - temp_host->total_service_check_interval += temp_service->check_interval; + else { + char *p; + for(p = illegal_output_chars; *p; p++) { + illegal_output_char_map[(int)*p] = 1; } } - if(verify_config == TRUE) { + if(verify_config) { printf("\n"); printf("Total Warnings: %d\n", warnings); printf("Total Errors: %d\n", errors); @@ -1687,26 +1500,20 @@ int pre_flight_check(void) { if(test_scheduling == TRUE) { - if(verify_object_relationships == TRUE) - runtime[0] = (double)((double)(tv[1].tv_sec - tv[0].tv_sec) + (double)((tv[1].tv_usec - tv[0].tv_usec) / 1000.0) / 1000.0); - else - runtime[0] = 0.0; - if(verify_circular_paths == TRUE) - runtime[1] = (double)((double)(tv[2].tv_sec - tv[1].tv_sec) + (double)((tv[2].tv_usec - tv[1].tv_usec) / 1000.0) / 1000.0); - else - runtime[1] = 0.0; + runtime[0] = tv_delta_f(&tv[0], &tv[1]); + runtime[1] = tv_delta_f(&tv[1], &tv[2]); runtime[2] = (double)((double)(tv[3].tv_sec - tv[2].tv_sec) + (double)((tv[3].tv_usec - tv[2].tv_usec) / 1000.0) / 1000.0); runtime[3] = runtime[0] + runtime[1] + runtime[2]; printf("Timing information on configuration verification is listed below.\n\n"); - printf("CONFIG VERIFICATION TIMES (* = Potential for speedup with -x option)\n"); + printf("CONFIG VERIFICATION TIMES\n"); printf("----------------------------------\n"); printf("Object Relationships: %.6lf sec\n", runtime[0]); - printf("Circular Paths: %.6lf sec *\n", runtime[1]); + printf("Circular Paths: %.6lf sec\n", runtime[1]); printf("Misc: %.6lf sec\n", runtime[2]); printf(" ============\n"); - printf("TOTAL: %.6lf sec * = %.6lf sec (%.1f%%) estimated savings\n", runtime[3], runtime[1], (runtime[1] / runtime[3]) * 100.0); + printf("TOTAL: %.6lf sec\n", runtime[3]); printf("\n\n"); } @@ -1720,27 +1527,17 @@ int pre_flight_object_check(int *w, int *e) { contact *temp_contact = NULL; commandsmember *temp_commandsmember = NULL; contactgroup *temp_contactgroup = NULL; - contactsmember *temp_contactsmember = NULL; - contactgroupsmember *temp_contactgroupsmember = NULL; host *temp_host = NULL; host *temp_host2 = NULL; hostsmember *temp_hostsmember = NULL; + servicesmember *sm = NULL; hostgroup *temp_hostgroup = NULL; servicegroup *temp_servicegroup = NULL; - servicesmember *temp_servicesmember = NULL; service *temp_service = NULL; - service *temp_service2 = NULL; command *temp_command = NULL; timeperiod *temp_timeperiod = NULL; timeperiod *temp_timeperiod2 = NULL; timeperiodexclusion *temp_timeperiodexclusion = NULL; - serviceescalation *temp_se = NULL; - hostescalation *temp_he = NULL; - servicedependency *temp_sd = NULL; - hostdependency *temp_hd = NULL; - char *buf = NULL; - char *temp_command_name = ""; - int found = FALSE; int total_objects = 0; int warnings = 0; int errors = 0; @@ -1760,16 +1557,12 @@ int pre_flight_object_check(int *w, int *e) { } #endif - /* bail out if we aren't supposed to verify object relationships */ - if(verify_object_relationships == FALSE) - return OK; - + if(verify_config) + printf("Checking objects...\n"); /*****************************************/ /* check each service... */ /*****************************************/ - if(verify_config == TRUE) - printf("Checking services...\n"); if(get_service_count() == 0) { logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: There are no services defined!"); errors++; @@ -1778,98 +1571,29 @@ int pre_flight_object_check(int *w, int *e) { for(temp_service = service_list; temp_service != NULL; temp_service = temp_service->next) { total_objects++; - found = FALSE; - - /* check for a valid host */ - temp_host = find_host(temp_service->host_name); - - /* we couldn't find an associated host! */ - if(!temp_host) { - logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Host '%s' specified in service '%s' not defined anywhere!", temp_service->host_name, temp_service->description); - errors++; - } - - /* save the host pointer for later */ - temp_service->host_ptr = temp_host; - - /* add a reverse link from the host to the service for faster lookups later */ - add_service_link_to_host(temp_host, temp_service); /* check the event handler command */ if(temp_service->event_handler != NULL) { - - /* check the event handler command */ - buf = (char *)strdup(temp_service->event_handler); - - /* get the command name, leave any arguments behind */ - temp_command_name = my_strtok(buf, "!"); - - temp_command = find_command(temp_command_name); - if(temp_command == NULL) { - logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Event handler command '%s' specified in service '%s' for host '%s' not defined anywhere", temp_command_name, temp_service->description, temp_service->host_name); + temp_service->event_handler_ptr = find_bang_command(temp_service->event_handler); + if(temp_service->event_handler_ptr == NULL) { + logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Event handler command '%s' specified in service '%s' for host '%s' not defined anywhere", temp_service->event_handler, temp_service->description, temp_service->host_name); errors++; } - - my_free(buf); - - /* save the pointer to the event handler for later */ - temp_service->event_handler_ptr = temp_command; } /* check the service check_command */ - buf = (char *)strdup(temp_service->service_check_command); - - /* get the command name, leave any arguments behind */ - temp_command_name = my_strtok(buf, "!"); - - temp_command = find_command(temp_command_name); - if(temp_command == NULL) { - logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Service check command '%s' specified in service '%s' for host '%s' not defined anywhere!", temp_command_name, temp_service->description, temp_service->host_name); + temp_service->check_command_ptr = find_bang_command(temp_service->check_command); + if(temp_service->check_command_ptr == NULL) { + logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Service check command '%s' specified in service '%s' for host '%s' not defined anywhere!", temp_service->check_command, temp_service->description, temp_service->host_name); errors++; } - my_free(buf); - - /* save the pointer to the check command for later */ - temp_service->check_command_ptr = temp_command; - /* check for sane recovery options */ - if(temp_service->notify_on_recovery == TRUE && temp_service->notify_on_warning == FALSE && temp_service->notify_on_critical == FALSE) { + if(temp_service->notification_options == OPT_RECOVERY) { logit(NSLOG_VERIFICATION_WARNING, TRUE, "Warning: Recovery notification option in service '%s' for host '%s' doesn't make any sense - specify warning and/or critical options as well", temp_service->description, temp_service->host_name); warnings++; } - /* reset the found flag */ - found = FALSE; - - /* check for valid contacts */ - for(temp_contactsmember = temp_service->contacts; temp_contactsmember != NULL; temp_contactsmember = temp_contactsmember->next) { - - temp_contact = find_contact(temp_contactsmember->contact_name); - - if(temp_contact == NULL) { - logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Contact '%s' specified in service '%s' for host '%s' is not defined anywhere!", temp_contactsmember->contact_name, temp_service->description, temp_service->host_name); - errors++; - } - - /* save the contact pointer for later */ - temp_contactsmember->contact_ptr = temp_contact; - } - - /* check all contact groupss */ - for(temp_contactgroupsmember = temp_service->contact_groups; temp_contactgroupsmember != NULL; temp_contactgroupsmember = temp_contactgroupsmember->next) { - - temp_contactgroup = find_contactgroup(temp_contactgroupsmember->group_name); - - if(temp_contactgroup == NULL) { - logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Contact group '%s' specified in service '%s' for host '%s' is not defined anywhere!", temp_contactgroupsmember->group_name, temp_service->description, temp_service->host_name); - errors++; - } - - /* save the contact group pointer for later */ - temp_contactgroupsmember->group_ptr = temp_contactgroup; - } - /* check to see if there is at least one contact/group */ if(temp_service->contacts == NULL && temp_service->contact_groups == NULL) { logit(NSLOG_VERIFICATION_WARNING, TRUE, "Warning: Service '%s' on host '%s' has no default contacts or contactgroups defined!", temp_service->description, temp_service->host_name); @@ -1881,16 +1605,6 @@ int pre_flight_object_check(int *w, int *e) { logit(NSLOG_VERIFICATION_WARNING, TRUE, "Warning: Service '%s' on host '%s' has no check time period defined!", temp_service->description, temp_service->host_name); warnings++; } - else { - temp_timeperiod = find_timeperiod(temp_service->check_period); - if(temp_timeperiod == NULL) { - logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Check period '%s' specified for service '%s' on host '%s' is not defined anywhere!", temp_service->check_period, temp_service->description, temp_service->host_name); - errors++; - } - - /* save the pointer to the check timeperiod for later */ - temp_service->check_period_ptr = temp_timeperiod; - } /* check service notification timeperiod */ if(temp_service->notification_period == NULL) { @@ -1898,15 +1612,18 @@ int pre_flight_object_check(int *w, int *e) { warnings++; } - else { - temp_timeperiod = find_timeperiod(temp_service->notification_period); - if(temp_timeperiod == NULL) { - logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Notification period '%s' specified for service '%s' on host '%s' is not defined anywhere!", temp_service->notification_period, temp_service->description, temp_service->host_name); + /* check parent services */ + for(sm = temp_service->parents; sm; sm = sm->next) { + sm->service_ptr = find_service(sm->host_name, sm->service_description); + if(sm->service_ptr == NULL) { + logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Service '%s' on host '%s' is not a valid parent for service '%s' on host '%s'\n", + sm->host_name, sm->service_description, + temp_service->host_name, temp_service->description); errors++; } - /* save the pointer to the notification timeperiod for later */ - temp_service->notification_period_ptr = temp_timeperiod; + /* add a reverse (child) link to make searches faster later on */ + add_child_link_to_service(sm->service_ptr, temp_service); } /* see if the notification interval is less than the check interval */ @@ -1924,7 +1641,7 @@ int pre_flight_object_check(int *w, int *e) { } } - if(verify_config == TRUE) + if(verify_config) printf("\tChecked %d services.\n", total_objects); @@ -1932,9 +1649,6 @@ int pre_flight_object_check(int *w, int *e) { /*****************************************/ /* check all hosts... */ /*****************************************/ - if(verify_config == TRUE) - printf("Checking hosts...\n"); - if(get_host_count() == 0) { logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: There are no hosts defined!"); errors++; @@ -1944,68 +1658,29 @@ int pre_flight_object_check(int *w, int *e) { for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) { total_objects++; - found = FALSE; /* make sure each host has at least one service associated with it */ - /* 02/21/08 NOTE: this is extremely inefficient */ - if(use_precached_objects == FALSE && use_large_installation_tweaks == FALSE) { - - for(temp_service = service_list; temp_service != NULL; temp_service = temp_service->next) { - if(!strcmp(temp_service->host_name, temp_host->name)) { - found = TRUE; - break; - } - } - - /* we couldn't find a service associated with this host! */ - if(found == FALSE) { - logit(NSLOG_VERIFICATION_WARNING, TRUE, "Warning: Host '%s' has no services associated with it!", temp_host->name); - warnings++; - } - - found = FALSE; + if(temp_host->total_services == 0 && verify_config >= 2) { + logit(NSLOG_VERIFICATION_WARNING, TRUE, "Warning: Host '%s' has no services associated with it!", temp_host->name); + warnings++; } /* check the event handler command */ if(temp_host->event_handler != NULL) { - - /* check the event handler command */ - buf = (char *)strdup(temp_host->event_handler); - - /* get the command name, leave any arguments behind */ - temp_command_name = my_strtok(buf, "!"); - - temp_command = find_command(temp_command_name); - if(temp_command == NULL) { - logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Event handler command '%s' specified for host '%s' not defined anywhere", temp_command_name, temp_host->name); + temp_host->event_handler_ptr = find_bang_command(temp_host->event_handler); + if(temp_host->event_handler_ptr == NULL) { + logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Event handler command '%s' specified for host '%s' not defined anywhere", temp_host->event_handler, temp_host->name); errors++; } - - my_free(buf); - - /* save the pointer to the event handler command for later */ - temp_host->event_handler_ptr = temp_command; } /* hosts that don't have check commands defined shouldn't ever be checked... */ - if(temp_host->host_check_command != NULL) { - - /* check the host check_command */ - buf = (char *)strdup(temp_host->host_check_command); - - /* get the command name, leave any arguments behind */ - temp_command_name = my_strtok(buf, "!"); - - temp_command = find_command(temp_command_name); - if(temp_command == NULL) { - logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Host check command '%s' specified for host '%s' is not defined anywhere!", temp_command_name, temp_host->name); + if(temp_host->check_command != NULL) { + temp_host->check_command_ptr = find_bang_command(temp_host->check_command); + if(temp_host->check_command_ptr == NULL) { + logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Host check command '%s' specified for host '%s' is not defined anywhere!", temp_host->check_command, temp_host->name); errors++; } - - /* save the pointer to the check command for later */ - temp_host->check_command_ptr = temp_command; - - my_free(buf); } /* check host check timeperiod */ @@ -2020,34 +1695,6 @@ int pre_flight_object_check(int *w, int *e) { temp_host->check_period_ptr = temp_timeperiod; } - /* check all contacts */ - for(temp_contactsmember = temp_host->contacts; temp_contactsmember != NULL; temp_contactsmember = temp_contactsmember->next) { - - temp_contact = find_contact(temp_contactsmember->contact_name); - - if(temp_contact == NULL) { - logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Contact '%s' specified in host '%s' is not defined anywhere!", temp_contactsmember->contact_name, temp_host->name); - errors++; - } - - /* save the contact pointer for later */ - temp_contactsmember->contact_ptr = temp_contact; - } - - /* check all contact groups */ - for(temp_contactgroupsmember = temp_host->contact_groups; temp_contactgroupsmember != NULL; temp_contactgroupsmember = temp_contactgroupsmember->next) { - - temp_contactgroup = find_contactgroup(temp_contactgroupsmember->group_name); - - if(temp_contactgroup == NULL) { - logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Contact group '%s' specified in host '%s' is not defined anywhere!", temp_contactgroupsmember->group_name, temp_host->name); - errors++; - } - - /* save the contact group pointer for later */ - temp_contactgroupsmember->group_ptr = temp_contactgroup; - } - /* check to see if there is at least one contact/group */ if(temp_host->contacts == NULL && temp_host->contact_groups == NULL) { logit(NSLOG_VERIFICATION_WARNING, TRUE, "Warning: Host '%s' has no default contacts or contactgroups defined!", temp_host->name); @@ -2082,7 +1729,7 @@ int pre_flight_object_check(int *w, int *e) { } /* check for sane recovery options */ - if(temp_host->notify_on_recovery == TRUE && temp_host->notify_on_down == FALSE && temp_host->notify_on_unreachable == FALSE) { + if(temp_host->notification_options == OPT_RECOVERY) { logit(NSLOG_VERIFICATION_WARNING, TRUE, "Warning: Recovery notification option in host '%s' definition doesn't make any sense - specify down and/or unreachable options as well", temp_host->name); warnings++; } @@ -2097,34 +1744,14 @@ int pre_flight_object_check(int *w, int *e) { } - if(verify_config == TRUE) + if(verify_config) printf("\tChecked %d hosts.\n", total_objects); /*****************************************/ /* check each host group... */ /*****************************************/ - if(verify_config == TRUE) - printf("Checking host groups...\n"); for(temp_hostgroup = hostgroup_list, total_objects = 0; temp_hostgroup != NULL; temp_hostgroup = temp_hostgroup->next, total_objects++) { - - /* check all group members */ - for(temp_hostsmember = temp_hostgroup->members; temp_hostsmember != NULL; temp_hostsmember = temp_hostsmember->next) { - - temp_host = find_host(temp_hostsmember->host_name); - if(temp_host == NULL) { - logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Host '%s' specified in host group '%s' is not defined anywhere!", temp_hostsmember->host_name, temp_hostgroup->group_name); - errors++; - } - - /* save a pointer to this hostgroup for faster host/group membership lookups later */ - else - add_object_to_objectlist(&temp_host->hostgroups_ptr, (void *)temp_hostgroup); - - /* save host pointer for later */ - temp_hostsmember->host_ptr = temp_host; - } - /* check for illegal characters in hostgroup name */ if(use_precached_objects == FALSE) { if(contains_illegal_object_chars(temp_hostgroup->group_name) == TRUE) { @@ -2134,34 +1761,14 @@ int pre_flight_object_check(int *w, int *e) { } } - if(verify_config == TRUE) + if(verify_config) printf("\tChecked %d host groups.\n", total_objects); /*****************************************/ /* check each service group... */ /*****************************************/ - if(verify_config == TRUE) - printf("Checking service groups...\n"); for(temp_servicegroup = servicegroup_list, total_objects = 0; temp_servicegroup != NULL; temp_servicegroup = temp_servicegroup->next, total_objects++) { - - /* check all group members */ - for(temp_servicesmember = temp_servicegroup->members; temp_servicesmember != NULL; temp_servicesmember = temp_servicesmember->next) { - - temp_service = find_service(temp_servicesmember->host_name, temp_servicesmember->service_description); - if(temp_service == NULL) { - logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Service '%s' on host '%s' specified in service group '%s' is not defined anywhere!", temp_servicesmember->service_description, temp_servicesmember->host_name, temp_servicegroup->group_name); - errors++; - } - - /* save a pointer to this servicegroup for faster service/group membership lookups later */ - else - add_object_to_objectlist(&temp_service->servicegroups_ptr, (void *)temp_servicegroup); - - /* save service pointer for later */ - temp_servicesmember->service_ptr = temp_service; - } - /* check for illegal characters in servicegroup name */ if(use_precached_objects == FALSE) { if(contains_illegal_object_chars(temp_servicegroup->group_name) == TRUE) { @@ -2171,7 +1778,7 @@ int pre_flight_object_check(int *w, int *e) { } } - if(verify_config == TRUE) + if(verify_config) printf("\tChecked %d service groups.\n", total_objects); @@ -2179,8 +1786,6 @@ int pre_flight_object_check(int *w, int *e) { /*****************************************/ /* check all contacts... */ /*****************************************/ - if(verify_config == TRUE) - printf("Checking contacts...\n"); if(contact_list == NULL) { logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: There are no contacts defined!"); errors++; @@ -2193,24 +1798,12 @@ int pre_flight_object_check(int *w, int *e) { errors++; } else for(temp_commandsmember = temp_contact->service_notification_commands; temp_commandsmember != NULL; temp_commandsmember = temp_commandsmember->next) { - - /* check the host notification command */ - buf = (char *)strdup(temp_commandsmember->command); - - /* get the command name, leave any arguments behind */ - temp_command_name = my_strtok(buf, "!"); - - temp_command = find_command(temp_command_name); - if(temp_command == NULL) { - logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Service notification command '%s' specified for contact '%s' is not defined anywhere!", temp_command_name, temp_contact->name); - errors++; - } - - /* save pointer to the command for later */ - temp_commandsmember->command_ptr = temp_command; - - my_free(buf); + temp_commandsmember->command_ptr = find_bang_command(temp_commandsmember->command); + if(temp_commandsmember->command_ptr == NULL) { + logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Service notification command '%s' specified for contact '%s' is not defined anywhere!", temp_commandsmember->command, temp_contact->name); + errors++; } + } /* check host notification commands */ if(temp_contact->host_notification_commands == NULL) { @@ -2218,24 +1811,12 @@ int pre_flight_object_check(int *w, int *e) { errors++; } else for(temp_commandsmember = temp_contact->host_notification_commands; temp_commandsmember != NULL; temp_commandsmember = temp_commandsmember->next) { - - /* check the host notification command */ - buf = (char *)strdup(temp_commandsmember->command); - - /* get the command name, leave any arguments behind */ - temp_command_name = my_strtok(buf, "!"); - - temp_command = find_command(temp_command_name); - if(temp_command == NULL) { - logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Host notification command '%s' specified for contact '%s' is not defined anywhere!", temp_command_name, temp_contact->name); - errors++; - } - - /* save pointer to the command for later */ - temp_commandsmember->command_ptr = temp_command; - - my_free(buf); + temp_commandsmember->command_ptr = find_bang_command(temp_commandsmember->command); + if(temp_commandsmember->command_ptr == NULL) { + logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Host notification command '%s' specified for contact '%s' is not defined anywhere!", temp_commandsmember->command, temp_contact->name); + errors++; } + } /* check service notification timeperiod */ if(temp_contact->service_notification_period == NULL) { @@ -2272,13 +1853,13 @@ int pre_flight_object_check(int *w, int *e) { } /* check for sane host recovery options */ - if(temp_contact->notify_on_host_recovery == TRUE && temp_contact->notify_on_host_down == FALSE && temp_contact->notify_on_host_unreachable == FALSE) { + if(temp_contact->host_notification_options == OPT_RECOVERY) { logit(NSLOG_VERIFICATION_WARNING, TRUE, "Warning: Host recovery notification option for contact '%s' doesn't make any sense - specify down and/or unreachable options as well", temp_contact->name); warnings++; } /* check for sane service recovery options */ - if(temp_contact->notify_on_service_recovery == TRUE && temp_contact->notify_on_service_critical == FALSE && temp_contact->notify_on_service_warning == FALSE) { + if(temp_contact->service_notification_options == OPT_RECOVERY) { logit(NSLOG_VERIFICATION_WARNING, TRUE, "Warning: Service recovery notification option for contact '%s' doesn't make any sense - specify critical and/or warning options as well", temp_contact->name); warnings++; } @@ -2292,7 +1873,7 @@ int pre_flight_object_check(int *w, int *e) { } } - if(verify_config == TRUE) + if(verify_config) printf("\tChecked %d contacts.\n", total_objects); @@ -2300,29 +1881,7 @@ int pre_flight_object_check(int *w, int *e) { /*****************************************/ /* check each contact group... */ /*****************************************/ - if(verify_config == TRUE) - printf("Checking contact groups...\n"); for(temp_contactgroup = contactgroup_list, total_objects = 0; temp_contactgroup != NULL; temp_contactgroup = temp_contactgroup->next, total_objects++) { - - found = FALSE; - - /* check all the group members */ - for(temp_contactsmember = temp_contactgroup->members; temp_contactsmember != NULL; temp_contactsmember = temp_contactsmember->next) { - - temp_contact = find_contact(temp_contactsmember->contact_name); - if(temp_contact == NULL) { - logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Contact '%s' specified in contact group '%s' is not defined anywhere!", temp_contactsmember->contact_name, temp_contactgroup->group_name); - errors++; - } - - /* save a pointer to this contactgroup for faster contact/group membership lookups later */ - else - add_object_to_objectlist(&temp_contact->contactgroups_ptr, (void *)temp_contactgroup); - - /* save the contact pointer for later */ - temp_contactsmember->contact_ptr = temp_contact; - } - /* check for illegal characters in contactgroup name */ if(use_precached_objects == FALSE) { if(contains_illegal_object_chars(temp_contactgroup->group_name) == TRUE) { @@ -2332,249 +1891,13 @@ int pre_flight_object_check(int *w, int *e) { } } - if(verify_config == TRUE) + if(verify_config) printf("\tChecked %d contact groups.\n", total_objects); - - /*****************************************/ - /* check all service escalations... */ - /*****************************************/ - if(verify_config == TRUE) - printf("Checking service escalations...\n"); - - for(temp_se = serviceescalation_list, total_objects = 0; temp_se != NULL; temp_se = temp_se->next, total_objects++) { - - /* find the service */ - temp_service = find_service(temp_se->host_name, temp_se->description); - if(temp_service == NULL) { - logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Service '%s' on host '%s' specified in service escalation is not defined anywhere!", temp_se->description, temp_se->host_name); - errors++; - } - - /* save the service pointer for later */ - temp_se->service_ptr = temp_service; - - /* find the timeperiod */ - if(temp_se->escalation_period != NULL) { - temp_timeperiod = find_timeperiod(temp_se->escalation_period); - if(temp_timeperiod == NULL) { - logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Escalation period '%s' specified in service escalation for service '%s' on host '%s' is not defined anywhere!", temp_se->escalation_period, temp_se->description, temp_se->host_name); - errors++; - } - - /* save the timeperiod pointer for later */ - temp_se->escalation_period_ptr = temp_timeperiod; - } - - /* find the contacts */ - for(temp_contactsmember = temp_se->contacts; temp_contactsmember != NULL; temp_contactsmember = temp_contactsmember->next) { - - /* find the contact */ - temp_contact = find_contact(temp_contactsmember->contact_name); - if(temp_contact == NULL) { - logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Contact '%s' specified in service escalation for service '%s' on host '%s' is not defined anywhere!", temp_contactsmember->contact_name, temp_se->description, temp_se->host_name); - errors++; - } - - /* save the contact pointer for later */ - temp_contactsmember->contact_ptr = temp_contact; - } - - /* check all contact groups */ - for(temp_contactgroupsmember = temp_se->contact_groups; temp_contactgroupsmember != NULL; temp_contactgroupsmember = temp_contactgroupsmember->next) { - - temp_contactgroup = find_contactgroup(temp_contactgroupsmember->group_name); - - if(temp_contactgroup == NULL) { - logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Contact group '%s' specified in service escalation for service '%s' on host '%s' is not defined anywhere!", temp_contactgroupsmember->group_name, temp_se->description, temp_se->host_name); - errors++; - } - - /* save the contact group pointer for later */ - temp_contactgroupsmember->group_ptr = temp_contactgroup; - } - } - - if(verify_config == TRUE) - printf("\tChecked %d service escalations.\n", total_objects); - - - - /*****************************************/ - /* check all service dependencies... */ - /*****************************************/ - if(verify_config == TRUE) - printf("Checking service dependencies...\n"); - - for(temp_sd = servicedependency_list, total_objects = 0; temp_sd != NULL; temp_sd = temp_sd->next, total_objects++) { - - /* find the dependent service */ - temp_service = find_service(temp_sd->dependent_host_name, temp_sd->dependent_service_description); - if(temp_service == NULL) { - logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Dependent service '%s' on host '%s' specified in service dependency for service '%s' on host '%s' is not defined anywhere!", temp_sd->dependent_service_description, temp_sd->dependent_host_name, temp_sd->service_description, temp_sd->host_name); - errors++; - } - - /* save pointer for later */ - temp_sd->dependent_service_ptr = temp_service; - - /* find the service we're depending on */ - temp_service2 = find_service(temp_sd->host_name, temp_sd->service_description); - if(temp_service2 == NULL) { - logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Service '%s' on host '%s' specified in service dependency for service '%s' on host '%s' is not defined anywhere!", temp_sd->service_description, temp_sd->host_name, temp_sd->dependent_service_description, temp_sd->dependent_host_name); - errors++; - } - - /* save pointer for later */ - temp_sd->master_service_ptr = temp_service2; - - /* make sure they're not the same service */ - if(temp_service == temp_service2) { - logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Service dependency definition for service '%s' on host '%s' is circular (it depends on itself)!", temp_sd->dependent_service_description, temp_sd->dependent_host_name); - errors++; - } - - /* find the timeperiod */ - if(temp_sd->dependency_period != NULL) { - temp_timeperiod = find_timeperiod(temp_sd->dependency_period); - if(temp_timeperiod == NULL) { - logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Dependency period '%s' specified in service dependency for service '%s' on host '%s' is not defined anywhere!", temp_sd->dependency_period, temp_sd->dependent_service_description, temp_sd->dependent_host_name); - errors++; - } - - /* save the timeperiod pointer for later */ - temp_sd->dependency_period_ptr = temp_timeperiod; - } - } - - if(verify_config == TRUE) - printf("\tChecked %d service dependencies.\n", total_objects); - - - - /*****************************************/ - /* check all host escalations... */ - /*****************************************/ - if(verify_config == TRUE) - printf("Checking host escalations...\n"); - - for(temp_he = hostescalation_list, total_objects = 0; temp_he != NULL; temp_he = temp_he->next, total_objects++) { - - /* find the host */ - temp_host = find_host(temp_he->host_name); - if(temp_host == NULL) { - logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Host '%s' specified in host escalation is not defined anywhere!", temp_he->host_name); - errors++; - } - - /* save the host pointer for later */ - temp_he->host_ptr = temp_host; - - /* find the timeperiod */ - if(temp_he->escalation_period != NULL) { - temp_timeperiod = find_timeperiod(temp_he->escalation_period); - if(temp_timeperiod == NULL) { - logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Escalation period '%s' specified in host escalation for host '%s' is not defined anywhere!", temp_he->escalation_period, temp_he->host_name); - errors++; - } - - /* save the timeperiod pointer for later */ - temp_he->escalation_period_ptr = temp_timeperiod; - } - - /* find the contacts */ - for(temp_contactsmember = temp_he->contacts; temp_contactsmember != NULL; temp_contactsmember = temp_contactsmember->next) { - - /* find the contact*/ - temp_contact = find_contact(temp_contactsmember->contact_name); - if(temp_contact == NULL) { - logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Contact '%s' specified in host escalation for host '%s' is not defined anywhere!", temp_contactsmember->contact_name, temp_he->host_name); - errors++; - } - - /* save the contact pointer for later */ - temp_contactsmember->contact_ptr = temp_contact; - } - - /* check all contact groups */ - for(temp_contactgroupsmember = temp_he->contact_groups; temp_contactgroupsmember != NULL; temp_contactgroupsmember = temp_contactgroupsmember->next) { - - temp_contactgroup = find_contactgroup(temp_contactgroupsmember->group_name); - - if(temp_contactgroup == NULL) { - logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Contact group '%s' specified in host escalation for host '%s' is not defined anywhere!", temp_contactgroupsmember->group_name, temp_he->host_name); - errors++; - } - - /* save the contact group pointer for later */ - temp_contactgroupsmember->group_ptr = temp_contactgroup; - } - } - - if(verify_config == TRUE) - printf("\tChecked %d host escalations.\n", total_objects); - - - - /*****************************************/ - /* check all host dependencies... */ - /*****************************************/ - if(verify_config == TRUE) - printf("Checking host dependencies...\n"); - - for(temp_hd = hostdependency_list, total_objects = 0; temp_hd != NULL; temp_hd = temp_hd->next, total_objects++) { - - /* find the dependent host */ - temp_host = find_host(temp_hd->dependent_host_name); - if(temp_host == NULL) { - logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Dependent host specified in host dependency for host '%s' is not defined anywhere!", temp_hd->dependent_host_name); - errors++; - } - - /* save pointer for later */ - temp_hd->dependent_host_ptr = temp_host; - - /* find the host we're depending on */ - temp_host2 = find_host(temp_hd->host_name); - if(temp_host2 == NULL) { - logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Host specified in host dependency for host '%s' is not defined anywhere!", temp_hd->dependent_host_name); - errors++; - } - - /* save pointer for later */ - temp_hd->master_host_ptr = temp_host2; - - /* make sure they're not the same host */ - if(temp_host == temp_host2) { - logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Host dependency definition for host '%s' is circular (it depends on itself)!", temp_hd->dependent_host_name); - errors++; - } - - /* find the timeperiod */ - if(temp_hd->dependency_period != NULL) { - temp_timeperiod = find_timeperiod(temp_hd->dependency_period); - if(temp_timeperiod == NULL) { - logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Dependency period '%s' specified in host dependency for host '%s' is not defined anywhere!", temp_hd->dependency_period, temp_hd->dependent_host_name); - errors++; - } - - /* save the timeperiod pointer for later */ - temp_hd->dependency_period_ptr = temp_timeperiod; - } - } - - if(verify_config == TRUE) - printf("\tChecked %d host dependencies.\n", total_objects); - - - /*****************************************/ /* check all commands... */ /*****************************************/ - if(verify_config == TRUE) - printf("Checking commands...\n"); - for(temp_command = command_list, total_objects = 0; temp_command != NULL; temp_command = temp_command->next, total_objects++) { /* check for illegal characters in command name */ @@ -2586,7 +1909,7 @@ int pre_flight_object_check(int *w, int *e) { } } - if(verify_config == TRUE) + if(verify_config) printf("\tChecked %d commands.\n", total_objects); @@ -2594,9 +1917,6 @@ int pre_flight_object_check(int *w, int *e) { /*****************************************/ /* check all timeperiods... */ /*****************************************/ - if(verify_config == TRUE) - printf("Checking time periods...\n"); - for(temp_timeperiod = timeperiod_list, total_objects = 0; temp_timeperiod != NULL; temp_timeperiod = temp_timeperiod->next, total_objects++) { /* check for illegal characters in timeperiod name */ @@ -2621,10 +1941,15 @@ int pre_flight_object_check(int *w, int *e) { } } - if(verify_config == TRUE) + if(verify_config) printf("\tChecked %d time periods.\n", total_objects); + /* help people use scripts to verify that objects are loaded */ + if(verify_config) { + printf("\tChecked %u host escalations.\n", num_objects.hostescalations); + printf("\tChecked %u service escalations.\n", num_objects.serviceescalations); + } /* update warning and error count */ *w += warnings; @@ -2641,20 +1966,142 @@ int pre_flight_object_check(int *w, int *e) { #define DFS_NEAR_LOOP 3 /* has trouble sons */ #define DFS_LOOPY 4 /* is a part of a loop */ -#define dfs_get_status(h) h->circular_path_checked -#define dfs_unset_status(h) h->circular_path_checked = 0 -#define dfs_set_status(h, flag) h->circular_path_checked = (flag) -#define dfs_host_status(h) (h ? dfs_get_status(h) : DFS_OK) +#define dfs_get_status(obj) (obj ? ary[obj->id] : DFS_OK) +#define dfs_set_status(obj, value) ary[obj->id] = (value) + /** * Modified version of Depth-first Search * http://en.wikipedia.org/wiki/Depth-first_search + * + * In a dependency tree like this (parent->child, dep->dep or whatever): + * A - B C + * \ / + * D + * / \ + * E - F - G + * / \\ + * H H + * + * ... we look at the nodes in the following order: + * A B D C G (marking all of them as OK) + * E F D G H F (D,G are already OK, E is marked near-loopy F and H are loopy) + * H (which is already marked as loopy, so we don't follow it) + * + * We look at each node at most once per parent, so the algorithm has + * O(nx) worst-case complexity,, where x is the average number of + * parents. */ -static int dfs_host_path(host *root) { - hostsmember *child = NULL; +/* + * same as dfs_host_path, but we flip the the tree and traverse it + * backwards, since core Nagios doesn't need the child pointer at + * later stages. + */ +static int dfs_servicedep_path(char *ary, service *root, int dep_type, int *errors) +{ + objectlist *olist; + int status; - if(!root) - return DFS_NEAR_LOOP; + status = dfs_get_status(root); + if(status != DFS_UNCHECKED) + return status; + + dfs_set_status(root, DFS_TEMP_CHECKED); + + if (dep_type == NOTIFICATION_DEPENDENCY) { + olist = root->notify_deps; + } else { + olist = root->exec_deps; + } + + if (!olist) { /* no children, so we can't be loopy */ + dfs_set_status(root, DFS_OK); + return DFS_OK; + } + for (; olist; olist = olist->next) { + int child_status; + service *child; + servicedependency *child_dep = (servicedependency *)olist->object_ptr; + + /* tree is upside down, so look to master */ + child = child_dep->master_service_ptr; + child_status = dfs_servicedep_path(ary, child, dep_type, errors); + + if (child_status == DFS_OK) + continue; + + if(child_status == DFS_TEMP_CHECKED) { + logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Circular %s dependency detected for services '%s;%s' and '%s;%s'\n", + dep_type == NOTIFICATION_DEPENDENCY ? "notification" : "execution", + root->host_name, root->description, + child->host_name, child->description); + (*errors)++; + dfs_set_status(child, DFS_LOOPY); + dfs_set_status(root, DFS_LOOPY); + continue; + } + } + + /* + * if we've hit ourself, we'll have marked us as loopy + * above, so if we're TEMP_CHECKED still we're ok + */ + if (dfs_get_status(root) == DFS_TEMP_CHECKED) + dfs_set_status(root, DFS_OK); + return dfs_get_status(root); +} + +static int dfs_hostdep_path(char *ary, host *root, int dep_type, int *errors) +{ + objectlist *olist; + int status; + + status = dfs_get_status(root); + if(status != DFS_UNCHECKED) + return status; + + dfs_set_status(root, DFS_TEMP_CHECKED); + + if (dep_type == NOTIFICATION_DEPENDENCY) { + olist = root->notify_deps; + } else { + olist = root->exec_deps; + } + + for (; olist; olist = olist->next) { + int child_status; + host *child; + hostdependency *child_dep = (hostdependency *)olist->object_ptr; + + child = child_dep->master_host_ptr; + child_status = dfs_hostdep_path(ary, child, dep_type, errors); + + if (child_status == DFS_OK) + continue; + + if(child_status == DFS_TEMP_CHECKED) { + logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Circular %s dependency detected for hosts '%s' and '%s'\n", + dep_type == NOTIFICATION_DEPENDENCY ? "notification" : "execution", + root->name, child->name); + dfs_set_status(child, DFS_LOOPY); + dfs_set_status(root, DFS_LOOPY); + (*errors)++; + continue; + } + } + + /* + * if we've hit ourself, we'll have marked us as loopy + * above, so if we're still TEMP_CHECKED we're ok + */ + if (dfs_get_status(root) == DFS_TEMP_CHECKED) + dfs_set_status(root, DFS_OK); + return dfs_get_status(root); +} + + +static int dfs_host_path(char *ary, host *root, int *errors) { + hostsmember *child = NULL; if(dfs_get_status(root) != DFS_UNCHECKED) return dfs_get_status(root); @@ -2664,27 +2111,20 @@ static int dfs_host_path(host *root) { /* We are scanning the children */ for(child = root->child_hosts; child != NULL; child = child->next) { - int child_status = dfs_get_status(child->host_ptr); + int child_status = dfs_host_path(ary, child->host_ptr, errors); - /* If a child is not checked, check it */ - if(child_status == DFS_UNCHECKED) - child_status = dfs_host_path(child->host_ptr); + /* we can move on quickly if child is ok */ + if(child_status == DFS_OK) + continue; /* If a child already temporary checked, its a problem, * loop inside, and its a acked status */ if(child_status == DFS_TEMP_CHECKED) { + logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: The hosts '%s' and '%s' form or lead into a circular parent/child chain!", root->name, child->host_ptr->name); + (*errors)++; dfs_set_status(child->host_ptr, DFS_LOOPY); dfs_set_status(root, DFS_LOOPY); - } - - /* If a child already temporary checked, its a problem, loop inside */ - if(child_status == DFS_NEAR_LOOP || child_status == DFS_LOOPY) { - /* if a node is know to be part of a loop, do not let it be less */ - if(dfs_get_status(root) != DFS_LOOPY) - dfs_set_status(root, DFS_NEAR_LOOP); - - /* we already saw this child, it's a problem */ - dfs_set_status(child->host_ptr, DFS_LOOPY); + continue; } } @@ -2698,121 +2138,128 @@ static int dfs_host_path(host *root) { return dfs_get_status(root); } +static int dfs_timeperiod_path(char *ary, timeperiod *root, int *errors) +{ + timeperiodexclusion *exc; + + if(dfs_get_status(root) != DFS_UNCHECKED) + return dfs_get_status(root); + + /* Mark the root temporary checked */ + dfs_set_status(root, DFS_TEMP_CHECKED); + + for (exc = root->exclusions; exc; exc = exc->next) { + int child_status = dfs_timeperiod_path(ary, exc->timeperiod_ptr, errors); + + if(child_status == DFS_TEMP_CHECKED) { + logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: The timeperiods '%s' and '%s' form or lead into a circular exclusion chain!", + root->name, exc->timeperiod_ptr->name); + (*errors)++; + dfs_set_status(exc->timeperiod_ptr, DFS_LOOPY); + dfs_set_status(root, DFS_LOOPY); + continue; + } + } + + if(dfs_get_status(root) == DFS_TEMP_CHECKED) + dfs_set_status(root, DFS_OK); + + return dfs_get_status(root); +} + /* check for circular paths and dependencies */ int pre_flight_circular_check(int *w, int *e) { host *temp_host = NULL; servicedependency *temp_sd = NULL; - servicedependency *temp_sd2 = NULL; hostdependency *temp_hd = NULL; - hostdependency *temp_hd2 = NULL; - int found = FALSE; - int result = OK; - int warnings = 0; + timeperiod *tp; + unsigned int i; int errors = 0; + unsigned int alloc, dep_type; + char *ary[2]; + if(num_objects.hosts > num_objects.services) + alloc = num_objects.hosts; + else + alloc = num_objects.services; + if(num_objects.timeperiods > alloc) + alloc = num_objects.timeperiods; - /* bail out if we aren't supposed to verify circular paths */ - if(verify_circular_paths == FALSE) - return OK; + for (i = 0; i < ARRAY_SIZE(ary); i++) { + if (!(ary[i] = calloc(1, alloc))) { + while (i) { + my_free(ary[--i]); + } + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Unable to allocate memory for circular path checks.\n"); + errors++; + return ERROR; + } + } /********************************************/ /* check for circular paths between hosts */ /********************************************/ - if(verify_config == TRUE) - printf("Checking for circular paths between hosts...\n"); - - /* check routes between all hosts */ - found = FALSE; - result = OK; - - - /* We clean the dsf status from previous check */ - for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) { - dfs_set_status(temp_host, DFS_UNCHECKED); - } + if(verify_config) + printf("Checking for circular paths...\n"); for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) { - if(dfs_host_path(temp_host) == DFS_LOOPY) - errors = 1; + dfs_host_path(ary[0], temp_host, &errors); } - - for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) { - if(dfs_get_status(temp_host) == DFS_LOOPY) - logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: The host '%s' is part of a circular parent/child chain!", temp_host->name); - /* clean DFS status */ - dfs_set_status(temp_host, DFS_UNCHECKED); - } - + if (verify_config) + printf("\tChecked %u hosts\n", num_objects.hosts); /********************************************/ - /* check for circular dependencies */ + /* check for circular dependencies */ /********************************************/ - if(verify_config == TRUE) - printf("Checking for circular host and service dependencies...\n"); + /* check service dependencies */ + /* We must clean the dfs status from previous check */ + for (i = 0; i < ARRAY_SIZE(ary); i++) + memset(ary[i], 0, alloc); + for(i = 0; i < num_objects.servicedependencies; i++) { + temp_sd = servicedependency_ary[i]; + dep_type = temp_sd->dependency_type; + /* + * this shouldn't happen, but it can in case dependencies are + * added to services on hosts in empty hostgroups (ie, nonexistent) + */ + if(dep_type < 1 || dep_type > ARRAY_SIZE(ary)) + continue; + dfs_servicedep_path(ary[dep_type - 1], temp_sd->dependent_service_ptr, dep_type, &errors); + } + if(verify_config) + printf("\tChecked %u service dependencies\n", num_objects.servicedependencies); - /* check execution dependencies between all services */ - for(temp_sd = servicedependency_list; temp_sd != NULL; temp_sd = temp_sd->next) { - - /* clear checked flag for all dependencies */ - for(temp_sd2 = servicedependency_list; temp_sd2 != NULL; temp_sd2 = temp_sd2->next) - temp_sd2->circular_path_checked = FALSE; - - found = check_for_circular_servicedependency_path(temp_sd, temp_sd, EXECUTION_DEPENDENCY); - if(found == TRUE) { - logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: A circular execution dependency (which could result in a deadlock) exists for service '%s' on host '%s'!", temp_sd->service_description, temp_sd->host_name); - errors++; - } + /* check host dependencies */ + for (i = 0; i < ARRAY_SIZE(ary); i++) + memset(ary[i], 0, alloc); + for(i = 0; i < num_objects.hostdependencies; i++) { + temp_hd = hostdependency_ary[i]; + dep_type = temp_hd->dependency_type; + /* see above */ + if(dep_type < 1 || dep_type > ARRAY_SIZE(ary)) + continue; + dfs_hostdep_path(ary[dep_type - 1], temp_hd->dependent_host_ptr, dep_type, &errors); } - /* check notification dependencies between all services */ - for(temp_sd = servicedependency_list; temp_sd != NULL; temp_sd = temp_sd->next) { + if(verify_config) + printf("\tChecked %u host dependencies\n", num_objects.hostdependencies); - /* clear checked flag for all dependencies */ - for(temp_sd2 = servicedependency_list; temp_sd2 != NULL; temp_sd2 = temp_sd2->next) - temp_sd2->circular_path_checked = FALSE; - - found = check_for_circular_servicedependency_path(temp_sd, temp_sd, NOTIFICATION_DEPENDENCY); - if(found == TRUE) { - logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: A circular notification dependency (which could result in a deadlock) exists for service '%s' on host '%s'!", temp_sd->service_description, temp_sd->host_name); - errors++; - } + /* check timeperiod exclusion chains */ + for (i = 0; i < ARRAY_SIZE(ary); i++) + memset(ary[i], 0, alloc); + for (tp = timeperiod_list; tp; tp = tp->next) { + dfs_timeperiod_path(ary[0], tp, &errors); } - - /* check execution dependencies between all hosts */ - for(temp_hd = hostdependency_list; temp_hd != NULL; temp_hd = temp_hd->next) { - - /* clear checked flag for all dependencies */ - for(temp_hd2 = hostdependency_list; temp_hd2 != NULL; temp_hd2 = temp_hd2->next) - temp_hd2->circular_path_checked = FALSE; - - found = check_for_circular_hostdependency_path(temp_hd, temp_hd, EXECUTION_DEPENDENCY); - if(found == TRUE) { - logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: A circular execution dependency (which could result in a deadlock) exists for host '%s'!", temp_hd->host_name); - errors++; - } - } - - /* check notification dependencies between all hosts */ - for(temp_hd = hostdependency_list; temp_hd != NULL; temp_hd = temp_hd->next) { - - /* clear checked flag for all dependencies */ - for(temp_hd2 = hostdependency_list; temp_hd2 != NULL; temp_hd2 = temp_hd2->next) - temp_hd2->circular_path_checked = FALSE; - - found = check_for_circular_hostdependency_path(temp_hd, temp_hd, NOTIFICATION_DEPENDENCY); - if(found == TRUE) { - logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: A circular notification dependency (which could result in a deadlock) exists for host '%s'!", temp_hd->host_name); - errors++; - } - } - + if (verify_config) + printf("\tChecked %u timeperiods\n", num_objects.timeperiods); /* update warning and error count */ - *w += warnings; *e += errors; + for (i = 0; i < ARRAY_SIZE(ary); i++) + free(ary[i]); + return (errors > 0) ? ERROR : OK; } - diff --git a/base/events.c b/base/events.c index 9062621..301e2c8 100644 --- a/base/events.c +++ b/base/events.c @@ -2,8 +2,6 @@ * * EVENTS.C - Timed event functions for Nagios * - * Copyright (c) 1999-2010 Ethan Galstad (egalstad@nagios.org) - * Last Modified: 08-28-2010 * * License: * @@ -30,84 +28,52 @@ #include "../include/nagios.h" #include "../include/broker.h" #include "../include/sretention.h" +#include "../include/workers.h" +#include "../lib/squeue.h" +/* the event we're currently processing */ +static timed_event *current_event; -extern char *config_file; - -extern int test_scheduling; - -extern time_t program_start; -extern time_t event_start; -extern time_t last_command_check; - -extern int sigshutdown; -extern int sigrestart; - -extern double sleep_time; -extern int interval_length; -extern int service_inter_check_delay_method; -extern int host_inter_check_delay_method; -extern int service_interleave_factor_method; -extern int max_host_check_spread; -extern int max_service_check_spread; - -extern int command_check_interval; -extern int check_reaper_interval; -extern int service_freshness_check_interval; -extern int host_freshness_check_interval; -extern int auto_rescheduling_interval; -extern int auto_rescheduling_window; - -extern int check_external_commands; -extern int check_orphaned_services; -extern int check_orphaned_hosts; -extern int check_service_freshness; -extern int check_host_freshness; -extern int auto_reschedule_checks; - -extern int retain_state_information; -extern int retention_update_interval; - -extern int max_parallel_service_checks; -extern int currently_running_service_checks; - -extern int aggregate_status_updates; -extern int status_update_interval; - -extern int log_rotation_method; - -extern int service_check_timeout; - -extern int execute_service_checks; -extern int execute_host_checks; - -extern int child_processes_fork_twice; - -extern int time_change_threshold; - -timed_event *event_list_low = NULL; -timed_event *event_list_low_tail = NULL; -timed_event *event_list_high = NULL; -timed_event *event_list_high_tail = NULL; - -extern host *host_list; -extern service *service_list; - -sched_info scheduling_info; - - +static unsigned int event_count[EVENT_USER_FUNCTION + 1]; /******************************************************************/ /************ EVENT SCHEDULING/HANDLING FUNCTIONS *****************/ /******************************************************************/ +int dump_event_stats(int sd) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(event_count); i++) { + nsock_printf(sd, "%s=%u;", EVENT_TYPE_STR(i), event_count[i]); + /* + * VERSIONFIX: Make EVENT_SLEEP and EVENT_USER_FUNCTION + * appear in linear order in include/nagios.h when we go + * from 4.0 -> 4.1, so we can remove this junk. + */ + if (i == 16) + i = 97; + } + nsock_printf_nul(sd, "SQUEUE_ENTRIES=%u", squeue_size(nagios_squeue)); + + return OK; + } + +static void track_events(unsigned int type, int add) +{ + /* + * remove_event() calls track_events() with add being -1. + * add_event() calls us with add being 1 + */ + if (type < ARRAY_SIZE(event_count)) + event_count[type] += add; + } /* initialize the event timing loop before we start monitoring */ void init_timing_loop(void) { host *temp_host = NULL; service *temp_service = NULL; time_t current_time = 0L; - unsigned long interval_to_use = 0L; int total_interleave_blocks = 0; int current_interleave_block = 1; int interleave_block_index = 0; @@ -118,12 +84,16 @@ void init_timing_loop(void) { double max_inter_check_delay = 0.0; struct timeval tv[9]; double runtime[9]; - + struct timeval now; + unsigned int fixed_hosts = 0, fixed_services = 0; + int check_delay = 0; log_debug_info(DEBUGL_FUNCTIONS, 0, "init_timing_loop() start\n"); - /* get the time right now */ - time(¤t_time); + /* get the time and seed the prng */ + gettimeofday(&now, NULL); + current_time = now.tv_sec; + srand((now.tv_sec << 10) ^ now.tv_usec); /******** GET BASIC HOST/SERVICE INFO ********/ @@ -165,6 +135,10 @@ void init_timing_loop(void) { } if(schedule_check == TRUE) { + double exec_time; + + /* get real exec time, or make a pessimistic guess */ + exec_time = temp_service->execution_time ? temp_service->execution_time : 2.0; scheduling_info.total_scheduled_services++; @@ -172,7 +146,7 @@ void init_timing_loop(void) { scheduling_info.service_check_interval_total += temp_service->check_interval; /* calculate rolling average execution time (available from retained state information) */ - scheduling_info.average_service_execution_time = (double)(((scheduling_info.average_service_execution_time * (scheduling_info.total_scheduled_services - 1)) + temp_service->execution_time) / (double)scheduling_info.total_scheduled_services); + scheduling_info.average_service_execution_time = (double)(((scheduling_info.average_service_execution_time * (scheduling_info.total_scheduled_services - 1)) + exec_time) / (double)scheduling_info.total_scheduled_services); } else { temp_service->should_be_scheduled = FALSE; @@ -238,7 +212,7 @@ void init_timing_loop(void) { /******** DETERMINE SERVICE SCHEDULING PARAMS ********/ - log_debug_info(DEBUGL_EVENTS, 2, "Determining service scheduling parameters..."); + log_debug_info(DEBUGL_EVENTS, 2, "Determining service scheduling parameters...\n"); /* default max service check spread (in minutes) */ scheduling_info.max_service_check_spread = max_service_check_spread; @@ -330,7 +304,7 @@ void init_timing_loop(void) { /******** SCHEDULE SERVICE CHECKS ********/ - log_debug_info(DEBUGL_EVENTS, 2, "Scheduling service checks..."); + log_debug_info(DEBUGL_EVENTS, 2, "Scheduling service checks...\n"); /* determine check times for service checks (with interleaving to minimize remote load) */ current_interleave_block = 0; @@ -339,8 +313,6 @@ void init_timing_loop(void) { log_debug_info(DEBUGL_EVENTS, 2, "Current Interleave Block: %d\n", current_interleave_block); for(interleave_block_index = 0; interleave_block_index < scheduling_info.service_interleave_factor && temp_service != NULL; temp_service = temp_service->next) { - int check_delay = 0; - log_debug_info(DEBUGL_EVENTS, 2, "Service '%s' on host '%s'\n", temp_service->description, temp_service->host_name); /* skip this service if it shouldn't be scheduled */ if(temp_service->should_be_scheduled == FALSE) { @@ -348,14 +320,6 @@ void init_timing_loop(void) { continue; } - /* skip services whose checks are currently executing */ - if(temp_service->is_executing) { - log_debug_info(DEBUGL_EVENTS, 2, - "Service check '%s' on host '%s' is already executing.\n", - temp_service->description, temp_service->host_name); - continue; - } - /* * skip services that are already scheduled for the (near) * future from retention data, but reschedule ones that @@ -366,7 +330,7 @@ void init_timing_loop(void) { * hanging too long without being run. */ check_delay = temp_service->next_check - current_time; - if(check_delay > 0 && check_delay < (temp_service->check_interval * interval_length)) { + if(check_delay > 0 && check_delay < check_window(temp_service)) { log_debug_info(DEBUGL_EVENTS, 2, "Service is already scheduled to be checked in the future: %s\n", ctime(&temp_service->next_check)); continue; } @@ -380,21 +344,37 @@ void init_timing_loop(void) { log_debug_info(DEBUGL_EVENTS, 2, "CIB: %d, IBI: %d, TIB: %d, SIF: %d\n", current_interleave_block, interleave_block_index, total_interleave_blocks, scheduling_info.service_interleave_factor); log_debug_info(DEBUGL_EVENTS, 2, "Mult factor: %d\n", mult_factor); - /* set the preferred next check time for the service */ - temp_service->next_check = (time_t)(current_time + (mult_factor * scheduling_info.service_inter_check_delay)); + /* + * set the preferred next check time for the service + * If we end up too far into the future, grab a random + * time within the service's window instead. + */ + check_delay = + mult_factor * scheduling_info.service_inter_check_delay; + if(check_delay > check_window(temp_service)) { + log_debug_info(DEBUGL_EVENTS, 0, + " Fixing check time %lu secs too far away\n", + check_delay - check_window(temp_service)); + fixed_services++; + check_delay = ranged_urand(0, check_window(temp_service)); + log_debug_info(DEBUGL_EVENTS, 0, " New check offset: %d\n", + check_delay); + } + temp_service->next_check = (time_t)(current_time + check_delay); - log_debug_info(DEBUGL_EVENTS, 2, "Preferred Check Time: %lu --> %s", (unsigned long)temp_service->next_check, ctime(&temp_service->next_check)); + log_debug_info(DEBUGL_EVENTS, 2, "Preferred Check Time: %lu --> %s\n", (unsigned long)temp_service->next_check, ctime(&temp_service->next_check)); /* make sure the service can actually be scheduled when we want */ is_valid_time = check_time_against_period(temp_service->next_check, temp_service->check_period_ptr); if(is_valid_time == ERROR) { - log_debug_info(DEBUGL_EVENTS, 2, "Preferred Time is Invalid In Timeperiod '%s': %lu --> %s", temp_service->check_period_ptr->name, (unsigned long)temp_service->next_check, ctime(&temp_service->next_check)); + log_debug_info(DEBUGL_EVENTS, 2, "Preferred Time is Invalid In Timeperiod '%s': %lu --> %s\n", temp_service->check_period_ptr->name, (unsigned long)temp_service->next_check, ctime(&temp_service->next_check)); get_next_valid_time(temp_service->next_check, &next_valid_time, temp_service->check_period_ptr); - temp_service->next_check = next_valid_time; + temp_service->next_check = + (time_t)(next_valid_time + check_delay); } - log_debug_info(DEBUGL_EVENTS, 2, "Actual Check Time: %lu --> %s", (unsigned long)temp_service->next_check, ctime(&temp_service->next_check)); + log_debug_info(DEBUGL_EVENTS, 2, "Actual Check Time: %lu --> %s\n", (unsigned long)temp_service->next_check, ctime(&temp_service->next_check)); if(scheduling_info.first_service_check == (time_t)0 || (temp_service->next_check < scheduling_info.first_service_check)) scheduling_info.first_service_check = temp_service->next_check; @@ -415,10 +395,6 @@ void init_timing_loop(void) { /* update status of all services (scheduled or not) */ update_service_status(temp_service, FALSE); - /* skip services whose checks are currently executing */ - if(temp_service->is_executing) - continue; - /* skip most services that shouldn't be scheduled */ if(temp_service->should_be_scheduled == FALSE) { @@ -428,10 +404,7 @@ void init_timing_loop(void) { } /* create a new service check event */ - log_debug_info(DEBUGL_EVENTS, 2, - "Scheduling check for service '%s' on host '%s'.\n", - temp_service->description, temp_service->host_name); - schedule_new_event(EVENT_SERVICE_CHECK, FALSE, temp_service->next_check, FALSE, 0, NULL, TRUE, (void *)temp_service, NULL, temp_service->check_options); + temp_service->next_check_event = schedule_new_event(EVENT_SERVICE_CHECK, FALSE, temp_service->next_check, FALSE, 0, NULL, TRUE, (void *)temp_service, NULL, temp_service->check_options); } @@ -440,7 +413,7 @@ void init_timing_loop(void) { /******** DETERMINE HOST SCHEDULING PARAMS ********/ - log_debug_info(DEBUGL_EVENTS, 2, "Determining host scheduling parameters..."); + log_debug_info(DEBUGL_EVENTS, 2, "Determining host scheduling parameters...\n"); scheduling_info.first_host_check = (time_t)0L; scheduling_info.last_host_check = (time_t)0L; @@ -506,7 +479,7 @@ void init_timing_loop(void) { /******** SCHEDULE HOST CHECKS ********/ - log_debug_info(DEBUGL_EVENTS, 2, "Scheduling host checks..."); + log_debug_info(DEBUGL_EVENTS, 2, "Scheduling host checks...\n"); /* determine check times for host checks */ mult_factor = 0; @@ -520,21 +493,25 @@ void init_timing_loop(void) { continue; } - /* skip hosts whose checks are currently executing */ - if(temp_host->is_executing) { - log_debug_info(DEBUGL_EVENTS, 2, - "Host check %s is already executing.\n", temp_host->name); - continue; - } - /* skip hosts that are already scheduled for the future (from retention data), but reschedule ones that were supposed to be checked before we started */ if(temp_host->next_check > current_time) { log_debug_info(DEBUGL_EVENTS, 2, "Host is already scheduled to be checked in the future: %s\n", ctime(&temp_host->next_check)); continue; } - /* calculate preferred host check time */ - temp_host->next_check = (time_t)(current_time + (mult_factor * scheduling_info.host_inter_check_delay)); + /* + * calculate preferred host check time. + * If it's too far into the future, we grab a random time + * within this host's max check window instead + */ + check_delay = mult_factor * scheduling_info.host_inter_check_delay; + if(check_delay > check_window(temp_host)) { + log_debug_info(DEBUGL_EVENTS, 1, "Fixing check time (off by %lu)\n", + check_delay - check_window(temp_host)); + fixed_hosts++; + check_delay = ranged_urand(0, check_window(temp_host)); + } + temp_host->next_check = (time_t)(current_time + check_delay); log_debug_info(DEBUGL_EVENTS, 2, "Preferred Check Time: %lu --> %s", (unsigned long)temp_host->next_check, ctime(&temp_host->next_check)); @@ -542,10 +519,10 @@ void init_timing_loop(void) { is_valid_time = check_time_against_period(temp_host->next_check, temp_host->check_period_ptr); if(is_valid_time == ERROR) { get_next_valid_time(temp_host->next_check, &next_valid_time, temp_host->check_period_ptr); - temp_host->next_check = next_valid_time; + temp_host->next_check = (time_t)(next_valid_time | check_delay); } - log_debug_info(DEBUGL_EVENTS, 2, "Actual Check Time: %lu --> %s", (unsigned long)temp_host->next_check, ctime(&temp_host->next_check)); + log_debug_info(DEBUGL_EVENTS, 2, "Actual Check Time: %lu --> %s\n", (unsigned long)temp_host->next_check, ctime(&temp_host->next_check)); if(scheduling_info.first_host_check == (time_t)0 || (temp_host->next_check < scheduling_info.first_host_check)) scheduling_info.first_host_check = temp_host->next_check; @@ -555,6 +532,8 @@ void init_timing_loop(void) { mult_factor++; } + log_debug_info(DEBUGL_EVENTS, 0, "Fixed scheduling for %u hosts and %u services\n", fixed_hosts, fixed_services); + if(test_scheduling == TRUE) gettimeofday(&tv[7], NULL); @@ -565,10 +544,6 @@ void init_timing_loop(void) { /* update status of all hosts (scheduled or not) */ update_host_status(temp_host, FALSE); - /* skip hosts whose checks are currently executing */ - if(temp_host->is_executing) - continue; - /* skip most hosts that shouldn't be scheduled */ if(temp_host->should_be_scheduled == FALSE) { @@ -578,9 +553,7 @@ void init_timing_loop(void) { } /* schedule a new host check event */ - log_debug_info(DEBUGL_EVENTS, 2, "Scheduling check for host '%s'.\n", - temp_host->name); - schedule_new_event(EVENT_HOST_CHECK, FALSE, temp_host->next_check, FALSE, 0, NULL, TRUE, (void *)temp_host, NULL, temp_host->check_options); + temp_host->next_check_event = schedule_new_event(EVENT_HOST_CHECK, FALSE, temp_host->next_check, FALSE, 0, NULL, TRUE, (void *)temp_host, NULL, temp_host->check_options); } if(test_scheduling == TRUE) @@ -609,17 +582,7 @@ void init_timing_loop(void) { schedule_new_event(EVENT_HFRESHNESS_CHECK, TRUE, current_time + host_freshness_check_interval, TRUE, host_freshness_check_interval, NULL, TRUE, NULL, NULL, 0); /* add a status save event */ - if(aggregate_status_updates == TRUE) - schedule_new_event(EVENT_STATUS_SAVE, TRUE, current_time + status_update_interval, TRUE, status_update_interval, NULL, TRUE, NULL, NULL, 0); - - /* add an external command check event if needed */ - if(check_external_commands == TRUE) { - if(command_check_interval == -1) - interval_to_use = (unsigned long)5; - else - interval_to_use = (unsigned long)command_check_interval; - schedule_new_event(EVENT_COMMAND_CHECK, TRUE, current_time + interval_to_use, TRUE, interval_to_use, NULL, TRUE, NULL, NULL, 0); - } + schedule_new_event(EVENT_STATUS_SAVE, TRUE, current_time + status_update_interval, TRUE, status_update_interval, NULL, TRUE, NULL, NULL, 0); /* add a log rotation event if necessary */ if(log_rotation_method != LOG_ROTATION_NONE) @@ -666,10 +629,7 @@ void init_timing_loop(void) { /* displays service check scheduling information */ void display_scheduling_info(void) { - float minimum_concurrent_checks1 = 0.0; - float minimum_concurrent_checks2 = 0.0; float minimum_concurrent_checks = 0.0; - float max_reaper_interval = 0.0; int suggestions = 0; printf("Projected scheduling information for host and service checks\n"); @@ -726,10 +686,19 @@ void display_scheduling_info(void) { printf("Last scheduled check: %s", ctime(&scheduling_info.last_service_check)); printf("\n\n"); + /***** MINIMUM CONCURRENT CHECKS RECOMMENDATION *****/ + minimum_concurrent_checks = ceil((((scheduling_info.total_scheduled_services / scheduling_info.average_service_check_interval) + + (scheduling_info.total_scheduled_hosts / scheduling_info.average_host_check_interval)) + * 1.4 * scheduling_info.average_service_execution_time)); + printf("CHECK PROCESSING INFORMATION\n"); printf("----------------------------\n"); - printf("Check result reaper interval: %d sec\n", check_reaper_interval); - printf("Max concurrent service checks: "); + printf("Average check execution time: %.2fs%s", + scheduling_info.average_service_execution_time, + scheduling_info.average_service_execution_time == 2.0 ? " (pessimistic guesstimate)\n" : "\n"); + printf("Estimated concurrent checks: %.0f (%.2f per cpu core)\n", + minimum_concurrent_checks, (float)minimum_concurrent_checks / (float)online_cpus()); + printf("Max concurrent service checks: "); if(max_parallel_service_checks == 0) printf("Unlimited\n"); else @@ -740,49 +709,38 @@ void display_scheduling_info(void) { printf("-----------------------\n"); - /***** MAX REAPER INTERVAL RECOMMENDATION *****/ - - /* assume a 100% (2x) check burst for check reaper */ - /* assume we want a max of 2k files in the result queue at any given time */ - max_reaper_interval = floor(2000 * scheduling_info.service_inter_check_delay); - if(max_reaper_interval < 2.0) - max_reaper_interval = 2.0; - if(max_reaper_interval > 30.0) - max_reaper_interval = 30.0; - if((int)max_reaper_interval < check_reaper_interval) { - printf("* Value for 'check_result_reaper_frequency' should be <= %d seconds\n", (int)max_reaper_interval); - suggestions++; - } - if(check_reaper_interval < 2) { - printf("* Value for 'check_result_reaper_frequency' should be >= 2 seconds\n"); - suggestions++; - } - - /***** MINIMUM CONCURRENT CHECKS RECOMMENDATION *****/ - - /* first method (old) - assume a 100% (2x) service check burst for max concurrent checks */ - if(scheduling_info.service_inter_check_delay == 0.0) - minimum_concurrent_checks1 = ceil(check_reaper_interval * 2.0); - else - minimum_concurrent_checks1 = ceil((check_reaper_interval * 2.0) / scheduling_info.service_inter_check_delay); - - /* second method (new) - assume a 25% (1.25x) service check burst for max concurrent checks */ - minimum_concurrent_checks2 = ceil((((double)scheduling_info.total_scheduled_services) / scheduling_info.average_service_check_interval) * 1.25 * check_reaper_interval * scheduling_info.average_service_execution_time); - - /* use max of computed values */ - if(minimum_concurrent_checks1 > minimum_concurrent_checks2) - minimum_concurrent_checks = minimum_concurrent_checks1; - else - minimum_concurrent_checks = minimum_concurrent_checks2; - /* compare with configured value */ if(((int)minimum_concurrent_checks > max_parallel_service_checks) && max_parallel_service_checks != 0) { printf("* Value for 'max_concurrent_checks' option should be >= %d\n", (int)minimum_concurrent_checks); suggestions++; } + if(loadctl.nofile_limit * 0.4 < minimum_concurrent_checks) { + printf("* Increase the \"open files\" ulimit for user '%s'\n", nagios_user); + printf(" - You can do this by adding\n %s hard nofiles %d\n to /etc/security/limits.conf\n", + nagios_user, rup2pof2(minimum_concurrent_checks * 2)); + suggestions++; + } + if(loadctl.nproc_limit * 0.75 < minimum_concurrent_checks) { + printf("* Increase the \"max user processes\" ulimit for user '%s'\n", nagios_user); + printf(" - You can do this by adding\n %s hard nproc %d\n to /etc/security/limits.conf\n", + nagios_user, rup2pof2(minimum_concurrent_checks)); + suggestions++; + } - if(suggestions == 0) + if(minimum_concurrent_checks > online_cpus() * 75) { + printf("* Aim for a max of 50 concurrent checks / cpu core (current: %.2f)\n", + (float)minimum_concurrent_checks / (float)online_cpus()); + suggestions++; + } + + if(suggestions) { + printf("\nNOTE: These are just guidelines and *not* hard numbers.\n\n"); + printf("Ultimately, only testing will tell if your settings and hardware are\n"); + printf("suitable for the types and number of checks you're planning to run.\n"); + } + else { printf("I have no suggestions - things look okay.\n"); + } printf("\n"); @@ -790,44 +748,48 @@ void display_scheduling_info(void) { } -/* schedule a new timed event */ -int schedule_new_event(int event_type, int high_priority, time_t run_time, int recurring, unsigned long event_interval, void *timing_func, int compensate_for_time_change, void *event_data, void *event_args, int event_options) { - timed_event **event_list = NULL; - timed_event **event_list_tail = NULL; - timed_event *new_event = NULL; +/* + * Create the event queue + * We oversize it somewhat to avoid unnecessary growing + */ +int init_event_queue(void) +{ + unsigned int size; - char run_time_string[MAX_DATETIME_LENGTH] = ""; + size = num_objects.hosts + num_objects.services; + if(size < 4096) + size = 4096; + + nagios_squeue = squeue_create(size); + return 0; +} + +/* schedule a new timed event */ +timed_event *schedule_new_event(int event_type, int high_priority, time_t run_time, int recurring, unsigned long event_interval, void *timing_func, int compensate_for_time_change, void *event_data, void *event_args, int event_options) { + timed_event *new_event; + char run_time_string[MAX_DATETIME_LENGTH] = ""; log_debug_info(DEBUGL_FUNCTIONS, 0, "schedule_new_event()\n"); get_datetime_string(&run_time, run_time_string, MAX_DATETIME_LENGTH, - SHORT_DATE_TIME); + SHORT_DATE_TIME); log_debug_info(DEBUGL_EVENTS, 0, "New Event Details:\n"); - log_debug_info(DEBUGL_EVENTS, 0, " Type: %s\n", - EVENT_TYPE_STR(event_type)); + log_debug_info(DEBUGL_EVENTS, 0, " Type: EVENT_%s\n", + EVENT_TYPE_STR(event_type)); log_debug_info(DEBUGL_EVENTS, 0, " High Priority: %s\n", - (high_priority ? "Yes" : "No")); + ( high_priority ? "Yes" : "No")); log_debug_info(DEBUGL_EVENTS, 0, " Run Time: %s\n", - run_time_string); + run_time_string); log_debug_info(DEBUGL_EVENTS, 0, " Recurring: %s\n", - (recurring ? "Yes" : "No")); + ( recurring ? "Yes" : "No")); log_debug_info(DEBUGL_EVENTS, 0, " Event Interval: %lu\n", - event_interval); + event_interval); log_debug_info(DEBUGL_EVENTS, 0, " Compensate for Time Change: %s\n", - (compensate_for_time_change ? "Yes" : "No")); + ( compensate_for_time_change ? "Yes" : "No")); log_debug_info(DEBUGL_EVENTS, 0, " Event Options: %d\n", - event_options); + event_options); - if(high_priority == TRUE) { - event_list = &event_list_high; - event_list_tail = &event_list_high_tail; - } - else { - event_list = &event_list_low; - event_list_tail = &event_list_low_tail; - } - - new_event = (timed_event *)malloc(sizeof(timed_event)); + new_event = (timed_event *)calloc(1, sizeof(timed_event)); if(new_event != NULL) { new_event->event_type = event_type; new_event->event_data = event_data; @@ -838,19 +800,22 @@ int schedule_new_event(int event_type, int high_priority, time_t run_time, int r new_event->event_interval = event_interval; new_event->timing_func = timing_func; new_event->compensate_for_time_change = compensate_for_time_change; + new_event->priority = high_priority; } else - return ERROR; + return NULL; + + log_debug_info(DEBUGL_EVENTS, 0, " Event ID: %p\n", new_event); /* add the event to the event list */ - add_event(new_event, event_list, event_list_tail); + add_event(nagios_squeue, new_event); - return OK; + return new_event; } /* reschedule an event in order of execution time */ -void reschedule_event(timed_event *event, timed_event **event_list, timed_event **event_list_tail) { +void reschedule_event(squeue_t *sq, timed_event *event) { time_t current_time = 0L; time_t (*timingfunc)(void); @@ -875,65 +840,43 @@ void reschedule_event(timed_event *event, timed_event **event_list, timed_event } /* add the event to the event list */ - add_event(event, event_list, event_list_tail); + add_event(sq, event); return; } /* add an event to list ordered by execution time */ -void add_event(timed_event *event, timed_event **event_list, timed_event **event_list_tail) { - timed_event *temp_event = NULL; - timed_event *first_event = NULL; +void add_event(squeue_t *sq, timed_event *event) { log_debug_info(DEBUGL_FUNCTIONS, 0, "add_event()\n"); - event->next = NULL; - event->prev = NULL; + if(event->sq_event) { + logit(NSLOG_RUNTIME_ERROR, TRUE, + "Error: Adding %s event that seems to already be scheduled\n", + EVENT_TYPE_STR(event->event_type)); + remove_event(sq, event); + } - first_event = *event_list; - - /* add the event to the head of the list if there are no other events */ - if(*event_list == NULL) { - *event_list = event; - *event_list_tail = event; + if(event->priority) { + event->sq_event = squeue_add_usec(sq, event->run_time, event->priority - 1, event); } - - /* add event to head of the list if it should be executed first */ - else if(event->run_time < first_event->run_time) { - event->prev = NULL; - (*event_list)->prev = event; - event->next = *event_list; - *event_list = event; - } - - /* else place the event according to next execution time */ else { - - /* start from the end of the list, as new events are likely to be executed in the future, rather than now... */ - for(temp_event = *event_list_tail; temp_event != NULL; temp_event = temp_event->prev) { - if(event->run_time >= temp_event->run_time) { - event->next = temp_event->next; - event->prev = temp_event; - temp_event->next = event; - if(event->next == NULL) - *event_list_tail = event; - else - event->next->prev = event; - break; - } - else if(temp_event->prev == NULL) { - temp_event->prev = event; - event->next = temp_event; - *event_list = event; - break; - } - } + event->sq_event = squeue_add(sq, event->run_time, event); } + if(!event->sq_event) { + logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Failed to add event to squeue '%p' with prio %u: %s\n", + sq, event->priority, strerror(errno)); + } + + if(sq == nagios_squeue) + track_events(event->event_type, +1); #ifdef USE_EVENT_BROKER - /* send event data to broker */ - broker_timed_event(NEBTYPE_TIMEDEVENT_ADD, NEBFLAG_NONE, NEBATTR_NONE, event, NULL); + else { + /* send event data to broker */ + broker_timed_event(NEBTYPE_TIMEDEVENT_ADD, NEBFLAG_NONE, NEBATTR_NONE, event, NULL); + } #endif return; @@ -942,93 +885,149 @@ void add_event(timed_event *event, timed_event **event_list, timed_event **event /* remove an event from the queue */ -void remove_event(timed_event *event, timed_event **event_list, timed_event **event_list_tail) { - timed_event *prev_event, *next_event; - - log_debug_info(DEBUGL_FUNCTIONS, 0, "remove_event()\n"); - - if(!event) - return; - +void remove_event(squeue_t *sq, timed_event *event) { #ifdef USE_EVENT_BROKER /* send event data to broker */ broker_timed_event(NEBTYPE_TIMEDEVENT_REMOVE, NEBFLAG_NONE, NEBATTR_NONE, event, NULL); #endif - - if(*event_list == NULL) + if(!event || !event->sq_event) return; - prev_event = event->prev; - next_event = event->next; - if(prev_event) { - prev_event->next = next_event; - } - if(next_event) { - next_event->prev = prev_event; - } + if (sq) + squeue_remove(sq, event->sq_event); + else + logit(NSLOG_RUNTIME_ERROR, TRUE, + "Error: remove_event() called for %s event with NULL sq parameter\n", + EVENT_TYPE_STR(event->event_type)); - if(!prev_event) { - /* no previous event, so "next" is now first in list */ - *event_list = next_event; - } - if(!next_event) { - /* no following event, so "prev" is now last in list */ - *event_list_tail = prev_event; - } + if(sq == nagios_squeue) + track_events(event->event_type, -1); + + event->sq_event = NULL; /* mark this event as unscheduled */ /* - * If there was only one event in the list, we're already - * done, just as if there were events before and efter the - * deleted event + * if we catch an event from the queue which gets removed when + * we go polling for input (as might happen with f.e. downtime + * events that we get "cancel" commands for just as they are + * about to start or expire), we must make sure we mark the + * current event as no longer scheduled, or we'll run into + * segfaults and memory corruptions for sure. */ + if (event == current_event) { + current_event = NULL; + } } +static int should_run_event(timed_event *temp_event) +{ + int run_event = TRUE; /* default action is to execute the event */ + int nudge_seconds = 0; + + /* we only care about jobs that cause processes to run */ + if (temp_event->event_type != EVENT_HOST_CHECK && + temp_event->event_type != EVENT_SERVICE_CHECK) + { + return TRUE; + } + + /* if we can't spawn any more jobs, don't bother */ + if (!wproc_can_spawn(&loadctl)) { + wproc_reap(1, 1); /* Try to reap one job for one msec. */ + return FALSE; + } + + /* run a few checks before executing a service check... */ + if(temp_event->event_type == EVENT_SERVICE_CHECK) { + service *temp_service = (service *)temp_event->event_data; + + /* forced checks override normal check logic */ + if((temp_service->check_options & CHECK_OPTION_FORCE_EXECUTION)) + return TRUE; + + /* don't run a service check if we're already maxed out on the number of parallel service checks... */ + if(max_parallel_service_checks != 0 && (currently_running_service_checks >= max_parallel_service_checks)) { + nudge_seconds = ranged_urand(NUDGE_MIN, NUDGE_MAX); + logit(NSLOG_RUNTIME_WARNING, TRUE, "\tMax concurrent service checks (%d) has been reached. Nudging %s:%s by %d seconds...\n", max_parallel_service_checks, temp_service->host_name, temp_service->description, nudge_seconds); + run_event = FALSE; + } + + /* don't run a service check if active checks are disabled */ + if(execute_service_checks == FALSE) { + log_debug_info(DEBUGL_EVENTS | DEBUGL_CHECKS, 1, "We're not executing service checks right now, so we'll skip check event for service '%s;%s'.\n", temp_service->host_name, temp_service->description); + run_event = FALSE; + } + + /* reschedule the check if we can't run it now */ + if(run_event == FALSE) { + remove_event(nagios_squeue, temp_event); + + if(nudge_seconds) { + /* We nudge the next check time when it is due to too many concurrent service checks */ + temp_service->next_check = (time_t)(temp_service->next_check + nudge_seconds); + } + else { + temp_service->next_check += check_window(temp_service); + } + + temp_event->run_time = temp_service->next_check; + reschedule_event(nagios_squeue, temp_event); + update_service_status(temp_service, FALSE); + + run_event = FALSE; + } + } + /* run a few checks before executing a host check... */ + else if(temp_event->event_type == EVENT_HOST_CHECK) { + host *temp_host = (host *)temp_event->event_data; + + /* forced checks override normal check logic */ + if((temp_host->check_options & CHECK_OPTION_FORCE_EXECUTION)) + return TRUE; + + /* don't run a host check if active checks are disabled */ + if(execute_host_checks == FALSE) { + log_debug_info(DEBUGL_EVENTS | DEBUGL_CHECKS, 1, "We're not executing host checks right now, so we'll skip host check event for host '%s'.\n", temp_host->name); + run_event = FALSE; + } + + /* reschedule the host check if we can't run it right now */ + if(run_event == FALSE) { + remove_event(nagios_squeue, temp_event); + temp_host->next_check += check_window(temp_host); + temp_event->run_time = temp_host->next_check; + reschedule_event(nagios_squeue, temp_event); + update_host_status(temp_host, FALSE); + run_event = FALSE; + } + } + + return run_event; +} /* this is the main event handler loop */ int event_execution_loop(void) { - timed_event *temp_event = NULL; - timed_event sleep_event; + timed_event *temp_event, *last_event = NULL; time_t last_time = 0L; time_t current_time = 0L; time_t last_status_update = 0L; - int run_event = TRUE; - int nudge_seconds; - host *temp_host = NULL; - service *temp_service = NULL; - struct timespec delay; - pid_t wait_result; - + int poll_time_ms; log_debug_info(DEBUGL_FUNCTIONS, 0, "event_execution_loop() start\n"); time(&last_time); - /* initialize fake "sleep" event */ - sleep_event.event_type = EVENT_SLEEP; - sleep_event.run_time = last_time; - sleep_event.recurring = FALSE; - sleep_event.event_interval = 0L; - sleep_event.compensate_for_time_change = FALSE; - sleep_event.timing_func = NULL; - sleep_event.event_data = NULL; - sleep_event.event_args = NULL; - sleep_event.event_options = 0; - sleep_event.next = NULL; - sleep_event.prev = NULL; - while(1) { + struct timeval now; + const struct timeval *event_runtime; + int inputs; + + /* super-priority (hardcoded) events come first */ /* see if we should exit or restart (a signal was encountered) */ if(sigshutdown == TRUE || sigrestart == TRUE) break; - /* if we don't have any events to handle, exit */ - if(event_list_high == NULL && event_list_low == NULL) { - log_debug_info(DEBUGL_EVENTS, 0, "There aren't any events that need to be handled! Exiting...\n"); - break; - } - /* get the current time */ time(¤t_time); @@ -1040,223 +1039,92 @@ int event_execution_loop(void) { else if((current_time - last_time) >= time_change_threshold) compensate_for_system_time_change((unsigned long)last_time, (unsigned long)current_time); + /* get next scheduled event */ + current_event = temp_event = (timed_event *)squeue_peek(nagios_squeue); + + /* if we don't have any events to handle, exit */ + if(!temp_event) { + log_debug_info(DEBUGL_EVENTS, 0, "There aren't any events that need to be handled! Exiting...\n"); + break; + } + /* keep track of the last time */ last_time = current_time; - log_debug_info(DEBUGL_EVENTS, 1, "** Event Check Loop\n"); - if(event_list_high != NULL) - log_debug_info(DEBUGL_EVENTS, 1, "Next High Priority Event Time: %s", ctime(&event_list_high->run_time)); - else - log_debug_info(DEBUGL_EVENTS, 1, "No high priority events are scheduled...\n"); - if(event_list_low != NULL) - log_debug_info(DEBUGL_EVENTS, 1, "Next Low Priority Event Time: %s", ctime(&event_list_low->run_time)); - else - log_debug_info(DEBUGL_EVENTS, 1, "No low priority events are scheduled...\n"); - log_debug_info(DEBUGL_EVENTS, 1, "Current/Max Service Checks: %d/%d\n", currently_running_service_checks, max_parallel_service_checks); - - /* get rid of terminated child processes (zombies) */ - if(child_processes_fork_twice == FALSE) { - while((wait_result = waitpid(-1, NULL, WNOHANG)) > 0); - } - - /* handle high priority events */ - if(event_list_high != NULL && (current_time >= event_list_high->run_time)) { - - /* remove the first event from the timing loop */ - temp_event = event_list_high; - event_list_high = event_list_high->next; - event_list_high->prev = NULL; - - /* handle the event */ - handle_timed_event(temp_event); - - /* reschedule the event if necessary */ - if(temp_event->recurring == TRUE) - reschedule_event(temp_event, &event_list_high, &event_list_high_tail); - - /* else free memory associated with the event */ - else - my_free(temp_event); - } - - /* handle low priority events */ - else if(event_list_low != NULL && (current_time >= event_list_low->run_time)) { - - /* default action is to execute the event */ - run_event = TRUE; - nudge_seconds = 0; - - /* run a few checks before executing a service check... */ - if(event_list_low->event_type == EVENT_SERVICE_CHECK) { - - temp_service = (service *)event_list_low->event_data; - - /* don't run a service check if we're already maxed out on the number of parallel service checks... */ - if(max_parallel_service_checks != 0 && (currently_running_service_checks >= max_parallel_service_checks)) { - - /* Move it at least 5 seconds (to overcome the current peak), with a random 10 seconds (to spread the load) */ - nudge_seconds = 5 + (rand() % 10); - log_debug_info(DEBUGL_EVENTS | DEBUGL_CHECKS, 0, "**WARNING** Max concurrent service checks (%d) has been reached! Nudging %s:%s by %d seconds...\n", max_parallel_service_checks, temp_service->host_name, temp_service->description, nudge_seconds); - - logit(NSLOG_RUNTIME_WARNING, TRUE, "\tMax concurrent service checks (%d) has been reached. Nudging %s:%s by %d seconds...\n", max_parallel_service_checks, temp_service->host_name, temp_service->description, nudge_seconds); - run_event = FALSE; - } - - /* don't run a service check if active checks are disabled */ - if(execute_service_checks == FALSE) { - - log_debug_info(DEBUGL_EVENTS | DEBUGL_CHECKS, 1, "We're not executing service checks right now, so we'll skip this event.\n"); - - run_event = FALSE; - } - - /* forced checks override normal check logic */ - if((temp_service->check_options & CHECK_OPTION_FORCE_EXECUTION)) - run_event = TRUE; - - /* reschedule the check if we can't run it now */ - if(run_event == FALSE) { - - /* remove the service check from the event queue and reschedule it for a later time */ - /* 12/20/05 since event was not executed, it needs to be remove()'ed to maintain sync with event broker modules */ - temp_event = event_list_low; - remove_event(temp_event, &event_list_low, &event_list_low_tail); - /* - event_list_low=event_list_low->next; - */ - if(nudge_seconds) { - /* We nudge the next check time when it is due to too many concurrent service checks */ - temp_service->next_check = (time_t)(temp_service->next_check + nudge_seconds); - } - else { - /* Otherwise reschedule (TODO: This should be smarter as it doesn't consider its timeperiod) */ - if(temp_service->state_type == SOFT_STATE && temp_service->current_state != STATE_OK) - temp_service->next_check = (time_t)(temp_service->next_check + (temp_service->retry_interval * interval_length)); - else - temp_service->next_check = (time_t)(temp_service->next_check + (temp_service->check_interval * interval_length)); - } - - temp_event->run_time = temp_service->next_check; - reschedule_event(temp_event, &event_list_low, &event_list_low_tail); - update_service_status(temp_service, FALSE); - - run_event = FALSE; - } - } - - /* run a few checks before executing a host check... */ - else if(event_list_low->event_type == EVENT_HOST_CHECK) { - - /* default action is to execute the event */ - run_event = TRUE; - - temp_host = (host *)event_list_low->event_data; - - /* don't run a host check if active checks are disabled */ - if(execute_host_checks == FALSE) { - - log_debug_info(DEBUGL_EVENTS | DEBUGL_CHECKS, 1, "We're not executing host checks right now, so we'll skip this event.\n"); - - run_event = FALSE; - } - - /* forced checks override normal check logic */ - if((temp_host->check_options & CHECK_OPTION_FORCE_EXECUTION)) - run_event = TRUE; - - /* reschedule the host check if we can't run it right now */ - if(run_event == FALSE) { - - /* remove the host check from the event queue and reschedule it for a later time */ - /* 12/20/05 since event was not executed, it needs to be remove()'ed to maintain sync with event broker modules */ - temp_event = event_list_low; - remove_event(temp_event, &event_list_low, &event_list_low_tail); - /* - event_list_low=event_list_low->next; - */ - if(temp_host->state_type == SOFT_STATE && temp_host->current_state != STATE_OK) - temp_host->next_check = (time_t)(temp_host->next_check + (temp_host->retry_interval * interval_length)); - else - temp_host->next_check = (time_t)(temp_host->next_check + (temp_host->check_interval * interval_length)); - - temp_event->run_time = temp_host->next_check; - reschedule_event(temp_event, &event_list_low, &event_list_low_tail); - update_host_status(temp_host, FALSE); - - run_event = FALSE; - } - } - - /* run the event */ - if(run_event == TRUE) { - - /* remove the first event from the timing loop */ - temp_event = event_list_low; - event_list_low = event_list_low->next; - /* we may have just removed the only item from the list */ - if(event_list_low != NULL) - event_list_low->prev = NULL; - - log_debug_info(DEBUGL_EVENTS, 1, "Running event...\n"); - -# /* handle the event */ - handle_timed_event(temp_event); - - /* reschedule the event if necessary */ - if(temp_event->recurring == TRUE) - reschedule_event(temp_event, &event_list_low, &event_list_low_tail); - - /* else free memory associated with the event */ - else - my_free(temp_event); - } - - } - - /* we don't have anything to do at this moment in time... */ - else if((event_list_high == NULL || (current_time < event_list_high->run_time)) && (event_list_low == NULL || (current_time < event_list_low->run_time))) { - - log_debug_info(DEBUGL_EVENTS, 2, "No events to execute at the moment. Idling for a bit...\n"); - - /* check for external commands if we're supposed to check as often as possible */ - if(command_check_interval == -1) - check_for_external_commands(); - - /* set time to sleep so we don't hog the CPU... */ -#ifdef USE_NANOSLEEP - delay.tv_sec = (time_t)sleep_time; - delay.tv_nsec = (long)((sleep_time - (double)delay.tv_sec) * 1000000000); -#else - delay.tv_sec = (time_t)sleep_time; - if(delay.tv_sec == 0L) - delay.tv_sec = 1; - delay.tv_nsec = 0L; -#endif - -#ifdef USE_EVENT_BROKER - /* populate fake "sleep" event */ - sleep_event.run_time = current_time; - sleep_event.event_data = (void *)&delay; - - /* send event data to broker */ - broker_timed_event(NEBTYPE_TIMEDEVENT_SLEEP, NEBFLAG_NONE, NEBATTR_NONE, &sleep_event, NULL); -#endif - - /* wait a while so we don't hog the CPU... */ -#ifdef USE_NANOSLEEP - nanosleep(&delay, NULL); -#else - sleep((unsigned int)delay.tv_sec); -#endif - } - - /* update status information occassionally - NagVis watches the NDOUtils DB to see if Nagios is alive */ + /* update status information occasionally - NagVis watches the NDOUtils DB to see if Nagios is alive */ if((unsigned long)(current_time - last_status_update) > 5) { last_status_update = current_time; update_program_status(FALSE); } + + event_runtime = squeue_event_runtime(temp_event->sq_event); + if (temp_event != last_event) { + log_debug_info(DEBUGL_EVENTS, 1, "** Event Check Loop\n"); + log_debug_info(DEBUGL_EVENTS, 1, "Next Event Time: %s", ctime(&temp_event->run_time)); + log_debug_info(DEBUGL_EVENTS, 1, "Current/Max Service Checks: %d/%d (%.3lf%% saturation)\n", + currently_running_service_checks, max_parallel_service_checks, + ((float)currently_running_service_checks / (float)max_parallel_service_checks) * 100); } + last_event = temp_event; + + gettimeofday(&now, NULL); + poll_time_ms = tv_delta_msec(&now, event_runtime); + if (poll_time_ms < 0) + poll_time_ms = 0; + else if(poll_time_ms >= 1500) + poll_time_ms = 1500; + + log_debug_info(DEBUGL_SCHEDULING | DEBUGL_IPC, 1, "## Polling %dms; sockets=%d; events=%u; iobs=%p\n", + poll_time_ms, iobroker_get_num_fds(nagios_iobs), + squeue_size(nagios_squeue), nagios_iobs); + inputs = iobroker_poll(nagios_iobs, poll_time_ms); + if (inputs < 0 && errno != EINTR) { + logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Polling for input on %p failed: %s", nagios_iobs, iobroker_strerror(inputs)); + break; + } + + log_debug_info(DEBUGL_IPC, 2, "## %d descriptors had input\n", inputs); + + /* + * if the event we peaked was removed from the queue from + * one of the I/O operations, we must take care not to + * try to run at, as we're (almost) sure to access free'd + * or invalid memory if we do. + */ + if (!current_event) { + log_debug_info(DEBUGL_EVENTS, 0, "Event was cancelled by iobroker input\n"); + continue; + } + + /* 5 milliseconds allowance for firing off events early */ + gettimeofday(&now, NULL); + if (tv_delta_msec(&now, event_runtime) > 5) + continue; + + /* move on if we shouldn't run this event */ + if(should_run_event(temp_event) == FALSE) + continue; + + /* handle the event */ + handle_timed_event(temp_event); + + /* + * we must remove the entry we've peeked, or + * we'll keep getting the same one over and over. + * This also maintains sync with broker modules. + */ + remove_event(nagios_squeue, temp_event); + + /* reschedule the event if necessary */ + if(temp_event->recurring == TRUE) + reschedule_event(nagios_squeue, temp_event); + + /* else free memory associated with the event */ + else + my_free(temp_event); + } + log_debug_info(DEBUGL_FUNCTIONS, 0, "event_execution_loop() end\n"); return OK; @@ -1270,7 +1138,8 @@ int handle_timed_event(timed_event *event) { service *temp_service = NULL; void (*userfunc)(void *); struct timeval tv; - double latency = 0.0; + const struct timeval *event_runtime; + double latency; log_debug_info(DEBUGL_FUNCTIONS, 0, "handle_timed_event() start\n"); @@ -1280,7 +1149,14 @@ int handle_timed_event(timed_event *event) { broker_timed_event(NEBTYPE_TIMEDEVENT_EXECUTE, NEBFLAG_NONE, NEBATTR_NONE, event, NULL); #endif - log_debug_info(DEBUGL_EVENTS, 0, "** Timed Event ** Type: %s, Run Time: %s", EVENT_TYPE_STR(event->event_type), ctime(&event->run_time)); + log_debug_info(DEBUGL_EVENTS, 0, "** Timed Event ** Type: EVENT_%s, Run Time: %s", EVENT_TYPE_STR(event->event_type), ctime(&event->run_time)); + + /* get event latency */ + gettimeofday(&tv, NULL); + event_runtime = squeue_event_runtime(event->sq_event); + latency = (double)(tv_delta_f(event_runtime, &tv)); + if (latency < 0.0) /* events may run up to 0.005 seconds early */ + latency = 0.0; /* how should we handle the event? */ switch(event->event_type) { @@ -1289,14 +1165,9 @@ int handle_timed_event(timed_event *event) { temp_service = (service *)event->event_data; - /* get check latency */ - gettimeofday(&tv, NULL); - latency = (double)((double)(tv.tv_sec - event->run_time) + (double)(tv.tv_usec / 1000) / 1000.0); - log_debug_info(DEBUGL_EVENTS, 0, "** Service Check Event ==> Host: '%s', Service: '%s', Options: %d, Latency: %f sec\n", temp_service->host_name, temp_service->description, event->event_options, latency); /* run the service check */ - temp_service = (service *)event->event_data; run_scheduled_service_check(temp_service, event->event_options, latency); break; @@ -1304,28 +1175,15 @@ int handle_timed_event(timed_event *event) { temp_host = (host *)event->event_data; - /* get check latency */ - gettimeofday(&tv, NULL); - latency = (double)((double)(tv.tv_sec - event->run_time) + (double)(tv.tv_usec / 1000) / 1000.0); - log_debug_info(DEBUGL_EVENTS, 0, "** Host Check Event ==> Host: '%s', Options: %d, Latency: %f sec\n", temp_host->name, event->event_options, latency); /* run the host check */ - temp_host = (host *)event->event_data; - perform_scheduled_host_check(temp_host, event->event_options, latency); - break; - - case EVENT_COMMAND_CHECK: - - log_debug_info(DEBUGL_EVENTS, 0, "** External Command Check Event\n"); - - /* check for external commands */ - check_for_external_commands(); + run_scheduled_host_check(temp_host, event->event_options, latency); break; case EVENT_LOG_ROTATION: - log_debug_info(DEBUGL_EVENTS, 0, "** Log File Rotation Event\n"); + log_debug_info(DEBUGL_EVENTS, 0, "** Log File Rotation Event. Latency: %.3fs\n", latency); /* rotate the log file */ rotate_log_file(event->run_time); @@ -1333,7 +1191,7 @@ int handle_timed_event(timed_event *event) { case EVENT_PROGRAM_SHUTDOWN: - log_debug_info(DEBUGL_EVENTS, 0, "** Program Shutdown Event\n"); + log_debug_info(DEBUGL_EVENTS, 0, "** Program Shutdown Event. Latency: %.3fs\n", latency); /* set the shutdown flag */ sigshutdown = TRUE; @@ -1344,7 +1202,7 @@ int handle_timed_event(timed_event *event) { case EVENT_PROGRAM_RESTART: - log_debug_info(DEBUGL_EVENTS, 0, "** Program Restart Event\n"); + log_debug_info(DEBUGL_EVENTS, 0, "** Program Restart Event. Latency: %.3fs\n", latency); /* set the restart flag */ sigrestart = TRUE; @@ -1355,7 +1213,7 @@ int handle_timed_event(timed_event *event) { case EVENT_CHECK_REAPER: - log_debug_info(DEBUGL_EVENTS, 0, "** Check Result Reaper\n"); + log_debug_info(DEBUGL_EVENTS, 0, "** Check Result Reaper. Latency: %.3fs\n", latency); /* reap host and service check results */ reap_check_results(); @@ -1363,7 +1221,7 @@ int handle_timed_event(timed_event *event) { case EVENT_ORPHAN_CHECK: - log_debug_info(DEBUGL_EVENTS, 0, "** Orphaned Host and Service Check Event\n"); + log_debug_info(DEBUGL_EVENTS, 0, "** Orphaned Host and Service Check Event. Latency: %.3fs\n", latency); /* check for orphaned hosts and services */ if(check_orphaned_hosts == TRUE) @@ -1374,7 +1232,7 @@ int handle_timed_event(timed_event *event) { case EVENT_RETENTION_SAVE: - log_debug_info(DEBUGL_EVENTS, 0, "** Retention Data Save Event\n"); + log_debug_info(DEBUGL_EVENTS, 0, "** Retention Data Save Event. Latency: %.3fs\n", latency); /* save state retention data */ save_state_information(TRUE); @@ -1382,7 +1240,7 @@ int handle_timed_event(timed_event *event) { case EVENT_STATUS_SAVE: - log_debug_info(DEBUGL_EVENTS, 0, "** Status Data Save Event\n"); + log_debug_info(DEBUGL_EVENTS, 0, "** Status Data Save Event. Latency: %.3fs\n", latency); /* save all status data (program, host, and service) */ update_all_status_data(); @@ -1390,7 +1248,7 @@ int handle_timed_event(timed_event *event) { case EVENT_SCHEDULED_DOWNTIME: - log_debug_info(DEBUGL_EVENTS, 0, "** Scheduled Downtime Event\n"); + log_debug_info(DEBUGL_EVENTS, 0, "** Scheduled Downtime Event. Latency: %.3fs\n", latency); /* process scheduled downtime info */ if(event->event_data) { @@ -1402,7 +1260,7 @@ int handle_timed_event(timed_event *event) { case EVENT_SFRESHNESS_CHECK: - log_debug_info(DEBUGL_EVENTS, 0, "** Service Result Freshness Check Event\n"); + log_debug_info(DEBUGL_EVENTS, 0, "** Service Result Freshness Check Event. Latency: %.3fs\n", latency); /* check service result freshness */ check_service_result_freshness(); @@ -1410,7 +1268,7 @@ int handle_timed_event(timed_event *event) { case EVENT_HFRESHNESS_CHECK: - log_debug_info(DEBUGL_EVENTS, 0, "** Host Result Freshness Check Event\n"); + log_debug_info(DEBUGL_EVENTS, 0, "** Host Result Freshness Check Event. Latency: %.3fs\n", latency); /* check host result freshness */ check_host_result_freshness(); @@ -1418,7 +1276,7 @@ int handle_timed_event(timed_event *event) { case EVENT_EXPIRE_DOWNTIME: - log_debug_info(DEBUGL_EVENTS, 0, "** Expire Downtime Event\n"); + log_debug_info(DEBUGL_EVENTS, 0, "** Expire Downtime Event. Latency: %.3fs\n", latency); /* check for expired scheduled downtime entries */ check_for_expired_downtime(); @@ -1427,14 +1285,14 @@ int handle_timed_event(timed_event *event) { case EVENT_RESCHEDULE_CHECKS: /* adjust scheduling of host and service checks */ - log_debug_info(DEBUGL_EVENTS, 0, "** Reschedule Checks Event\n"); + log_debug_info(DEBUGL_EVENTS, 0, "** Reschedule Checks Event. Latency: %.3fs\n", latency); adjust_check_scheduling(); break; case EVENT_EXPIRE_COMMENT: - log_debug_info(DEBUGL_EVENTS, 0, "** Expire Comment Event\n"); + log_debug_info(DEBUGL_EVENTS, 0, "** Expire Comment Event. Latency: %.3fs\n", latency); /* check for expired comment */ check_for_expired_comment((unsigned long)event->event_data); @@ -1442,7 +1300,7 @@ int handle_timed_event(timed_event *event) { case EVENT_CHECK_PROGRAM_UPDATE: - log_debug_info(DEBUGL_EVENTS, 0, "** Check For Program Update\n"); + log_debug_info(DEBUGL_EVENTS, 0, "** Check For Program Update. Latency: %.3fs\n", latency); /* check for new versions of Nagios */ check_for_nagios_updates(FALSE, TRUE); @@ -1450,7 +1308,7 @@ int handle_timed_event(timed_event *event) { case EVENT_USER_FUNCTION: - log_debug_info(DEBUGL_EVENTS, 0, "** User Function Event\n"); + log_debug_info(DEBUGL_EVENTS, 0, "** User Function Event. Latency: %.3fs\n", latency); /* run a user-defined function */ if(event->event_data != NULL) { @@ -1464,6 +1322,11 @@ int handle_timed_event(timed_event *event) { break; } +#ifdef USE_EVENT_BROKER + /* send event data to broker */ + broker_timed_event(NEBTYPE_TIMEDEVENT_END, NEBFLAG_NONE, NEBATTR_NONE, event, NULL); +#endif + log_debug_info(DEBUGL_FUNCTIONS, 0, "handle_timed_event() end\n"); return OK; @@ -1471,223 +1334,262 @@ int handle_timed_event(timed_event *event) { -/* adjusts scheduling of host and service checks */ +/* The squeue internal event type, declared again here so we can manipulate the + * scheduling queue without a malloc/free for each add/remove. + * @todo: Refactor this to not depend so heavily on the event queue + * implementation, doing so efficiently may require a different scheduling queue + * data structure. */ +struct squeue_event { + unsigned int pos; + pqueue_pri_t pri; + struct timeval when; + void *data; + }; + +/* + * Adjusts scheduling of active, non-forced host and service checks. + */ void adjust_check_scheduling(void) { - timed_event *temp_event = NULL; + pqueue_t *temp_pqueue; /* squeue_t is a typedef of pqueue_t. */ + struct squeue_event *sq_event; + struct squeue_event **events_to_reschedule; + + timed_event *temp_event; service *temp_service = NULL; host *temp_host = NULL; - double projected_host_check_overhead = 0.1; - double projected_service_check_overhead = 0.1; - time_t current_time = 0L; - time_t first_window_time = 0L; - time_t last_window_time = 0L; - time_t last_check_time = 0L; - time_t new_run_time = 0L; - int total_checks = 0; - int current_check = 0; + + const double INTER_CHECK_RESCHEDULE_THRESHOLD = scheduling_info.service_inter_check_delay * 0.25; double inter_check_delay = 0.0; - double current_icd_offset = 0.0; - double total_check_exec_time = 0.0; - double last_check_exec_time = 0.0; - int adjust_scheduling = FALSE; - double exec_time_factor = 0.0; - double current_exec_time = 0.0; - double current_exec_time_offset = 0.0; double new_run_time_offset = 0.0; + time_t first_window_time; + time_t last_window_time; + + struct timeval last_check_tv = { (time_t)0, (suseconds_t)0 }; + + int adjust_scheduling = FALSE; + int total_checks = 0; + int i; + log_debug_info(DEBUGL_FUNCTIONS, 0, "adjust_check_scheduling() start\n"); - /* TODO: - - Track host check overhead on a per-host basis - - Figure out how to calculate service check overhead - */ - /* determine our adjustment window */ - time(¤t_time); - first_window_time = current_time; + /* Determine our adjustment window. */ + first_window_time = time(NULL); last_window_time = first_window_time + auto_rescheduling_window; - /* get current scheduling data */ - for(temp_event = event_list_low; temp_event != NULL; temp_event = temp_event->next) { + /* Nothing to do if the first event is after the reschedule window. */ + sq_event = pqueue_peek(nagios_squeue); + temp_event = sq_event ? sq_event->data : NULL; + if (!temp_event || temp_event->run_time > last_window_time) + return; - /* skip events outside of our current window */ - if(temp_event->run_time <= first_window_time) - continue; - if(temp_event->run_time > last_window_time) - break; - if(temp_event->event_type == EVENT_HOST_CHECK) { - - if((temp_host = (host *)temp_event->event_data) == NULL) - continue; - - /* ignore forced checks */ - if(temp_host->check_options & CHECK_OPTION_FORCE_EXECUTION) - continue; - - /* does the last check "bump" into this one? */ - if((unsigned long)(last_check_time + last_check_exec_time) > temp_event->run_time) - adjust_scheduling = TRUE; - - last_check_time = temp_event->run_time; - - /* calculate time needed to perform check */ - /* NOTE: host check execution time is not taken into account, as scheduled host checks are run in parallel */ - last_check_exec_time = projected_host_check_overhead; - total_check_exec_time += last_check_exec_time; - } - - else if(temp_event->event_type == EVENT_SERVICE_CHECK) { - - if((temp_service = (service *)temp_event->event_data) == NULL) - continue; - - /* ignore forced checks */ - if(temp_service->check_options & CHECK_OPTION_FORCE_EXECUTION) - continue; - - /* does the last check "bump" into this one? */ - if((unsigned long)(last_check_time + last_check_exec_time) > temp_event->run_time) - adjust_scheduling = TRUE; - - last_check_time = temp_event->run_time; - - /* calculate time needed to perform check */ - /* NOTE: service check execution time is not taken into account, as service checks are run in parallel */ - last_check_exec_time = projected_service_check_overhead; - total_check_exec_time += last_check_exec_time; - } - - else - continue; - - total_checks++; + /* Get a sorted array of all check events to reschedule. First we need a + * duplicate of nagios_squeue so we can get the events in-order without + * having to remove them from the original queue. We will use + * pqueue_change_priority() to move the check events in the original queue. + * @note: This is horribly dependent on implementation details of squeue + * and pqueue, but we don't have much choice to avoid a free/malloc of each + * squeue_event from the head to last_window_time, or avoid paying the full + * O(n lg n) penalty twice to drain and rebuild the queue. */ + temp_pqueue = malloc(sizeof(*temp_pqueue)); + if (!temp_pqueue) { + logit(NSLOG_RUNTIME_ERROR, TRUE, "Failed to allocate queue needed to adjust check scheduling.\n"); + return; } + *temp_pqueue = *nagios_squeue; + /* We need a separate copy of the underlying queue array. */ + temp_pqueue->d = malloc(temp_pqueue->size * sizeof(void*)); + if (!temp_pqueue->d) { + logit(NSLOG_RUNTIME_ERROR, TRUE, "Failed to allocate queue data needed to adjust check scheduling.\n"); + free(temp_pqueue); + return; + } + memcpy(temp_pqueue->d, nagios_squeue->d, temp_pqueue->size * sizeof(void*)); + temp_pqueue->avail = temp_pqueue->size; - /* nothing to do... */ - if(total_checks == 0 || adjust_scheduling == FALSE) { - - /* - printf("\n\n"); - printf("NOTHING TO DO!\n"); - printf("# CHECKS: %d\n",total_checks); - printf("WINDOW TIME: %d\n",auto_rescheduling_window); - printf("EXEC TIME: %.3f\n",total_check_exec_time); - */ - + /* Now allocate space for a sorted array of check events. We shouldn't need + * space for all events, but we can't really calculate how many we'll need + * without looking at all events. */ + events_to_reschedule = malloc((temp_pqueue->size - 1) * sizeof(void*)); + if (!events_to_reschedule) { + logit(NSLOG_RUNTIME_ERROR, TRUE, "Failed to allocate memory needed to adjust check scheduling.\n"); + pqueue_free(temp_pqueue); /* pqueue_free() to keep the events. */ return; } - if((unsigned long)total_check_exec_time > auto_rescheduling_window) { - inter_check_delay = 0.0; - exec_time_factor = (double)((double)auto_rescheduling_window / total_check_exec_time); - } - else { - inter_check_delay = (double)((((double)auto_rescheduling_window) - total_check_exec_time) / (double)(total_checks * 1.0)); - exec_time_factor = 1.0; - } + /* Now we get the events to reschedule and collect some scheduling info. */ + while ((sq_event = pqueue_pop(temp_pqueue))) { - /* - printf("\n\n"); - printf("TOTAL CHECKS: %d\n",total_checks); - printf("WINDOW TIME: %d\n",auto_rescheduling_window); - printf("EXEC TIME: %.3f\n",total_check_exec_time); - printf("ICD: %.3f\n",inter_check_delay); - printf("EXEC FACTOR: %.3f\n",exec_time_factor); - */ - - /* adjust check scheduling */ - current_icd_offset = (inter_check_delay / 2.0); - for(temp_event = event_list_low; temp_event != NULL; temp_event = temp_event->next) { - - /* skip events outside of our current window */ - if(temp_event->run_time <= first_window_time) + /* We need a timed_event and event data. */ + temp_event = sq_event->data; + if (!temp_event || !temp_event->event_data) continue; - if(temp_event->run_time > last_window_time) + + /* Skip events before our current window. */ + if (temp_event->run_time < first_window_time) + continue; + /* We're done once past the end of the window. */ + if (temp_event->run_time > last_window_time) break; - if(temp_event->event_type == EVENT_HOST_CHECK) { + switch (temp_event->event_type) { + case EVENT_HOST_CHECK: + temp_host = temp_event->event_data; + /* Leave forced checks. */ + if (temp_host->check_options & CHECK_OPTION_FORCE_EXECUTION) + continue; + break; - if((temp_host = (host *)temp_event->event_data) == NULL) + case EVENT_SERVICE_CHECK: + temp_service = temp_event->event_data; + /* Leave forced checks. */ + if (temp_service->check_options & CHECK_OPTION_FORCE_EXECUTION) + continue; + break; + + default: continue; - - /* ignore forced checks */ - if(temp_host->check_options & CHECK_OPTION_FORCE_EXECUTION) - continue; - - current_exec_time = ((temp_host->execution_time + projected_host_check_overhead) * exec_time_factor); } - else if(temp_event->event_type == EVENT_SERVICE_CHECK) { - - if((temp_service = (service *)temp_event->event_data) == NULL) - continue; - - /* ignore forced checks */ - if(temp_service->check_options & CHECK_OPTION_FORCE_EXECUTION) - continue; - - /* NOTE: service check execution time is not taken into account, as service checks are run in parallel */ - current_exec_time = (projected_service_check_overhead * exec_time_factor); + /* Reschedule if the last check overlap into this one. */ + if (last_check_tv.tv_sec > 0 && tv_delta_msec(&last_check_tv, &sq_event->when) < INTER_CHECK_RESCHEDULE_THRESHOLD * 1000) { +/* log_debug_info(DEBUGL_SCHEDULING, 2, "Rescheduling event %d: %.3fs delay.\n", total_checks, tv_delta_f(&last_check_tv, &sq_event->when)); +*/ adjust_scheduling = TRUE; } - else - continue; - - current_check++; - new_run_time_offset = current_exec_time_offset + current_icd_offset; - new_run_time = (time_t)(first_window_time + (unsigned long)new_run_time_offset); - - /* - printf(" CURRENT CHECK #: %d\n",current_check); - printf(" CURRENT ICD OFFSET: %.3f\n",current_icd_offset); - printf(" CURRENT EXEC TIME: %.3f\n",current_exec_time); - printf(" CURRENT EXEC OFFSET: %.3f\n",current_exec_time_offset); - printf(" NEW RUN TIME: %lu\n",new_run_time); - */ - - if(temp_event->event_type == EVENT_HOST_CHECK) { - temp_event->run_time = new_run_time; - temp_host->next_check = new_run_time; - update_host_status(temp_host, FALSE); - } - else { - temp_event->run_time = new_run_time; - temp_service->next_check = new_run_time; - update_service_status(temp_service, FALSE); - } - - current_icd_offset += inter_check_delay; - current_exec_time_offset += current_exec_time; + last_check_tv = sq_event->when; + events_to_reschedule[total_checks++] = sq_event; + } + + /* Removing squeue_events from temp_pqueue invalidates the positions of + * those events in nagios_squeue, so we need to fix that up before we + * return or change their priorities. Start at i=1 since i=0 is unused. */ + for (i = 1; i < (int)nagios_squeue->size; ++i) { + if ((sq_event = nagios_squeue->d[i])) + sq_event->pos = i; + } + + /* No checks to reschedule, nothing to do... */ + if (total_checks < 2 || !adjust_scheduling) { + log_debug_info(DEBUGL_SCHEDULING, 0, "No events need to be rescheduled (%d checks in %ds window).\n", total_checks, auto_rescheduling_window); + + pqueue_free(temp_pqueue); + free(events_to_reschedule); + return; + } + + + inter_check_delay = auto_rescheduling_window / (double)total_checks; + + log_debug_info(DEBUGL_SCHEDULING, 0, "Rescheduling events: %d checks in %ds window, ICD: %.3fs.\n", total_checks, auto_rescheduling_window, inter_check_delay); + + + /* Now smooth out the schedule. */ + new_run_time_offset = inter_check_delay * 0.5; + for (i = 0; i < total_checks; ++i, new_run_time_offset += inter_check_delay) { + struct timeval new_run_time; + + /* All events_to_reschedule are valid squeue_events with data pointers + * to timed_events for non-forced host or service checks. */ + sq_event = events_to_reschedule[i]; + temp_event = sq_event->data; + + /* Calculate and apply a new queue 'when' time. */ + new_run_time.tv_sec = first_window_time + (time_t)floor(new_run_time_offset); + new_run_time.tv_usec = (suseconds_t)(fmod(new_run_time_offset, 1.0) * 1E6); + +/* log_debug_info(DEBUGL_SCHEDULING, 2, "Check %d: offset %.3fs, new run time %lu.%06ld.\n", i, new_run_time_offset, (unsigned long)new_run_time.tv_sec, (long)new_run_time.tv_usec); +*/ + squeue_change_priority_tv(nagios_squeue, sq_event, &new_run_time); + + + if (temp_event->run_time != new_run_time.tv_sec) + temp_event->run_time = new_run_time.tv_sec; + + switch (temp_event->event_type) { + case EVENT_HOST_CHECK: + temp_host = temp_event->event_data; + if (temp_host->next_check != new_run_time.tv_sec) { + temp_host->next_check = new_run_time.tv_sec; + update_host_status(temp_host, FALSE); + } + break; + case EVENT_SERVICE_CHECK: + temp_service = temp_event->event_data; + if (temp_service->next_check != new_run_time.tv_sec) { + temp_service->next_check = new_run_time.tv_sec; + update_service_status(temp_service, FALSE); + } + break; + default: + break; + } } - /* resort event list (some events may be out of order at this point) */ - resort_event_list(&event_list_low, &event_list_low_tail); log_debug_info(DEBUGL_FUNCTIONS, 0, "adjust_check_scheduling() end\n"); + pqueue_free(temp_pqueue); + free(events_to_reschedule); return; } +static void adjust_squeue_for_time_change(squeue_t **q, int delta) { + timed_event *event; + squeue_t *sq_new; + /* + * this is pretty inefficient in terms of free() + malloc(), + * but it should be pretty rare that we have to adjust times + * so we go with the well-tested codepath. + */ + sq_new = squeue_create(squeue_size(*q)); + while ((event = squeue_pop(*q))) { + if (event->compensate_for_time_change == TRUE) { + if (event->timing_func) { + time_t (*timingfunc)(void); + timingfunc = event->timing_func; + event->run_time = timingfunc(); + } + else { + event->run_time += delta; + } + } + if(event->priority) { + event->sq_event = squeue_add_usec(sq_new, event->run_time, event->priority - 1, event); + } + else { + event->sq_event = squeue_add(sq_new, event->run_time, event); + } + } + squeue_destroy(*q, 0); + *q = sq_new; + } /* attempts to compensate for a change in the system time */ void compensate_for_system_time_change(unsigned long last_time, unsigned long current_time) { unsigned long time_difference = 0L; - timed_event *temp_event = NULL; service *temp_service = NULL; host *temp_host = NULL; int days = 0; int hours = 0; int minutes = 0; int seconds = 0; - time_t (*timingfunc)(void); + int delta = 0; log_debug_info(DEBUGL_FUNCTIONS, 0, "compensate_for_system_time_change() start\n"); + /* + * if current_time < last_time, delta will be negative so we can + * still use addition to all effected timestamps + */ + delta = current_time - last_time; + /* we moved back in time... */ if(last_time > current_time) { time_difference = last_time - current_time; @@ -1703,49 +1605,11 @@ void compensate_for_system_time_change(unsigned long last_time, unsigned long cu } /* log the time change */ - logit(NSLOG_PROCESS_INFO | NSLOG_RUNTIME_WARNING, TRUE, "Warning: A system time change of %dd %dh %dm %ds (%s in time) has been detected. Compensating...\n", days, hours, minutes, seconds, (last_time > current_time) ? "backwards" : "forwards"); + logit(NSLOG_PROCESS_INFO | NSLOG_RUNTIME_WARNING, TRUE, "Warning: A system time change of %d seconds (%dd %dh %dm %ds %s in time) has been detected. Compensating...\n", + delta, days, hours, minutes, seconds, + (last_time > current_time) ? "backwards" : "forwards"); - /* adjust the next run time for all high priority timed events */ - for(temp_event = event_list_high; temp_event != NULL; temp_event = temp_event->next) { - - /* skip special events that occur at specific times... */ - if(temp_event->compensate_for_time_change == FALSE) - continue; - - /* use custom timing function */ - if(temp_event->timing_func != NULL) { - timingfunc = temp_event->timing_func; - temp_event->run_time = (*timingfunc)(); - } - - /* else use standard adjustment */ - else - adjust_timestamp_for_time_change(last_time, current_time, time_difference, &temp_event->run_time); - } - - /* resort event list (some events may be out of order at this point) */ - resort_event_list(&event_list_high, &event_list_high_tail); - - /* adjust the next run time for all low priority timed events */ - for(temp_event = event_list_low; temp_event != NULL; temp_event = temp_event->next) { - - /* skip special events that occur at specific times... */ - if(temp_event->compensate_for_time_change == FALSE) - continue; - - /* use custom timing function */ - if(temp_event->timing_func != NULL) { - timingfunc = temp_event->timing_func; - temp_event->run_time = (*timingfunc)(); - } - - /* else use standard adjustment */ - else - adjust_timestamp_for_time_change(last_time, current_time, time_difference, &temp_event->run_time); - } - - /* resort event list (some events may be out of order at this point) */ - resort_event_list(&event_list_low, &event_list_low_tail); + adjust_squeue_for_time_change(&nagios_squeue, delta); /* adjust service timestamps */ for(temp_service = service_list; temp_service != NULL; temp_service = temp_service->next) { @@ -1766,7 +1630,7 @@ void compensate_for_system_time_change(unsigned long last_time, unsigned long cu /* adjust host timestamps */ for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) { - adjust_timestamp_for_time_change(last_time, current_time, time_difference, &temp_host->last_host_notification); + adjust_timestamp_for_time_change(last_time, current_time, time_difference, &temp_host->last_notification); adjust_timestamp_for_time_change(last_time, current_time, time_difference, &temp_host->last_check); adjust_timestamp_for_time_change(last_time, current_time, time_difference, &temp_host->next_check); adjust_timestamp_for_time_change(last_time, current_time, time_difference, &temp_host->last_state_change); @@ -1774,7 +1638,7 @@ void compensate_for_system_time_change(unsigned long last_time, unsigned long cu adjust_timestamp_for_time_change(last_time, current_time, time_difference, &temp_host->last_state_history_update); /* recalculate next re-notification time */ - temp_host->next_host_notification = get_next_host_notification_time(temp_host, temp_host->last_host_notification); + temp_host->next_notification = get_next_host_notification_time(temp_host, temp_host->last_notification); /* update the status data */ update_host_status(temp_host, FALSE); @@ -1783,7 +1647,6 @@ void compensate_for_system_time_change(unsigned long last_time, unsigned long cu /* adjust program timestamps */ adjust_timestamp_for_time_change(last_time, current_time, time_difference, &program_start); adjust_timestamp_for_time_change(last_time, current_time, time_difference, &event_start); - adjust_timestamp_for_time_change(last_time, current_time, time_difference, &last_command_check); /* update the status data */ update_program_status(FALSE); @@ -1793,33 +1656,6 @@ void compensate_for_system_time_change(unsigned long last_time, unsigned long cu -/* resorts an event list by event execution time - needed when compensating for system time changes */ -void resort_event_list(timed_event **event_list, timed_event **event_list_tail) { - timed_event *temp_event_list = NULL; - timed_event *temp_event = NULL; - timed_event *next_event = NULL; - - log_debug_info(DEBUGL_FUNCTIONS, 0, "resort_event_list()\n"); - - /* move current event list to temp list */ - temp_event_list = *event_list; - *event_list = NULL; - - /* move all events to the new event list */ - for(temp_event = temp_event_list; temp_event != NULL; temp_event = next_event) { - next_event = temp_event->next; - - /* add the event to the newly created event list so it will be resorted */ - temp_event->next = NULL; - temp_event->prev = NULL; - add_event(temp_event, event_list, event_list_tail); - } - - return; - } - - - /* adjusts a timestamp variable in accordance with a system time change */ void adjust_timestamp_for_time_change(time_t last_time, time_t current_time, unsigned long time_difference, time_t *ts) { diff --git a/base/flapping.c b/base/flapping.c index 21be777..c4bac1c 100644 --- a/base/flapping.c +++ b/base/flapping.c @@ -2,8 +2,6 @@ * * FLAPPING.C - State flap detection and handling routines for Nagios * - * Copyright (c) 2001-2009 Ethan Galstad (egalstad@nagios.org) - * Last Modified: 05-15-2009 * * License: * @@ -32,21 +30,6 @@ #include "../include/nagios.h" #include "../include/broker.h" -extern int interval_length; - -extern int enable_flap_detection; - -extern double low_service_flap_threshold; -extern double high_service_flap_threshold; -extern double low_host_flap_threshold; -extern double high_host_flap_threshold; - -extern host *host_list; -extern service *service_list; - -extern unsigned long modified_host_process_attributes; -extern unsigned long modified_service_process_attributes; - /******************************************************************/ /******************** FLAP DETECTION FUNCTIONS ********************/ @@ -91,14 +74,9 @@ void check_for_service_flapping(service *svc, int update, int allow_flapstart_no /* should we update state history for this state? */ if(update_history == TRUE) { - if(svc->current_state == STATE_OK && svc->flap_detection_on_ok == FALSE) - update_history = FALSE; - if(svc->current_state == STATE_WARNING && svc->flap_detection_on_warning == FALSE) - update_history = FALSE; - if(svc->current_state == STATE_UNKNOWN && svc->flap_detection_on_unknown == FALSE) - update_history = FALSE; - if(svc->current_state == STATE_CRITICAL && svc->flap_detection_on_critical == FALSE) + if(!should_flap_detect(svc)) update_history = FALSE; + } /* record current service state */ @@ -142,13 +120,13 @@ void check_for_service_flapping(service *svc, int update, int allow_flapstart_no log_debug_info(DEBUGL_FLAPPING, 2, "LFT=%.2f, HFT=%.2f, CPC=%.2f, PSC=%.2f%%\n", low_threshold, high_threshold, curved_percent_change, curved_percent_change); - /* don't do anything if we don't have flap detection enabled on a program-wide basis */ - if(enable_flap_detection == FALSE) - return; - - /* don't do anything if we don't have flap detection enabled for this service */ - if(svc->flap_detection_enabled == FALSE) + /* don't do anything if we don't have flap detection enabled + on a program-wide basis or for this service */ + if(enable_flap_detection == FALSE || svc->flap_detection_enabled == FALSE) { + if(svc->is_flapping == TRUE) + clear_service_flap(svc, curved_percent_change, high_threshold, low_threshold, 1); return; + } /* are we flapping, undecided, or what?... */ @@ -172,7 +150,7 @@ void check_for_service_flapping(service *svc, int update, int allow_flapstart_no /* did the service just stop flapping? */ else if(is_flapping == FALSE && svc->is_flapping == TRUE) - clear_service_flap(svc, curved_percent_change, high_threshold, low_threshold); + clear_service_flap(svc, curved_percent_change, high_threshold, low_threshold, 0); return; } @@ -215,12 +193,9 @@ void check_for_host_flapping(host *hst, int update, int actual_check, int allow_ /* should we update state history for this state? */ if(update_history == TRUE) { - if(hst->current_state == HOST_UP && hst->flap_detection_on_up == FALSE) - update_history = FALSE; - if(hst->current_state == HOST_DOWN && hst->flap_detection_on_down == FALSE) - update_history = FALSE; - if(hst->current_state == HOST_UNREACHABLE && hst->flap_detection_on_unreachable == FALSE) + if(!(hst->flap_detection_options & (1 << hst->current_state))) update_history = FALSE; + } /* if we didn't have an actual check, only update if we've waited long enough */ @@ -278,13 +253,13 @@ void check_for_host_flapping(host *hst, int update, int actual_check, int allow_ log_debug_info(DEBUGL_FLAPPING, 2, "LFT=%.2f, HFT=%.2f, CPC=%.2f, PSC=%.2f%%\n", low_threshold, high_threshold, curved_percent_change, curved_percent_change); - /* don't do anything if we don't have flap detection enabled on a program-wide basis */ - if(enable_flap_detection == FALSE) - return; - - /* don't do anything if we don't have flap detection enabled for this host */ - if(hst->flap_detection_enabled == FALSE) + /* don't do anything if we don't have flap detection enabled + on a program-wide basis or for this service */ + if(enable_flap_detection == FALSE || hst->flap_detection_enabled == FALSE) { + if(hst->is_flapping == TRUE) + clear_host_flap(hst, curved_percent_change, high_threshold, low_threshold, 1); return; + } /* are we flapping, undecided, or what?... */ @@ -308,7 +283,7 @@ void check_for_host_flapping(host *hst, int update, int actual_check, int allow_ /* did the host just stop flapping? */ else if(is_flapping == FALSE && hst->is_flapping == TRUE) - clear_host_flap(hst, curved_percent_change, high_threshold, low_threshold); + clear_host_flap(hst, curved_percent_change, high_threshold, low_threshold, 0); return; } @@ -361,17 +336,22 @@ void set_service_flap(service *svc, double percent_change, double high_threshold /* handles a service that has stopped flapping */ -void clear_service_flap(service *svc, double percent_change, double high_threshold, double low_threshold) { +void clear_service_flap(service *svc, double percent_change, double high_threshold, double low_threshold, int is_disabled) { log_debug_info(DEBUGL_FUNCTIONS, 0, "clear_service_flap()\n"); if(svc == NULL) return; - log_debug_info(DEBUGL_FLAPPING, 1, "Service '%s' on host '%s' stopped flapping.\n", svc->description, svc->host_name); - - /* log a notice - this one is parsed by the history CGI */ - logit(NSLOG_INFO_MESSAGE, FALSE, "SERVICE FLAPPING ALERT: %s;%s;STOPPED; Service appears to have stopped flapping (%2.1f%% change < %2.1f%% threshold)\n", svc->host_name, svc->description, percent_change, low_threshold); + if (is_disabled == 0) { + log_debug_info(DEBUGL_FLAPPING, 1, "Service '%s' on host '%s' stopped flapping.\n", svc->description, svc->host_name); + /* log a notice - this one is parsed by the history CGI */ + logit(NSLOG_INFO_MESSAGE, FALSE, "SERVICE FLAPPING ALERT: %s;%s;STOPPED; Service appears to have stopped flapping (%2.1f%% change < %2.1f%% threshold)\n", svc->host_name, svc->description, percent_change, low_threshold); + } else { + log_debug_info(DEBUGL_FLAPPING, 1, "Disabled flap detection for service '%s' on host '%s'.\n", svc->description, svc->host_name); + /* log a notice - this one is parsed by the history CGI */ + logit(NSLOG_INFO_MESSAGE, FALSE, "SERVICE FLAPPING ALERT: %s;%s;STOPPED; Disabled flap detection for service\n", svc->host_name, svc->description); + } /* delete the comment we added earlier */ if(svc->flapping_comment_id != 0) @@ -386,12 +366,14 @@ void clear_service_flap(service *svc, double percent_change, double high_thresho broker_flapping_data(NEBTYPE_FLAPPING_STOP, NEBFLAG_NONE, NEBATTR_FLAPPING_STOP_NORMAL, SERVICE_FLAPPING, svc, percent_change, high_threshold, low_threshold, NULL); #endif - /* send a notification */ - service_notification(svc, NOTIFICATION_FLAPPINGSTOP, NULL, NULL, NOTIFICATION_OPTION_NONE); + if (is_disabled == 0) { + /* send a notification */ + service_notification(svc, NOTIFICATION_FLAPPINGSTOP, NULL, NULL, NOTIFICATION_OPTION_NONE); - /* should we send a recovery notification? */ - if(svc->check_flapping_recovery_notification == TRUE && svc->current_state == STATE_OK) - service_notification(svc, NOTIFICATION_NORMAL, NULL, NULL, NOTIFICATION_OPTION_NONE); + /* should we send a recovery notification? */ + if(svc->check_flapping_recovery_notification == TRUE && svc->current_state == STATE_OK) + service_notification(svc, NOTIFICATION_NORMAL, NULL, NULL, NOTIFICATION_OPTION_NONE); + } /* clear the recovery notification flag */ svc->check_flapping_recovery_notification = FALSE; @@ -442,17 +424,22 @@ void set_host_flap(host *hst, double percent_change, double high_threshold, doub /* handles a host that has stopped flapping */ -void clear_host_flap(host *hst, double percent_change, double high_threshold, double low_threshold) { +void clear_host_flap(host *hst, double percent_change, double high_threshold, double low_threshold, int is_disabled) { log_debug_info(DEBUGL_FUNCTIONS, 0, "clear_host_flap()\n"); if(hst == NULL) return; - log_debug_info(DEBUGL_FLAPPING, 1, "Host '%s' stopped flapping.\n", hst->name); - - /* log a notice - this one is parsed by the history CGI */ - logit(NSLOG_INFO_MESSAGE, FALSE, "HOST FLAPPING ALERT: %s;STOPPED; Host appears to have stopped flapping (%2.1f%% change < %2.1f%% threshold)\n", hst->name, percent_change, low_threshold); + if (is_disabled == 0) { + log_debug_info(DEBUGL_FLAPPING, 1, "Host '%s' stopped flapping.\n", hst->name); + /* log a notice - this one is parsed by the history CGI */ + logit(NSLOG_INFO_MESSAGE, FALSE, "HOST FLAPPING ALERT: %s;STOPPED; Host appears to have stopped flapping (%2.1f%% change < %2.1f%% threshold)\n", hst->name, percent_change, low_threshold); + } else { + log_debug_info(DEBUGL_FLAPPING, 1, "Disabled flap detection for host '%s'.\n", hst->name); + /* log a notice - this one is parsed by the history CGI */ + logit(NSLOG_INFO_MESSAGE, FALSE, "HOST FLAPPING ALERT: %s;STOPPED; Disabled flap detection\n", hst->name); + } /* delete the comment we added earlier */ if(hst->flapping_comment_id != 0) @@ -467,12 +454,14 @@ void clear_host_flap(host *hst, double percent_change, double high_threshold, do broker_flapping_data(NEBTYPE_FLAPPING_STOP, NEBFLAG_NONE, NEBATTR_FLAPPING_STOP_NORMAL, HOST_FLAPPING, hst, percent_change, high_threshold, low_threshold, NULL); #endif - /* send a notification */ - host_notification(hst, NOTIFICATION_FLAPPINGSTOP, NULL, NULL, NOTIFICATION_OPTION_NONE); + if (is_disabled == 0) { + /* send a notification */ + host_notification(hst, NOTIFICATION_FLAPPINGSTOP, NULL, NULL, NOTIFICATION_OPTION_NONE); - /* should we send a recovery notification? */ - if(hst->check_flapping_recovery_notification == TRUE && hst->current_state == HOST_UP) - host_notification(hst, NOTIFICATION_NORMAL, NULL, NULL, NOTIFICATION_OPTION_NONE); + /* should we send a recovery notification? */ + if(hst->check_flapping_recovery_notification == TRUE && hst->current_state == HOST_UP) + host_notification(hst, NOTIFICATION_NORMAL, NULL, NULL, NOTIFICATION_OPTION_NONE); + } /* clear the recovery notification flag */ hst->check_flapping_recovery_notification = FALSE; @@ -488,8 +477,7 @@ void clear_host_flap(host *hst, double percent_change, double high_threshold, do /* enables flap detection on a program wide basis */ void enable_flap_detection_routines(void) { - host *temp_host = NULL; - service *temp_service = NULL; + unsigned int i; unsigned long attr = MODATTR_FLAP_DETECTION_ENABLED; log_debug_info(DEBUGL_FUNCTIONS, 0, "enable_flap_detection_routines()\n"); @@ -514,20 +502,18 @@ void enable_flap_detection_routines(void) { update_program_status(FALSE); /* check for flapping */ - for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) - check_for_host_flapping(temp_host, FALSE, FALSE, TRUE); - for(temp_service = service_list; temp_service != NULL; temp_service = temp_service->next) - check_for_service_flapping(temp_service, FALSE, TRUE); + for(i = 0; i < num_objects.hosts; i++) + check_for_host_flapping(host_ary[i], FALSE, FALSE, TRUE); + for(i = 0; i < num_objects.services; i++) + check_for_service_flapping(service_ary[i], FALSE, TRUE); - return; } /* disables flap detection on a program wide basis */ void disable_flap_detection_routines(void) { - host *temp_host = NULL; - service *temp_service = NULL; + unsigned int i; unsigned long attr = MODATTR_FLAP_DETECTION_ENABLED; log_debug_info(DEBUGL_FUNCTIONS, 0, "disable_flap_detection_routines()\n"); @@ -552,10 +538,10 @@ void disable_flap_detection_routines(void) { update_program_status(FALSE); /* handle the details... */ - for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) - handle_host_flap_detection_disabled(temp_host); - for(temp_service = service_list; temp_service != NULL; temp_service = temp_service->next) - handle_service_flap_detection_disabled(temp_service); + for(i = 0; i < num_objects.hosts; i++) + handle_host_flap_detection_disabled(host_ary[i]); + for(i = 0; i < num_objects.services; i++) + handle_service_flap_detection_disabled(service_ary[i]); return; } @@ -788,8 +774,3 @@ void handle_service_flap_detection_disabled(service *svc) { return; } - - - - - diff --git a/base/logging.c b/base/logging.c index ef732ad..1c4e5da 100644 --- a/base/logging.c +++ b/base/logging.c @@ -2,8 +2,6 @@ * * LOGGING.C - Log file functions for use with Nagios * - * Copyright (c) 1999-2007 Ethan Galstad (egalstad@nagios.org) - * Last Modified: 10-28-2007 * * License: * @@ -28,98 +26,11 @@ #include "../include/macros.h" #include "../include/nagios.h" #include "../include/broker.h" +#include -extern char *log_file; -extern char *temp_file; -extern char *log_archive_path; - -extern host *host_list; -extern service *service_list; - -extern int use_syslog; -extern int log_service_retries; -extern int log_initial_states; - -extern unsigned long logging_options; -extern unsigned long syslog_options; - -extern int verify_config; -extern int test_scheduling; - -extern time_t last_log_rotation; -extern int log_rotation_method; - -extern int daemon_mode; - -extern char *debug_file; -extern int debug_level; -extern int debug_verbosity; -extern unsigned long max_debug_file_size; -FILE *debug_file_fp = NULL; - -static pthread_mutex_t debug_fp_lock; - -/* These simple helpers should most likely be elsewhere */ -static const char *service_state_name(int state) { - switch(state) { - case STATE_OK: - return "OK"; - case STATE_WARNING: - return "WARNING"; - case STATE_CRITICAL: - return "CRITICAL"; - } - - return "UNKNOWN"; - } - -static const char *host_state_name(int state) { - switch(state) { - case HOST_UP: - return "UP"; - case HOST_DOWN: - return "DOWN"; - case HOST_UNREACHABLE: - return "UNREACHABLE"; - } - - return "(unknown)"; - } - -static const char *state_type_name(int state_type) { - return state_type == HARD_STATE ? "HARD" : "SOFT"; - } - -/* - * since we don't want child processes to hang indefinitely - * in case they inherit a locked lock, we use soft-locking - * here, which basically tries to acquire the lock for a - * short while and then gives up, returning -1 to signal - * the error - */ -static inline int soft_lock(pthread_mutex_t *lock) { - int i; - - for(i = 0; i < 5; i++) { - if(!pthread_mutex_trylock(lock)) { - /* success */ - return 0; - } - - if(errno == EDEADLK) { - /* we already have the lock */ - return 0; - } - - /* sleep briefly */ - usleep(30); - } - - return -1; /* we failed to get the lock. Nothing to do */ - } - - +static FILE *debug_file_fp; +static FILE *log_fp; /******************************************************************/ /************************ LOGGING FUNCTIONS ***********************/ @@ -199,29 +110,92 @@ static void write_to_all_logs_with_timestamp(char *buffer, unsigned long data_ty } +static FILE *open_log_file(void) +{ + int fh; + struct stat st; + + if(log_fp) /* keep it open unless we rotate */ + return log_fp; + + if ((fh = open(log_file, O_RDWR|O_APPEND|O_CREAT|O_NOFOLLOW, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) == -1) { + if (daemon_mode == FALSE) + printf("Warning: Cannot open log file '%s' for writing\n", log_file); + return NULL; + } + log_fp = fdopen(fh, "a+"); + if(log_fp == NULL) { + if (daemon_mode == FALSE) + printf("Warning: Cannot open log file '%s' for writing\n", log_file); + return NULL; + } + + if ((fstat(fh, &st)) == -1) { + log_fp = NULL; + close(fh); + if (daemon_mode == FALSE) + printf("Warning: Cannot fstat log file '%s'\n", log_file); + return NULL; + } + if (st.st_nlink != 1 || (st.st_mode & S_IFMT) != S_IFREG) { + log_fp = NULL; + close(fh); + if (daemon_mode == FALSE) + printf("Warning: log file '%s' has an invalid mode\n", log_file); + return NULL; + } + + (void)fcntl(fileno(log_fp), F_SETFD, FD_CLOEXEC); + return log_fp; +} + +int fix_log_file_owner(uid_t uid, gid_t gid) +{ + int r1 = 0, r2 = 0; + + if (!(log_fp = open_log_file())) + return -1; + r1 = fchown(fileno(log_fp), uid, gid); + + if (open_debug_log() != OK) + return -1; + if (debug_file_fp) + r2 = fchown(fileno(debug_file_fp), uid, gid); + + /* return 0 if both are 0 and otherwise < 0 */ + return r1 < r2 ? r1 : r2; +} + +int close_log_file(void) +{ + if(!log_fp) + return 0; + + fflush(log_fp); + fclose(log_fp); + log_fp = NULL; + return 0; +} + /* write something to the nagios log file */ int write_to_log(char *buffer, unsigned long data_type, time_t *timestamp) { - FILE *fp = NULL; + FILE *fp; time_t log_time = 0L; if(buffer == NULL) return ERROR; /* don't log anything if we're not actually running... */ - if(verify_config == TRUE || test_scheduling == TRUE) + if(verify_config || test_scheduling == TRUE) return OK; /* make sure we can log this type of entry */ if(!(data_type & logging_options)) return OK; - fp = fopen(log_file, "a+"); - if(fp == NULL) { - if(daemon_mode == FALSE) - printf("Warning: Cannot open log file '%s' for writing\n", log_file); + fp = open_log_file(); + if (fp == NULL) return ERROR; - } - /* what timestamp should we use? */ if(timestamp == NULL) time(&log_time); @@ -232,9 +206,8 @@ int write_to_log(char *buffer, unsigned long data_type, time_t *timestamp) { strip(buffer); /* write the buffer to the log file */ - fprintf(fp, "[%lu] %s\n", log_time, buffer); - - fclose(fp); + fprintf(fp, "[%llu] %s\n", (unsigned long long)log_time, buffer); + fflush(fp); #ifdef USE_EVENT_BROKER /* send data to the event broker */ @@ -252,7 +225,7 @@ int write_to_syslog(char *buffer, unsigned long data_type) { return ERROR; /* don't log anything if we're not actually running... */ - if(verify_config == TRUE || test_scheduling == TRUE) + if(verify_config || test_scheduling == TRUE) return OK; /* bail out if we shouldn't write to syslog */ @@ -295,13 +268,14 @@ int log_service_event(service *svc) { return ERROR; asprintf(&temp_buffer, "SERVICE ALERT: %s;%s;%s;%s;%d;%s\n", - svc->host_name, svc->description, - service_state_name(svc->current_state), - state_type_name(svc->state_type), - svc->current_attempt, - (svc->plugin_output == NULL) ? "" : svc->plugin_output); + svc->host_name, svc->description, + service_state_name(svc->current_state), + state_type_name(svc->state_type), + svc->current_attempt, + (svc->plugin_output == NULL) ? "" : svc->plugin_output); write_to_all_logs(temp_buffer, log_options); + free(temp_buffer); return OK; } @@ -321,11 +295,11 @@ int log_host_event(host *hst) { log_options = NSLOG_HOST_UP; asprintf(&temp_buffer, "HOST ALERT: %s;%s;%s;%d;%s\n", - hst->name, - host_state_name(hst->current_state), - state_type_name(hst->state_type), - hst->current_attempt, - (hst->plugin_output == NULL) ? "" : hst->plugin_output); + hst->name, + host_state_name(hst->current_state), + state_type_name(hst->state_type), + hst->current_attempt, + (hst->plugin_output == NULL) ? "" : hst->plugin_output); write_to_all_logs(temp_buffer, log_options); @@ -347,11 +321,11 @@ int log_host_states(int type, time_t *timestamp) { for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) { asprintf(&temp_buffer, "%s HOST STATE: %s;%s;%s;%d;%s\n", (type == INITIAL_STATES) ? "INITIAL" : "CURRENT", - temp_host->name, - host_state_name(temp_host->current_state), - state_type_name(temp_host->state_type), - temp_host->current_attempt, - (temp_host->plugin_output == NULL) ? "" : temp_host->plugin_output); + temp_host->name, + host_state_name(temp_host->current_state), + state_type_name(temp_host->state_type), + temp_host->current_attempt, + (temp_host->plugin_output == NULL) ? "" : temp_host->plugin_output); write_to_all_logs_with_timestamp(temp_buffer, NSLOG_INFO_MESSAGE, timestamp); @@ -379,12 +353,12 @@ int log_service_states(int type, time_t *timestamp) { continue; asprintf(&temp_buffer, "%s SERVICE STATE: %s;%s;%s;%s;%d;%s\n", - (type == INITIAL_STATES) ? "INITIAL" : "CURRENT", - temp_service->host_name, temp_service->description, - service_state_name(temp_service->current_state), - state_type_name(temp_service->state_type), - temp_service->current_attempt, - temp_service->plugin_output); + (type == INITIAL_STATES) ? "INITIAL" : "CURRENT", + temp_service->host_name, temp_service->description, + service_state_name(temp_service->current_state), + state_type_name(temp_service->state_type), + temp_service->current_attempt, + temp_service->plugin_output); write_to_all_logs_with_timestamp(temp_buffer, NSLOG_INFO_MESSAGE, timestamp); @@ -404,6 +378,8 @@ int rotate_log_file(time_t rotation_time) { int rename_result = 0; int stat_result = -1; struct stat log_file_stat; + struct stat archive_stat; + int archive_stat_result; if(log_rotation_method == LOG_ROTATION_NONE) { return OK; @@ -427,11 +403,26 @@ int rotate_log_file(time_t rotation_time) { stat_result = stat(log_file, &log_file_stat); + close_log_file(); + /* get the archived filename to use */ asprintf(&log_archive, "%s%snagios-%02d-%02d-%d-%02d.log", log_archive_path, (log_archive_path[strlen(log_archive_path) - 1] == '/') ? "" : "/", t->tm_mon + 1, t->tm_mday, t->tm_year + 1900, t->tm_hour); + /* HACK: If the archive exists, don't overwrite it. This is a hack + because the real problem is that some log rotations are executed + early and as a result the next log rotation is scheduled for + the same time as the one that ran early */ + archive_stat_result = stat(log_archive, &archive_stat); + if((0 == archive_stat_result) || + ((-1 == archive_stat_result) && (ENOENT != errno))) { + return OK; + } + /* rotate the log file */ rename_result = my_rename(log_file, log_archive); + log_fp = open_log_file(); + if (log_fp == NULL) + return ERROR; if(rename_result) { my_free(log_archive); @@ -451,9 +442,11 @@ int rotate_log_file(time_t rotation_time) { chown(log_file, log_file_stat.st_uid, log_file_stat.st_gid); } - /* log current host and service state */ - log_host_states(CURRENT_STATES, &rotation_time); - log_service_states(CURRENT_STATES, &rotation_time); + /* log current host and service state if activated */ + if(log_current_states==TRUE) { + log_host_states(CURRENT_STATES, &rotation_time); + log_service_states(CURRENT_STATES, &rotation_time); + } /* free memory */ my_free(log_archive); @@ -476,41 +469,36 @@ int write_log_file_info(time_t *timestamp) { /* opens the debug log for writing */ -int open_debug_log(void) { +int open_debug_log(void) +{ + int fh; + struct stat st; /* don't do anything if we're not actually running... */ - if(verify_config == TRUE || test_scheduling == TRUE) + if(verify_config || test_scheduling == TRUE) return OK; /* don't do anything if we're not debugging */ if(debug_level == DEBUGL_NONE) return OK; - if((debug_file_fp = fopen(debug_file, "a+")) == NULL) + if ((fh = open(debug_file, O_RDWR|O_APPEND|O_CREAT|O_NOFOLLOW, S_IRUSR|S_IWUSR)) == -1) + return ERROR; + if((debug_file_fp = fdopen(fh, "a+")) == NULL) return ERROR; - return OK; + if ((fstat(fh, &st)) == -1) { + debug_file_fp = NULL; + close(fh); + return ERROR; + } + if (st.st_nlink != 1 || (st.st_mode & S_IFMT) != S_IFREG) { + debug_file_fp = NULL; + close(fh); + return ERROR; } - -/* change the ownership of the debug log. This is done so that if Nagios - receives a HUP signal, it will be owned by a user that can reopen the file */ -int chown_debug_log(uid_t uid, gid_t gid) { - - /* don't do anything if we're not actually running... */ - if(verify_config == TRUE || test_scheduling == TRUE) - return OK; - - /* don't do anything if we're not debugging */ - if(debug_level == DEBUGL_NONE) - return OK; - - if(chown(debug_file, uid, gid) < 0) { - logit(NSLOG_RUNTIME_WARNING, TRUE, - "Failed to change ownership on debug log: %s.", - strerror(errno)); - return ERROR; - } + (void)fcntl(fh, F_SETFD, FD_CLOEXEC); return OK; } @@ -531,7 +519,7 @@ int close_debug_log(void) { /* write to the debug log */ int log_debug_info(int level, int verbosity, const char *fmt, ...) { va_list ap; - char *temp_path = NULL; + char *tmppath = NULL; struct timeval current_time; if(!(debug_level == DEBUGL_ALL || (level & debug_level))) @@ -543,15 +531,6 @@ int log_debug_info(int level, int verbosity, const char *fmt, ...) { if(debug_file_fp == NULL) return ERROR; - /* - * lock it so concurrent threads don't stomp on each other's - * writings. We maintain the lock until we've (optionally) - * renamed the file. - * If soft_lock() fails we return early. - */ - if(soft_lock(&debug_fp_lock) < 0) - return ERROR; - /* write the timestamp */ gettimeofday(¤t_time, NULL); fprintf(debug_file_fp, "[%lu.%06lu] [%03d.%d] [pid=%lu] ", current_time.tv_sec, current_time.tv_usec, level, verbosity, (unsigned long)getpid()); @@ -571,25 +550,22 @@ int log_debug_info(int level, int verbosity, const char *fmt, ...) { close_debug_log(); /* rotate the log file */ - asprintf(&temp_path, "%s.old", debug_file); - if(temp_path) { + asprintf(&tmppath, "%s.old", debug_file); + if(tmppath) { /* unlink the old debug file */ - unlink(temp_path); + unlink(tmppath); /* rotate the debug file */ - my_rename(debug_file, temp_path); + my_rename(debug_file, tmppath); /* free memory */ - my_free(temp_path); + my_free(tmppath); } /* open a new file */ open_debug_log(); } - pthread_mutex_unlock(&debug_fp_lock); - return OK; } - diff --git a/base/nagios.c b/base/nagios.c index 3f42684..2678700 100644 --- a/base/nagios.c +++ b/base/nagios.c @@ -3,13 +3,9 @@ * NAGIOS.C - Core Program Code For Nagios * * Program: Nagios Core - * Version: 3.5.1 * License: GPL - * Copyright (c) 2009-2010 Nagios Core Development Team and Community Contributors - * Copyright (c) 1999-2009 Ethan Galstad * * First Written: 01-28-1999 (start of development) - * Last Modified: * * Description: * @@ -49,238 +45,179 @@ #include "../include/broker.h" #include "../include/nebmods.h" #include "../include/nebmodules.h" +#include "../include/workers.h" /*#define DEBUG_MEMORY 1*/ #ifdef DEBUG_MEMORY #include #endif +static int is_worker; -char *config_file = NULL; -char *log_file = NULL; -char *command_file = NULL; -char *temp_file = NULL; -char *temp_path = NULL; -char *check_result_path = NULL; -char *lock_file = NULL; -char *log_archive_path = NULL; -char *p1_file = NULL; /**** EMBEDDED PERL ****/ -char *auth_file = NULL; /**** EMBEDDED PERL INTERPRETER AUTH FILE ****/ -char *nagios_user = NULL; -char *nagios_group = NULL; +static void set_loadctl_defaults(void) +{ + struct rlimit rlim; -char *global_host_event_handler = NULL; -char *global_service_event_handler = NULL; -command *global_host_event_handler_ptr = NULL; -command *global_service_event_handler_ptr = NULL; + /* Workers need to up 'em, master needs to know 'em */ + getrlimit(RLIMIT_NOFILE, &rlim); + rlim.rlim_cur = rlim.rlim_max; + setrlimit(RLIMIT_NOFILE, &rlim); + loadctl.nofile_limit = rlim.rlim_max; +#ifdef RLIMIT_NPROC + getrlimit(RLIMIT_NPROC, &rlim); + rlim.rlim_cur = rlim.rlim_max; + setrlimit(RLIMIT_NPROC, &rlim); + loadctl.nproc_limit = rlim.rlim_max; +#else + loadctl.nproc_limit = loadctl.nofile_limit / 2; +#endif -char *ocsp_command = NULL; -char *ochp_command = NULL; -command *ocsp_command_ptr = NULL; -command *ochp_command_ptr = NULL; + /* + * things may have been configured already. Otherwise we + * set some sort of sane defaults here + */ + if (!loadctl.jobs_max) { + loadctl.jobs_max = loadctl.nproc_limit - 100; + if (!is_worker && loadctl.jobs_max > (loadctl.nofile_limit - 50) * wproc_num_workers_online) { + loadctl.jobs_max = (loadctl.nofile_limit - 50) * wproc_num_workers_online; + } + } -char *illegal_object_chars = NULL; -char *illegal_output_chars = NULL; + if (!loadctl.jobs_limit) + loadctl.jobs_limit = loadctl.jobs_max; -int use_regexp_matches = FALSE; -int use_true_regexp_matching = FALSE; + if (!loadctl.backoff_limit) + loadctl.backoff_limit = online_cpus() * 2.5; + if (!loadctl.rampup_limit) + loadctl.rampup_limit = online_cpus() * 0.8; + if (!loadctl.backoff_change) + loadctl.backoff_change = loadctl.jobs_limit * 0.3; + if (!loadctl.rampup_change) + loadctl.rampup_change = loadctl.backoff_change * 0.25; + if (!loadctl.check_interval) + loadctl.check_interval = 60; + if (!loadctl.jobs_min) + loadctl.jobs_min = online_cpus() * 20; /* pessimistic */ +} -int use_syslog = DEFAULT_USE_SYSLOG; -int log_notifications = DEFAULT_NOTIFICATION_LOGGING; -int log_service_retries = DEFAULT_LOG_SERVICE_RETRIES; -int log_host_retries = DEFAULT_LOG_HOST_RETRIES; -int log_event_handlers = DEFAULT_LOG_EVENT_HANDLERS; -int log_initial_states = DEFAULT_LOG_INITIAL_STATES; -int log_external_commands = DEFAULT_LOG_EXTERNAL_COMMANDS; -int log_passive_checks = DEFAULT_LOG_PASSIVE_CHECKS; +static int test_path_access(const char *program, int mode) +{ + char *envpath, *p, *colon; + int ret, our_errno = 1500; /* outside errno range */ -unsigned long logging_options = 0; -unsigned long syslog_options = 0; + if (program[0] == '/' || !(envpath = getenv("PATH"))) + return access(program, mode); -int service_check_timeout = DEFAULT_SERVICE_CHECK_TIMEOUT; -int service_check_timeout_state = STATE_CRITICAL; -int host_check_timeout = DEFAULT_HOST_CHECK_TIMEOUT; -int event_handler_timeout = DEFAULT_EVENT_HANDLER_TIMEOUT; -int notification_timeout = DEFAULT_NOTIFICATION_TIMEOUT; -int ocsp_timeout = DEFAULT_OCSP_TIMEOUT; -int ochp_timeout = DEFAULT_OCHP_TIMEOUT; + if (!(envpath = strdup(envpath))) { + errno = ENOMEM; + return -1; + } -double sleep_time = DEFAULT_SLEEP_TIME; -int interval_length = DEFAULT_INTERVAL_LENGTH; -int service_inter_check_delay_method = ICD_SMART; -int host_inter_check_delay_method = ICD_SMART; -int service_interleave_factor_method = ILF_SMART; -int max_host_check_spread = DEFAULT_HOST_CHECK_SPREAD; -int max_service_check_spread = DEFAULT_SERVICE_CHECK_SPREAD; + for (p = envpath; p; p = colon + 1) { + char *path; -int command_check_interval = DEFAULT_COMMAND_CHECK_INTERVAL; -int check_reaper_interval = DEFAULT_CHECK_REAPER_INTERVAL; -int max_check_reaper_time = DEFAULT_MAX_REAPER_TIME; -int service_freshness_check_interval = DEFAULT_FRESHNESS_CHECK_INTERVAL; -int host_freshness_check_interval = DEFAULT_FRESHNESS_CHECK_INTERVAL; -int auto_rescheduling_interval = DEFAULT_AUTO_RESCHEDULING_INTERVAL; + colon = strchr(p, ':'); + if (colon) + *colon = 0; + asprintf(&path, "%s/%s", p, program); + ret = access(path, mode); + free(path); + if (!ret) + break; -int check_external_commands = DEFAULT_CHECK_EXTERNAL_COMMANDS; -int check_orphaned_services = DEFAULT_CHECK_ORPHANED_SERVICES; -int check_orphaned_hosts = DEFAULT_CHECK_ORPHANED_HOSTS; -int check_service_freshness = DEFAULT_CHECK_SERVICE_FRESHNESS; -int check_host_freshness = DEFAULT_CHECK_HOST_FRESHNESS; -int auto_reschedule_checks = DEFAULT_AUTO_RESCHEDULE_CHECKS; -int auto_rescheduling_window = DEFAULT_AUTO_RESCHEDULING_WINDOW; + if (ret < 0) { + if (errno == ENOENT) + continue; + if (our_errno > errno) + our_errno = errno; + } + if (!colon) + break; + } -int additional_freshness_latency = DEFAULT_ADDITIONAL_FRESHNESS_LATENCY; + free(envpath); -int check_for_updates = DEFAULT_CHECK_FOR_UPDATES; -int bare_update_check = DEFAULT_BARE_UPDATE_CHECK; -time_t last_update_check = 0L; -unsigned long update_uid = 0L; -int update_available = FALSE; -char *last_program_version = NULL; -char *new_program_version = NULL; + if (!ret) + errno = 0; + else + errno = our_errno; -time_t last_command_check = 0L; -time_t last_command_status_update = 0L; -time_t last_log_rotation = 0L; -time_t last_program_stop = 0L; + return ret; +} -int use_aggressive_host_checking = DEFAULT_AGGRESSIVE_HOST_CHECKING; -unsigned long cached_host_check_horizon = DEFAULT_CACHED_HOST_CHECK_HORIZON; -unsigned long cached_service_check_horizon = DEFAULT_CACHED_SERVICE_CHECK_HORIZON; -int enable_predictive_host_dependency_checks = DEFAULT_ENABLE_PREDICTIVE_HOST_DEPENDENCY_CHECKS; -int enable_predictive_service_dependency_checks = DEFAULT_ENABLE_PREDICTIVE_SERVICE_DEPENDENCY_CHECKS; +static int nagios_core_worker(const char *path) +{ + int sd, ret; + char response[128]; -int soft_state_dependencies = FALSE; + is_worker = 1; -int retain_state_information = FALSE; -int retention_update_interval = DEFAULT_RETENTION_UPDATE_INTERVAL; -int use_retained_program_state = TRUE; -int use_retained_scheduling_info = FALSE; -int retention_scheduling_horizon = DEFAULT_RETENTION_SCHEDULING_HORIZON; -unsigned long modified_host_process_attributes = MODATTR_NONE; -unsigned long modified_service_process_attributes = MODATTR_NONE; -unsigned long retained_host_attribute_mask = 0L; -unsigned long retained_service_attribute_mask = 0L; -unsigned long retained_contact_host_attribute_mask = 0L; -unsigned long retained_contact_service_attribute_mask = 0L; -unsigned long retained_process_host_attribute_mask = 0L; -unsigned long retained_process_service_attribute_mask = 0L; + set_loadctl_defaults(); -unsigned long next_comment_id = 0L; -unsigned long next_downtime_id = 0L; -unsigned long next_event_id = 0L; -unsigned long next_problem_id = 0L; -unsigned long next_notification_id = 0L; + sd = nsock_unix(path, NSOCK_TCP | NSOCK_CONNECT); + if (sd < 0) { + printf("Failed to connect to query socket '%s': %s: %s\n", + path, nsock_strerror(sd), strerror(errno)); + return 1; + } -int log_rotation_method = LOG_ROTATION_NONE; + ret = nsock_printf_nul(sd, "@wproc register name=Core Worker %ld;pid=%ld", (long)getpid(), (long)getpid()); + if (ret < 0) { + printf("Failed to register as worker.\n"); + return 1; + } -int sigshutdown = FALSE; -int sigrestart = FALSE; -char *sigs[35] = {"EXIT", "HUP", "INT", "QUIT", "ILL", "TRAP", "ABRT", "BUS", "FPE", "KILL", "USR1", "SEGV", "USR2", "PIPE", "ALRM", "TERM", "STKFLT", "CHLD", "CONT", "STOP", "TSTP", "TTIN", "TTOU", "URG", "XCPU", "XFSZ", "VTALRM", "PROF", "WINCH", "IO", "PWR", "UNUSED", "ZERR", "DEBUG", (char *)NULL}; -int caught_signal = FALSE; -int sig_id = 0; + ret = read(sd, response, 3); + if (ret != 3) { + printf("Failed to read response from wproc manager\n"); + return 1; + } + if (memcmp(response, "OK", 3)) { + read(sd, response + 3, sizeof(response) - 4); + response[sizeof(response) - 2] = 0; + printf("Failed to register with wproc manager: %s\n", response); + return 1; + } -int restarting = FALSE; + enter_worker(sd, start_cmd); + return 0; +} -int verify_config = FALSE; -int verify_object_relationships = TRUE; -int verify_circular_paths = TRUE; -int test_scheduling = FALSE; -int precache_objects = FALSE; -int use_precached_objects = FALSE; +/* + * only handles logfile for now, which we stash in macros to + * make sure we can log *somewhere* in case the new path is + * completely inaccessible. + */ +static int test_configured_paths(void) +{ + FILE *fp; + nagios_macros *mac; -int daemon_mode = FALSE; -int daemon_dumps_core = TRUE; + mac = get_global_macros(); -int max_parallel_service_checks = DEFAULT_MAX_PARALLEL_SERVICE_CHECKS; -int currently_running_service_checks = 0; -int currently_running_host_checks = 0; + fp = fopen(log_file, "a+"); + if (!fp) { + /* + * we do some variable trashing here so logit() can + * open the old logfile (if any), in case we got a + * restart command or a SIGHUP + */ + char *value_absolute = log_file; + log_file = mac->x[MACRO_LOGFILE]; + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Failed to open logfile '%s' for writing: %s\n", value_absolute, strerror(errno)); + return ERROR; + } -time_t program_start = 0L; -time_t event_start = 0L; -int nagios_pid = 0; -int enable_notifications = TRUE; -int execute_service_checks = TRUE; -int accept_passive_service_checks = TRUE; -int execute_host_checks = TRUE; -int accept_passive_host_checks = TRUE; -int enable_event_handlers = TRUE; -int obsess_over_services = FALSE; -int obsess_over_hosts = FALSE; -int enable_failure_prediction = TRUE; + fclose(fp); -int translate_passive_host_checks = DEFAULT_TRANSLATE_PASSIVE_HOST_CHECKS; -int passive_host_checks_are_soft = DEFAULT_PASSIVE_HOST_CHECKS_SOFT; + /* save the macro */ + mac->x[MACRO_LOGFILE] = log_file; + return OK; +} -int aggregate_status_updates = TRUE; -int status_update_interval = DEFAULT_STATUS_UPDATE_INTERVAL; - -int time_change_threshold = DEFAULT_TIME_CHANGE_THRESHOLD; - -unsigned long event_broker_options = BROKER_NOTHING; - -int process_performance_data = DEFAULT_PROCESS_PERFORMANCE_DATA; - -int enable_flap_detection = DEFAULT_ENABLE_FLAP_DETECTION; - -double low_service_flap_threshold = DEFAULT_LOW_SERVICE_FLAP_THRESHOLD; -double high_service_flap_threshold = DEFAULT_HIGH_SERVICE_FLAP_THRESHOLD; -double low_host_flap_threshold = DEFAULT_LOW_HOST_FLAP_THRESHOLD; -double high_host_flap_threshold = DEFAULT_HIGH_HOST_FLAP_THRESHOLD; - -int use_large_installation_tweaks = DEFAULT_USE_LARGE_INSTALLATION_TWEAKS; -int enable_environment_macros = TRUE; -int free_child_process_memory = -1; -int child_processes_fork_twice = -1; - -int enable_embedded_perl = DEFAULT_ENABLE_EMBEDDED_PERL; -int use_embedded_perl_implicitly = DEFAULT_USE_EMBEDDED_PERL_IMPLICITLY; -int embedded_perl_initialized = FALSE; - -int date_format = DATE_FORMAT_US; -char *use_timezone = NULL; - -int allow_empty_hostgroup_assignment = DEFAULT_ALLOW_EMPTY_HOSTGROUP_ASSIGNMENT; - -int command_file_fd; -FILE *command_file_fp; -int command_file_created = FALSE; - - -extern contact *contact_list; -extern contactgroup *contactgroup_list; -extern hostgroup *hostgroup_list; -extern command *command_list; -extern timeperiod *timeperiod_list; -extern serviceescalation *serviceescalation_list; - -notification *notification_list; - -check_result check_result_info; -check_result *check_result_list = NULL; -unsigned long max_check_result_file_age = DEFAULT_MAX_CHECK_RESULT_AGE; - -dbuf check_result_dbuf; - -circular_buffer external_command_buffer; -circular_buffer check_result_buffer; -pthread_t worker_threads[TOTAL_WORKER_THREADS]; -int external_command_buffer_slots = DEFAULT_EXTERNAL_COMMAND_BUFFER_SLOTS; - -check_stats check_statistics[MAX_CHECK_STATS_TYPES]; - -char *debug_file; -int debug_level = DEFAULT_DEBUG_LEVEL; -int debug_verbosity = DEFAULT_DEBUG_VERBOSITY; -unsigned long max_debug_file_size = DEFAULT_MAX_DEBUG_FILE_SIZE; - - - - -/* Following main() declaration required by older versions of Perl ut 5.00503 */ -int main(int argc, char **argv, char **env) { +int main(int argc, char **argv) { int result; int error = FALSE; - char *buffer = NULL; int display_license = FALSE; int display_help = FALSE; int c = 0; @@ -288,10 +225,11 @@ int main(int argc, char **argv, char **env) { time_t now; char datestring[256]; nagios_macros *mac; - - mac = get_global_macros(); - - + const char *worker_socket = NULL; + int i; +#ifdef HAVE_SIGACTION + struct sigaction sig_action; +#endif #ifdef HAVE_GETOPT_H int option_index = 0; @@ -302,27 +240,25 @@ int main(int argc, char **argv, char **env) { {"verify-config", no_argument, 0, 'v'}, {"daemon", no_argument, 0, 'd'}, {"test-scheduling", no_argument, 0, 's'}, - {"dont-verify-objects", no_argument, 0, 'o'}, - {"dont-verify-paths", no_argument, 0, 'x'}, {"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'}, {0, 0, 0, 0} }; +#define getopt(argc, argv, o) getopt_long(argc, argv, o, long_options, &option_index) #endif + memset(&loadctl, 0, sizeof(loadctl)); + mac = get_global_macros(); + /* make sure we have the correct number of command line arguments */ if(argc < 2) error = TRUE; - /* get all command line arguments */ while(1) { - -#ifdef HAVE_GETOPT_H - c = getopt_long(argc, argv, "+hVvdsoxpu", long_options, &option_index); -#else - c = getopt(argc, argv, "+hVvdsoxpu"); -#endif + c = getopt(argc, argv, "+hVvdspuxTW"); if(c == -1 || c == EOF) break; @@ -339,7 +275,7 @@ int main(int argc, char **argv, char **env) { break; case 'v': /* verify */ - verify_config = TRUE; + verify_config++; break; case 's': /* scheduling check */ @@ -350,16 +286,6 @@ int main(int argc, char **argv, char **env) { daemon_mode = TRUE; break; - case 'o': /* don't verify objects */ - /* - verify_object_relationships=FALSE; - */ - break; - - case 'x': /* don't verify circular paths */ - verify_circular_paths = FALSE; - break; - case 'p': /* precache object config */ precache_objects = TRUE; break; @@ -367,6 +293,16 @@ int main(int argc, char **argv, char **env) { 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 'x': + printf("Warning: -x is deprecated and will be removed\n"); + break; default: break; @@ -374,23 +310,25 @@ int main(int argc, char **argv, char **env) { } - /* make sure we have the right combination of arguments */ - if(precache_objects == TRUE && (test_scheduling == FALSE && verify_config == FALSE)) { - error = TRUE; - display_help = TRUE; - } - #ifdef DEBUG_MEMORY mtrace(); #endif + /* if we're a worker we can skip everything below */ + if(worker_socket) { + exit(nagios_core_worker(worker_socket)); + } + + /* Initialize configuration variables */ + init_main_cfg_vars(1); + init_shared_cfg_vars(1); if(daemon_mode == FALSE) { printf("\nNagios Core %s\n", PROGRAM_VERSION); - printf("Copyright (c) 2009-2011 Nagios Core Development Team and Community Contributors\n"); + printf("Copyright (c) 2009-present Nagios Core Development Team and Community Contributors\n"); printf("Copyright (c) 1999-2009 Ethan Galstad\n"); printf("Last Modified: %s\n", PROGRAM_MODIFICATION_DATE); printf("License: GPL\n\n"); - printf("Website: http://www.nagios.org\n"); + printf("Website: https://www.nagios.org\n"); } /* just display the license */ @@ -421,16 +359,17 @@ int main(int argc, char **argv, char **env) { printf("\n"); printf("Options:\n"); printf("\n"); - printf(" -v, --verify-config Verify all configuration data\n"); + printf(" -v, --verify-config Verify all configuration data (-v -v for more info)\n"); printf(" -s, --test-scheduling Shows projected/recommended check scheduling and other\n"); printf(" diagnostic info based on the current configuration files.\n"); - /*printf(" -o, --dont-verify-objects Don't verify object relationships - USE WITH CAUTION!\n");*/ - printf(" -x, --dont-verify-paths Don't check for circular object paths - USE WITH CAUTION!\n"); - printf(" -p, --precache-objects Precache object configuration - use with -v or -s options\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 Nagios 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("\n"); - printf("Visit the Nagios website at http://www.nagios.org/ for bug fixes, new\n"); + printf("Visit the Nagios website at https://www.nagios.org/ for bug fixes, new\n"); printf("releases, online documentation, FAQs, information on subscribing to\n"); printf("the mailing lists, and commercial support options for Nagios.\n"); printf("\n"); @@ -438,201 +377,166 @@ int main(int argc, char **argv, char **env) { exit(ERROR); } - /* - * Set the signal handler for the SIGXFSZ signal here because - * we may encounter this signal before the other signal handlers - * are set. - */ - signal(SIGXFSZ, handle_sigxfsz); - /* config file is last argument specified */ - config_file = (char *)strdup(argv[optind]); + /* + * 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); } - /* make sure the config file uses an absolute path */ - if(config_file[0] != '/') { + config_file_dir = nspath_absolute_dirname(config_file, NULL); - /* save the name of the config file */ - buffer = (char *)strdup(config_file); + /* + * Set the signal handler for the SIGXFSZ signal here because + * we may encounter this signal before the other signal handlers + * are set. + */ +#ifdef HAVE_SIGACTION + sig_action.sa_sigaction = NULL; + sig_action.sa_handler = handle_sigxfsz; + sigfillset(&sig_action.sa_mask); + sig_action.sa_flags = SA_NODEFER|SA_RESTART; + sigaction(SIGXFSZ, &sig_action, NULL); +#else + signal(SIGXFSZ, handle_sigxfsz); +#endif - /* reallocate a larger chunk of memory */ - config_file = (char *)realloc(config_file, MAX_FILENAME_LENGTH); - if(config_file == NULL) { - printf("Error allocating memory.\n"); - exit(ERROR); + /* + * let's go to town. We'll be noisy if we're verifying config + * or running scheduling tests. + */ + if(verify_config || test_scheduling || precache_objects) { + reset_variables(); + /* + * if we don't beef up our resource limits as much as + * we can, it's quite possible we'll run headlong into + * EAGAIN due to too many processes when we try to + * drop privileges later. + */ + set_loadctl_defaults(); + + 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); } - /* get absolute path of current working directory */ - getcwd(config_file, MAX_FILENAME_LENGTH); - - /* append a forward slash */ - strncat(config_file, "/", 1); - config_file[MAX_FILENAME_LENGTH - 1] = '\x0'; - - /* append the config file to the path */ - strncat(config_file, buffer, MAX_FILENAME_LENGTH - strlen(config_file) - 1); - config_file[MAX_FILENAME_LENGTH - 1] = '\x0'; - - my_free(buffer); - } - - - /* we're just verifying the configuration... */ - if(verify_config == TRUE) { - - /* reset program variables */ - reset_variables(); - - printf("Reading configuration data...\n"); - - /* read in the configuration files (main config file, resource and object config files) */ - if((result = read_main_config_file(config_file)) == OK) { - + if(verify_config) printf(" Read main config file okay...\n"); - /* drop privileges */ - if((result = drop_privileges(nagios_user, nagios_group)) == ERROR) - printf(" Failed to drop privileges. Aborting."); - else { - /* read object config files */ - if((result = read_all_object_data(config_file)) == OK) - printf(" Read object config files okay...\n"); - else - printf(" Error processing object config files!\n"); - } + /* drop privileges */ + if((result = drop_privileges(nagios_user, nagios_group)) == ERROR) { + printf(" Failed to drop privileges. Aborting."); + exit(EXIT_FAILURE); } - else - printf(" Error processing main config file!\n\n"); - printf("\n"); + /* + * this must come after dropping privileges, so we make + * sure to test access permissions as the right user. + */ + if (!verify_config && test_configured_paths() == ERROR) { + printf(" One or more path problems detected. Aborting.\n"); + exit(EXIT_FAILURE); + } - /* there was a problem reading the config files */ + /* 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, "nagios.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 '/usr/local/nagios/etc/nagios.cfg'\n"); + printf(" main configuration file is typically '%s'\n", 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 defintions. If you are upgrading from a previous\n"); + printf(" directives and data definitions. If you are upgrading from a previous\n"); printf(" version of Nagios, 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); } - /* the config files were okay, so run the pre-flight check */ - else { - + 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("\nThings look okay - No serious problems were detected during the pre-flight check\n"); - else { - 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 defintions. If you are upgrading from a previous\n"); - printf(" version of Nagios, 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"); - } } - /* clean up after ourselves */ - cleanup(); + /* run the pre-flight check to make sure things look okay... */ + result = pre_flight_check(); - /* free config_file */ - my_free(config_file); + 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 Nagios, 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); + } - /* exit */ - exit(result); - } + if(verify_config) { + printf("\nThings look okay - No serious problems were detected during the pre-flight check\n"); + } + /* scheduling tests need a bit more than config verifications */ + if(test_scheduling == TRUE) { - /* we're just testing scheduling... */ - else if(test_scheduling == TRUE) { + /* we'll need the event queue here so we can time insertions */ + init_event_queue(); + timing_point("Done initializing event queue\n"); - /* reset program variables */ - reset_variables(); - - /* read in the configuration files (main config file and all host config files) */ - result = read_main_config_file(config_file); - - /* drop privileges */ - if(result == OK) - if((result = drop_privileges(nagios_user, nagios_group)) == ERROR) - printf("Failed to drop privileges. Aborting."); - - /* read object config files */ - if(result == OK) - result = read_all_object_data(config_file); - - /* read initial service and host state information */ - if(result == OK) { + /* read initial service and host state information */ initialize_retention_data(config_file); read_initial_state_information(); - } - - if(result != OK) - printf("***> One or more problems was encountered while reading configuration data...\n"); - - /* run the pre-flight check to make sure everything looks okay */ - if(result == OK) { - if((result = pre_flight_check()) != OK) - printf("***> One or more problems was encountered while running the pre-flight check...\n"); - } - - if(result == OK) { + timing_point("Retention data and initial state parsed\n"); /* initialize the event timing loop */ init_timing_loop(); + timing_point("Timing loop initialized\n"); /* display scheduling information */ display_scheduling_info(); - - if(precache_objects == TRUE) { - printf("\n"); - printf("OBJECT PRECACHING\n"); - printf("-----------------\n"); - printf("Object config files were precached.\n"); - } } -#undef TEST_TIMEPERIODS -#ifdef TEST_TIMEPERIODS - /* DO SOME TIMEPERIOD TESTING - ADDED 08/11/2009 */ - time_t now, pref_time, valid_time; - timeperiod *tp; - tp = find_timeperiod("247_exclusion"); - time(&now); - pref_time = now; - get_next_valid_time(pref_time, &valid_time, tp); - printf("=====\n"); - printf("CURRENT: %lu = %s", (unsigned long)now, ctime(&now)); - printf("PREFERRED: %lu = %s", (unsigned long)pref_time, ctime(&pref_time)); - printf("NEXT: %lu = %s", (unsigned long)valid_time, ctime(&valid_time)); - printf("=====\n"); -#endif + 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); } @@ -640,26 +544,54 @@ int main(int argc, char **argv, char **env) { /* else start to monitor things... */ else { + /* + * 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], '/')) + nagios_binary_path = nspath_absolute(argv[0], NULL); + else + nagios_binary_path = strdup(argv[0]); + + if (!nagios_binary_path) { + logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Unable to allocate memory for nagios_binary_path\n"); + exit(EXIT_FAILURE); + } + + if (!(nagios_iobs = iobroker_create())) { + logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Failed to create IO broker set: %s\n", + strerror(errno)); + exit(EXIT_FAILURE); + } + /* keep monitoring things until we get a shutdown command */ do { + /* reset internal book-keeping (in case we're restarting) */ + wproc_num_workers_spawned = wproc_num_workers_online = 0; + caught_signal = sigshutdown = FALSE; + sig_id = 0; /* reset program variables */ reset_variables(); + timing_point("Variables reset\n"); /* get PID */ nagios_pid = (int)getpid(); /* read in the configuration files (main and resource config files) */ result = read_main_config_file(config_file); + if (result != OK) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Failed to process config file '%s'. Aborting\n", config_file); + exit(EXIT_FAILURE); + } + timing_point("Main config file read\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); my_free(mac->x[MACRO_PROCESSSTARTTIME]); - asprintf(&mac->x[MACRO_PROCESSSTARTTIME], "%lu", (unsigned long)program_start); - - /* open debug log */ - open_debug_log(); + asprintf(&mac->x[MACRO_PROCESSSTARTTIME], "%llu", (unsigned long long)program_start); /* drop privileges */ if(drop_privileges(nagios_user, nagios_group) == ERROR) { @@ -670,11 +602,31 @@ int main(int argc, char **argv, char **env) { exit(ERROR); } -#ifdef USE_EVENT_BROKER - /* initialize modules */ - neb_init_modules(); - neb_init_callback_list(); -#endif + if (test_path_access(nagios_binary_path, X_OK)) { + logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: failed to access() %s: %s\n", nagios_binary_path, strerror(errno)); + logit(NSLOG_RUNTIME_ERROR, TRUE, "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) { + logit(NSLOG_PROCESS_INFO | NSLOG_RUNTIME_ERROR, TRUE, "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 */ logit(NSLOG_PROCESS_INFO, TRUE, "Nagios %s starting... (PID=%d)\n", PROGRAM_VERSION, (int)getpid()); @@ -688,12 +640,62 @@ int main(int argc, char **argv, char **env) { /* write log version/info */ write_log_file_info(NULL); + /* open debug log now that we're the right user */ + open_debug_log(); + +#ifdef USE_EVENT_BROKER + /* initialize modules */ + neb_init_modules(); + neb_init_callback_list(); +#endif + timing_point("NEB module API initialized\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 + */ + if (qh_init(qh_socket_path ? qh_socket_path : DEFAULT_QUERY_SOCKET) != OK) { + logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Failed to initialize query handler. Aborting\n"); + exit(EXIT_FAILURE); + } + timing_point("Query handler initialized\n"); + nerd_init(); + timing_point("NERD initialized\n"); + + /* initialize check workers */ + if(init_workers(num_check_workers) < 0) { + logit(NSLOG_RUNTIME_ERROR, TRUE, "Failed to spawn workers. Aborting\n"); + exit(EXIT_FAILURE); + } + timing_point("%u workers spawned\n", wproc_num_workers_spawned); + i = 0; + while (i < 50 && wproc_num_workers_online < wproc_num_workers_spawned) { + iobroker_poll(nagios_iobs, 50); + i++; + } + timing_point("%u workers connected\n", wproc_num_workers_online); + + /* now that workers have arrived we can set the defaults */ + set_loadctl_defaults(); + #ifdef USE_EVENT_BROKER /* load modules */ - neb_load_all_modules(); + if (neb_load_all_modules() != OK) { + logit(NSLOG_CONFIG_ERROR, ERROR, "Error: Module loading failed. Aborting.\n"); + /* if we're dumping core, we must remove all dl-files */ + if (daemon_dumps_core) + neb_unload_all_modules(NEBMODULE_FORCE_UNLOAD, NEBMODULE_NEB_SHUTDOWN); + exit(EXIT_FAILURE); + } + timing_point("Modules loaded\n"); /* send program data to broker */ broker_program_state(NEBTYPE_PROCESS_PRELAUNCH, NEBFLAG_NONE, NEBATTR_NONE, NULL); + timing_point("First callback made\n"); #endif /* read in all object config data */ @@ -718,17 +720,7 @@ int main(int argc, char **argv, char **env) { if(sigrestart == TRUE) { /* clean up the status data */ - cleanup_status_data(config_file, TRUE); - - /* shutdown the external command worker thread */ - shutdown_command_file_worker_thread(); - - /* close and delete the external command file FIFO */ - close_command_file(); - - /* cleanup embedded perl interpreter */ - if(embedded_perl_initialized == TRUE) - deinit_embedded_perl(); + cleanup_status_data(TRUE); } #ifdef USE_EVENT_BROKER @@ -739,24 +731,14 @@ int main(int argc, char **argv, char **env) { exit(ERROR); } + timing_point("Object configuration parsed and understood\n"); + /* write the objects.cache file */ + fcache_objects(object_cache_file); + timing_point("Objects cached\n"); - /* initialize embedded Perl interpreter */ - /* NOTE 02/15/08 embedded Perl must be initialized if compiled in, regardless of whether or not its enabled in the config file */ - /* It compiled it, but not initialized, Nagios will segfault in readdir() calls, as libperl takes this function over */ - if(embedded_perl_initialized == FALSE) { - /* if(enable_embedded_perl==TRUE){*/ -#ifdef EMBEDDEDPERL - init_embedded_perl(env); -#else - init_embedded_perl(NULL); -#endif - embedded_perl_initialized = TRUE; - /* }*/ - } - - /* handle signals (interrupts) */ - setup_sighandler(); + init_event_queue(); + timing_point("Event queue initialized\n"); #ifdef USE_EVENT_BROKER @@ -764,85 +746,58 @@ int main(int argc, char **argv, char **env) { broker_program_state(NEBTYPE_PROCESS_START, NEBFLAG_NONE, NEBATTR_NONE, NULL); #endif - /* 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) { - logit(NSLOG_PROCESS_INFO | NSLOG_RUNTIME_ERROR, TRUE, "Bailing out due to failure to daemonize. (PID=%d)", (int)getpid()); - -#ifdef USE_EVENT_BROKER - /* send program data to broker */ - broker_program_state(NEBTYPE_PROCESS_SHUTDOWN, NEBFLAG_PROCESS_INITIATED, NEBATTR_SHUTDOWN_ABNORMAL, NULL); -#endif - cleanup(); - exit(ERROR); - } - - asprintf(&buffer, "Finished daemonizing... (New PID=%d)\n", (int)getpid()); - write_to_all_logs(buffer, NSLOG_PROCESS_INFO); - my_free(buffer); - - /* get new PID */ - nagios_pid = (int)getpid(); - } - - /* open the command file (named pipe) for reading */ - result = open_command_file(); - if(result != OK) { - - logit(NSLOG_PROCESS_INFO | NSLOG_RUNTIME_ERROR, TRUE, "Bailing out due to errors encountered while trying to initialize the external command file... (PID=%d)\n", (int)getpid()); - -#ifdef USE_EVENT_BROKER - /* send program data to broker */ - broker_program_state(NEBTYPE_PROCESS_SHUTDOWN, NEBFLAG_PROCESS_INITIATED, NEBATTR_SHUTDOWN_ABNORMAL, NULL); -#endif - cleanup(); - exit(ERROR); - } - /* initialize status data unless we're starting */ - if(sigrestart == FALSE) + if(sigrestart == FALSE) { initialize_status_data(config_file); + timing_point("Status data initialized\n"); + } + + /* initialize scheduled downtime data */ + initialize_downtime_data(); + timing_point("Downtime data initialized\n"); /* read initial service and host state information */ initialize_retention_data(config_file); + timing_point("Retention data initialized\n"); read_initial_state_information(); + timing_point("Initial state information read\n"); /* initialize comment data */ - initialize_comment_data(config_file); - - /* initialize scheduled downtime data */ - initialize_downtime_data(config_file); + initialize_comment_data(); + timing_point("Comment data initialized\n"); /* initialize performance data */ initialize_performance_data(config_file); - - /* Determine which checks are still executing so they are not - scheduled when the timing loop is initialized */ - find_executing_checks(check_result_path); + timing_point("Performance data initialized\n"); /* initialize the event timing loop */ init_timing_loop(); + timing_point("Event timing loop initialized\n"); /* initialize check statistics */ init_check_stats(); + timing_point("check stats initialized\n"); /* check for updates */ check_for_nagios_updates(FALSE, TRUE); + timing_point("Update check concluded\n"); /* update all status data (with retained information) */ update_all_status_data(); + timing_point("Status data updated\n"); /* log initial host and service state */ log_host_states(INITIAL_STATES, NULL); log_service_states(INITIAL_STATES, NULL); + timing_point("Initial states logged\n"); /* reset the restart flag */ sigrestart = FALSE; + /* fire up command file worker */ + launch_command_file_worker(); + timing_point("Command file worker launched\n"); + #ifdef USE_EVENT_BROKER /* send program data to broker */ broker_program_state(NEBTYPE_PROCESS_EVENTLOOPSTART, NEBFLAG_NONE, NEBATTR_NONE, NULL); @@ -851,24 +806,27 @@ int main(int argc, char **argv, char **env) { /* get event start time and save as macro */ event_start = time(NULL); my_free(mac->x[MACRO_EVENTSTARTTIME]); - asprintf(&mac->x[MACRO_EVENTSTARTTIME], "%lu", (unsigned long)event_start); + asprintf(&mac->x[MACRO_EVENTSTARTTIME], "%llu", (unsigned long long)event_start); + timing_point("Entering event execution loop\n"); /***** start monitoring all services *****/ /* (doesn't return until a restart or shutdown signal is encountered) */ event_execution_loop(); + /* + * immediately deinitialize the query handler so it + * can remove modules that have stashed data with it + */ + qh_deinit(qh_socket_path ? qh_socket_path : DEFAULT_QUERY_SOCKET); + /* 03/01/2007 EG Moved from sighandler() to prevent FUTEX locking problems under NPTL */ /* 03/21/2007 EG SIGSEGV signals are still logged in sighandler() so we don't loose them */ /* did we catch a signal? */ if(caught_signal == TRUE) { if(sig_id == SIGHUP) - asprintf(&buffer, "Caught SIGHUP, restarting...\n"); - else if(sig_id != SIGSEGV) - asprintf(&buffer, "Caught SIG%s, shutting down...\n", sigs[sig_id]); + logit(NSLOG_PROCESS_INFO, TRUE, "Caught SIGHUP, restarting...\n"); - write_to_all_logs(buffer, NSLOG_PROCESS_INFO); - my_free(buffer); } #ifdef USE_EVENT_BROKER @@ -882,37 +840,24 @@ int main(int argc, char **argv, char **env) { /* save service and host state information */ save_state_information(FALSE); - cleanup_retention_data(config_file); + cleanup_retention_data(); /* clean up performance data */ - cleanup_performance_data(config_file); + cleanup_performance_data(); /* clean up the scheduled downtime data */ - cleanup_downtime_data(config_file); - - /* clean up the comment data */ - cleanup_comment_data(config_file); + cleanup_downtime_data(); /* clean up the status data unless we're restarting */ - if(sigrestart == FALSE) - cleanup_status_data(config_file, TRUE); - - /* close and delete the external command file FIFO unless we're restarting */ if(sigrestart == FALSE) { - shutdown_command_file_worker_thread(); - close_command_file(); + cleanup_status_data(TRUE); } - /* cleanup embedded perl interpreter */ - if(sigrestart == FALSE) - deinit_embedded_perl(); - + free_worker_memory(WPROC_FORCE); /* shutdown stuff... */ if(sigshutdown == TRUE) { - - /* make sure lock file has been removed - it may not have been if we received a shutdown command */ - if(daemon_mode == TRUE) - unlink(lock_file); + iobroker_destroy(nagios_iobs, IOBROKER_CLOSE_SOCKETS); + nagios_iobs = NULL; /* log a shutdown message */ logit(NSLOG_PROCESS_INFO, TRUE, "Successfully shutdown... (PID=%d)\n", (int)getpid()); @@ -927,11 +872,15 @@ int main(int argc, char **argv, char **env) { } while(sigrestart == TRUE && sigshutdown == FALSE); + if(daemon_mode == TRUE) + unlink(lock_file); + /* free misc memory */ + my_free(lock_file); my_free(config_file); + my_free(config_file_dir); + my_free(nagios_binary_path); } return OK; } - - diff --git a/base/nagiostats.c b/base/nagiostats.c index e235ef7..a5ea994 100644 --- a/base/nagiostats.c +++ b/base/nagiostats.c @@ -3,11 +3,7 @@ * NAGIOSTATS.C - Displays Nagios Statistics * * Program: Nagiostats - * Version: 3.5.1 * License: GPL - * Copyright (c) 2003-2008 Ethan Galstad (egalstad@nagios.org) - * - * Last Modified: 12-20-2008 * * License: * @@ -26,6 +22,7 @@ * *****************************************************************************/ +#include "../lib/libnagios.h" #include "../include/config.h" #include "../include/common.h" #include "../include/nagios.h" @@ -38,175 +35,165 @@ #define STATUS_SERVICE_DATA 4 -char *main_config_file = NULL; +static char *main_config_file = NULL; char *status_file = NULL; -char *nagiostats_file = NULL; -char *mrtg_variables = NULL; -char *mrtg_delimiter = "\n"; +static char *mrtg_variables = NULL; +static const char *mrtg_delimiter = "\n"; -int mrtg_mode = FALSE; +static int mrtg_mode = FALSE; -time_t status_creation_date = 0L; -char *status_version = NULL; +static time_t status_creation_date = 0L; +static char *status_version = NULL; time_t program_start = 0L; -int status_service_entries = 0; -int status_host_entries = 0; -unsigned long nagios_pid = 0L; +static int status_service_entries = 0; +static int status_host_entries = 0; +int nagios_pid = 0; -double min_service_state_change = 0.0; -int have_min_service_state_change = FALSE; -double max_service_state_change = 0.0; -int have_max_service_state_change = FALSE; -double average_service_state_change = 0.0; -double min_active_service_state_change = 0.0; -int have_min_active_service_state_change = FALSE; -double max_active_service_state_change = 0.0; -int have_max_active_service_state_change = FALSE; -double average_active_service_state_change = 0.0; -double min_active_service_latency = 0.0; -int have_min_active_service_latency = FALSE; -double max_active_service_latency = 0.0; -int have_max_active_service_latency = FALSE; -double average_active_service_latency = 0.0; -double min_active_service_execution_time = 0.0; -int have_min_active_service_execution_time = FALSE; -double max_active_service_execution_time = 0.0; -int have_max_active_service_execution_time = FALSE; -double average_active_service_execution_time = 0.0; -double min_passive_service_state_change = 0.0; -int have_min_passive_service_state_change = FALSE; -double max_passive_service_state_change = 0.0; -int have_max_passive_service_state_change = FALSE; -double average_passive_service_state_change = 0.0; -double min_passive_service_latency = 0.0; -int have_min_passive_service_latency = FALSE; -double max_passive_service_latency = 0.0; -int have_max_passive_service_latency = FALSE; -double average_passive_service_latency = 0.0; +static double min_service_state_change = 0.0; +static int have_min_service_state_change = FALSE; +static double max_service_state_change = 0.0; +static int have_max_service_state_change = FALSE; +static double average_service_state_change = 0.0; +static double min_active_service_state_change = 0.0; +static int have_min_active_service_state_change = FALSE; +static double max_active_service_state_change = 0.0; +static int have_max_active_service_state_change = FALSE; +static double average_active_service_state_change = 0.0; +static double min_active_service_latency = 0.0; +static int have_min_active_service_latency = FALSE; +static double max_active_service_latency = 0.0; +static int have_max_active_service_latency = FALSE; +static double average_active_service_latency = 0.0; +static double min_active_service_execution_time = 0.0; +static int have_min_active_service_execution_time = FALSE; +static double max_active_service_execution_time = 0.0; +static int have_max_active_service_execution_time = FALSE; +static double average_active_service_execution_time = 0.0; +static double min_passive_service_state_change = 0.0; +static int have_min_passive_service_state_change = FALSE; +static double max_passive_service_state_change = 0.0; +static int have_max_passive_service_state_change = FALSE; +static double average_passive_service_state_change = 0.0; +static double min_passive_service_latency = 0.0; +static int have_min_passive_service_latency = FALSE; +static double max_passive_service_latency = 0.0; +static int have_max_passive_service_latency = FALSE; +static double average_passive_service_latency = 0.0; -int have_min_host_state_change = FALSE; -double min_host_state_change = 0.0; -int have_max_host_state_change = FALSE; -double max_host_state_change = 0.0; -double average_host_state_change = 0.0; -int have_min_active_host_state_change = FALSE; -double min_active_host_state_change = 0.0; -int have_max_active_host_state_change = FALSE; -double max_active_host_state_change = 0.0; -double average_active_host_state_change = 0.0; -int have_min_active_host_latency = FALSE; -double min_active_host_latency = 0.0; -int have_max_active_host_latency = FALSE; -double max_active_host_latency = 0.0; -double average_active_host_latency = 0.0; -int have_min_active_host_execution_time = FALSE; -double min_active_host_execution_time = 0.0; -int have_max_active_host_execution_time = FALSE; -double max_active_host_execution_time = 0.0; -double average_active_host_execution_time = 0.0; -int have_min_passive_host_latency = FALSE; -double min_passive_host_latency = 0.0; -int have_max_passive_host_latency = FALSE; -double max_passive_host_latency = 0.0; -double average_passive_host_latency = 0.0; -double min_passive_host_state_change = 0.0; -int have_min_passive_host_state_change = FALSE; -double max_passive_host_state_change = 0.0; -int have_max_passive_host_state_change = FALSE; -double average_passive_host_state_change = 0.0; +static int have_min_host_state_change = FALSE; +static double min_host_state_change = 0.0; +static int have_max_host_state_change = FALSE; +static double max_host_state_change = 0.0; +static double average_host_state_change = 0.0; +static int have_min_active_host_state_change = FALSE; +static double min_active_host_state_change = 0.0; +static int have_max_active_host_state_change = FALSE; +static double max_active_host_state_change = 0.0; +static double average_active_host_state_change = 0.0; +static int have_min_active_host_latency = FALSE; +static double min_active_host_latency = 0.0; +static int have_max_active_host_latency = FALSE; +static double max_active_host_latency = 0.0; +static double average_active_host_latency = 0.0; +static int have_min_active_host_execution_time = FALSE; +static double min_active_host_execution_time = 0.0; +static int have_max_active_host_execution_time = FALSE; +static double max_active_host_execution_time = 0.0; +static double average_active_host_execution_time = 0.0; +static int have_min_passive_host_latency = FALSE; +static double min_passive_host_latency = 0.0; +static int have_max_passive_host_latency = FALSE; +static double max_passive_host_latency = 0.0; +static double average_passive_host_latency = 0.0; +static double min_passive_host_state_change = 0.0; +static int have_min_passive_host_state_change = FALSE; +static double max_passive_host_state_change = 0.0; +static int have_max_passive_host_state_change = FALSE; +static double average_passive_host_state_change = 0.0; -int passive_service_checks = 0; -int active_service_checks = 0; -int services_ok = 0; -int services_warning = 0; -int services_unknown = 0; -int services_critical = 0; -int services_flapping = 0; -int services_in_downtime = 0; -int services_checked = 0; -int services_scheduled = 0; -int passive_host_checks = 0; -int active_host_checks = 0; -int hosts_up = 0; -int hosts_down = 0; -int hosts_unreachable = 0; -int hosts_flapping = 0; -int hosts_in_downtime = 0; -int hosts_checked = 0; -int hosts_scheduled = 0; +static int passive_service_checks = 0; +static int active_service_checks = 0; +static int services_ok = 0; +static int services_warning = 0; +static int services_unknown = 0; +static int services_critical = 0; +static int services_flapping = 0; +static int services_in_downtime = 0; +static int services_checked = 0; +static int services_scheduled = 0; +static int passive_host_checks = 0; +static int active_host_checks = 0; +static int hosts_up = 0; +static int hosts_down = 0; +static int hosts_unreachable = 0; +static int hosts_flapping = 0; +static int hosts_in_downtime = 0; +static int hosts_checked = 0; +static int hosts_scheduled = 0; -int passive_services_checked_last_1min = 0; -int passive_services_checked_last_5min = 0; -int passive_services_checked_last_15min = 0; -int passive_services_checked_last_1hour = 0; -int active_services_checked_last_1min = 0; -int active_services_checked_last_5min = 0; -int active_services_checked_last_15min = 0; -int active_services_checked_last_1hour = 0; -int passive_hosts_checked_last_1min = 0; -int passive_hosts_checked_last_5min = 0; -int passive_hosts_checked_last_15min = 0; -int passive_hosts_checked_last_1hour = 0; -int active_hosts_checked_last_1min = 0; -int active_hosts_checked_last_5min = 0; -int active_hosts_checked_last_15min = 0; -int active_hosts_checked_last_1hour = 0; +static int passive_services_checked_last_1min = 0; +static int passive_services_checked_last_5min = 0; +static int passive_services_checked_last_15min = 0; +static int passive_services_checked_last_1hour = 0; +static int active_services_checked_last_1min = 0; +static int active_services_checked_last_5min = 0; +static int active_services_checked_last_15min = 0; +static int active_services_checked_last_1hour = 0; +static int passive_hosts_checked_last_1min = 0; +static int passive_hosts_checked_last_5min = 0; +static int passive_hosts_checked_last_15min = 0; +static int passive_hosts_checked_last_1hour = 0; +static int active_hosts_checked_last_1min = 0; +static int active_hosts_checked_last_5min = 0; +static int active_hosts_checked_last_15min = 0; +static int active_hosts_checked_last_1hour = 0; -int active_host_checks_last_1min = 0; -int active_host_checks_last_5min = 0; -int active_host_checks_last_15min = 0; -int active_ondemand_host_checks_last_1min = 0; -int active_ondemand_host_checks_last_5min = 0; -int active_ondemand_host_checks_last_15min = 0; -int active_scheduled_host_checks_last_1min = 0; -int active_scheduled_host_checks_last_5min = 0; -int active_scheduled_host_checks_last_15min = 0; -int passive_host_checks_last_1min = 0; -int passive_host_checks_last_5min = 0; -int passive_host_checks_last_15min = 0; -int active_cached_host_checks_last_1min = 0; -int active_cached_host_checks_last_5min = 0; -int active_cached_host_checks_last_15min = 0; -int parallel_host_checks_last_1min = 0; -int parallel_host_checks_last_5min = 0; -int parallel_host_checks_last_15min = 0; -int serial_host_checks_last_1min = 0; -int serial_host_checks_last_5min = 0; -int serial_host_checks_last_15min = 0; +static int active_host_checks_last_1min = 0; +static int active_host_checks_last_5min = 0; +static int active_host_checks_last_15min = 0; +static int active_ondemand_host_checks_last_1min = 0; +static int active_ondemand_host_checks_last_5min = 0; +static int active_ondemand_host_checks_last_15min = 0; +static int active_scheduled_host_checks_last_1min = 0; +static int active_scheduled_host_checks_last_5min = 0; +static int active_scheduled_host_checks_last_15min = 0; +static int passive_host_checks_last_1min = 0; +static int passive_host_checks_last_5min = 0; +static int passive_host_checks_last_15min = 0; +static int active_cached_host_checks_last_1min = 0; +static int active_cached_host_checks_last_5min = 0; +static int active_cached_host_checks_last_15min = 0; +static int parallel_host_checks_last_1min = 0; +static int parallel_host_checks_last_5min = 0; +static int parallel_host_checks_last_15min = 0; +static int serial_host_checks_last_1min = 0; +static int serial_host_checks_last_5min = 0; +static int serial_host_checks_last_15min = 0; -int active_service_checks_last_1min = 0; -int active_service_checks_last_5min = 0; -int active_service_checks_last_15min = 0; -int active_ondemand_service_checks_last_1min = 0; -int active_ondemand_service_checks_last_5min = 0; -int active_ondemand_service_checks_last_15min = 0; -int active_scheduled_service_checks_last_1min = 0; -int active_scheduled_service_checks_last_5min = 0; -int active_scheduled_service_checks_last_15min = 0; -int passive_service_checks_last_1min = 0; -int passive_service_checks_last_5min = 0; -int passive_service_checks_last_15min = 0; -int active_cached_service_checks_last_1min = 0; -int active_cached_service_checks_last_5min = 0; -int active_cached_service_checks_last_15min = 0; +static int active_service_checks_last_1min = 0; +static int active_service_checks_last_5min = 0; +static int active_service_checks_last_15min = 0; +static int active_ondemand_service_checks_last_1min = 0; +static int active_ondemand_service_checks_last_5min = 0; +static int active_ondemand_service_checks_last_15min = 0; +static int active_scheduled_service_checks_last_1min = 0; +static int active_scheduled_service_checks_last_5min = 0; +static int active_scheduled_service_checks_last_15min = 0; +static int passive_service_checks_last_1min = 0; +static int passive_service_checks_last_5min = 0; +static int passive_service_checks_last_15min = 0; +static int active_cached_service_checks_last_1min = 0; +static int active_cached_service_checks_last_5min = 0; +static int active_cached_service_checks_last_15min = 0; -int external_commands_last_1min = 0; -int external_commands_last_5min = 0; -int external_commands_last_15min = 0; +static int external_commands_last_1min = 0; +static int external_commands_last_5min = 0; +static int external_commands_last_15min = 0; -int total_external_command_buffer_slots = 0; -int used_external_command_buffer_slots = 0; -int high_external_command_buffer_slots = 0; - - - -int display_mrtg_values(void); -int display_stats(void); -int read_config_file(void); -int read_status_file(void); -void strip(char *); -void get_time_breakdown(unsigned long, int *, int *, int *, int *); -int read_nagiostats_file(void); +static int display_mrtg_values(void); +static int display_stats(void); +static int read_config_file(void); +static int read_status_file(void); int main(int argc, char **argv) { @@ -219,30 +206,26 @@ int main(int argc, char **argv) { #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, 'L'}, - {"config", required_argument, 0, 'c'}, - {"statsfile", required_argument, 0, 's'}, - {"mrtg", no_argument, 0, 'm'}, - {"data", required_argument, 0, 'd'}, - {"delimiter", required_argument, 0, 'D'}, - {0, 0, 0, 0} + {"help", no_argument, NULL, 'h'}, + {"version", no_argument, NULL, 'V'}, + {"license", no_argument, NULL, 'L'}, + {"config", required_argument, NULL, 'c'}, + {"statsfile", required_argument, NULL, 's'}, + {"mrtg", no_argument, NULL, 'm'}, + {"data", required_argument, NULL, 'd'}, + {"delimiter", required_argument, NULL, 'D'}, + {NULL, 0, NULL, 0} }; +#define getopt(argc, argv, OPTSTR) getopt_long(argc, argv, OPTSTR, long_options, &option_index) #endif /* defaults */ main_config_file = strdup(DEFAULT_CONFIG_FILE); - status_file = strdup(DEFAULT_STATUS_FILE); /* get all command line arguments */ while(1) { -#ifdef HAVE_GETOPT_H - c = getopt_long(argc, argv, "+hVLc:ms:d:D:", long_options, &option_index); -#else c = getopt(argc, argv, "+hVLc:ms:d:D:"); -#endif if(c == -1 || c == EOF) break; @@ -265,7 +248,7 @@ int main(int argc, char **argv) { main_config_file = strdup(optarg); break; case 's': - nagiostats_file = strdup(optarg); + status_file = strdup(optarg); break; case 'm': mrtg_mode = TRUE; @@ -280,7 +263,6 @@ int main(int argc, char **argv) { default: break; } - } if(mrtg_mode == FALSE) { @@ -324,7 +306,7 @@ int main(int argc, char **argv) { printf("\n"); printf("Output:\n"); printf(" -m, --mrtg display output in MRTG compatible format.\n"); - printf(" -d, --data=VARS comma-seperated list of variables to output in MRTG\n"); + printf(" -d, --data=VARS comma-separated list of variables to output in MRTG\n"); printf(" (or compatible) format. See possible values below.\n"); printf(" Percentages are rounded, times are in milliseconds.\n"); printf(" -D, --delimiter=C character to use as delimiter in MRTG output mode.\n"); @@ -336,7 +318,7 @@ int main(int argc, char **argv) { printf(" STATUSFILEAGE string with age of status data file.\n"); printf(" STATUSFILEAGETT string with age of status data file (time_t format).\n"); printf(" NAGIOSVERSION string with Nagios version.\n"); - printf(" NAGIOSPID pid number of Nagios deamon.\n"); + printf(" NAGIOSPID pid number of Nagios daemon.\n"); printf(" NAGIOSVERPID string with Nagios version and PID.\n"); printf(" TOTCMDBUF total number of external command buffer slots available.\n"); printf(" USEDCMDBUF number of external command buffer slots currently in use.\n"); @@ -347,7 +329,7 @@ int main(int argc, char **argv) { printf(" NUMSVCWARN number of services WARNING.\n"); printf(" NUMSVCUNKN number of services UNKNOWN.\n"); printf(" NUMSVCCRIT number of services CRITICAL.\n"); - printf(" NUMSVCPROB number of service problems (WARNING, UNKNOWN or CRITIAL).\n"); + printf(" NUMSVCPROB number of service problems (WARNING, UNKNOWN or CRITICAL).\n"); printf(" NUMSVCCHECKED number of services that have been checked since start.\n"); printf(" NUMSVCSCHEDULED number of services that are currently scheduled to be checked.\n"); printf(" NUMSVCFLAPPING number of services that are currently flapping.\n"); @@ -376,18 +358,18 @@ int main(int argc, char **argv) { printf(" xxxPSVHSTLAT MIN/MAX/AVG passive host check latency (ms).\n"); printf(" xxxPSVHSTPSC MIN/MAX/AVG passive host check %% state change.\n"); printf(" xxxHSTPSC MIN/MAX/AVG host check %% state change.\n"); - printf(" NUMACTHSTCHECKSxM number of total active host checks occuring in last 1/5/15 minutes.\n"); - printf(" NUMOACTHSTCHECKSxM number of on-demand active host checks occuring in last 1/5/15 minutes.\n"); - printf(" NUMCACHEDHSTCHECKSxM number of cached host checks occuring in last 1/5/15 minutes.\n"); - printf(" NUMSACTHSTCHECKSxM number of scheduled active host checks occuring in last 1/5/15 minutes.\n"); - printf(" NUMPARHSTCHECKSxM number of parallel host checks occuring in last 1/5/15 minutes.\n"); - printf(" NUMSERHSTCHECKSxM number of serial host checks occuring in last 1/5/15 minutes.\n"); - printf(" NUMPSVHSTCHECKSxM number of passive host checks occuring in last 1/5/15 minutes.\n"); - printf(" NUMACTSVCCHECKSxM number of total active service checks occuring in last 1/5/15 minutes.\n"); - printf(" NUMOACTSVCCHECKSxM number of on-demand active service checks occuring in last 1/5/15 minutes.\n"); - printf(" NUMCACHEDSVCCHECKSxM number of cached service checks occuring in last 1/5/15 minutes.\n"); - printf(" NUMSACTSVCCHECKSxM number of scheduled active service checks occuring in last 1/5/15 minutes.\n"); - printf(" NUMPSVSVCCHECKSxM number of passive service checks occuring in last 1/5/15 minutes.\n"); + printf(" NUMACTHSTCHECKSxM number of total active host checks occurring in last 1/5/15 minutes.\n"); + printf(" NUMOACTHSTCHECKSxM number of on-demand active host checks occurring in last 1/5/15 minutes.\n"); + printf(" NUMCACHEDHSTCHECKSxM number of cached host checks occurring in last 1/5/15 minutes.\n"); + printf(" NUMSACTHSTCHECKSxM number of scheduled active host checks occurring in last 1/5/15 minutes.\n"); + printf(" NUMPARHSTCHECKSxM number of parallel host checks occurring in last 1/5/15 minutes.\n"); + printf(" NUMSERHSTCHECKSxM number of serial host checks occurring in last 1/5/15 minutes.\n"); + printf(" NUMPSVHSTCHECKSxM number of passive host checks occurring in last 1/5/15 minutes.\n"); + printf(" NUMACTSVCCHECKSxM number of total active service checks occurring in last 1/5/15 minutes.\n"); + printf(" NUMOACTSVCCHECKSxM number of on-demand active service checks occurring in last 1/5/15 minutes.\n"); + printf(" NUMCACHEDSVCCHECKSxM number of cached service checks occurring in last 1/5/15 minutes.\n"); + printf(" NUMSACTSVCCHECKSxM number of scheduled active service checks occurring in last 1/5/15 minutes.\n"); + printf(" NUMPSVSVCCHECKSxM number of passive service checks occurring in last 1/5/15 minutes.\n"); printf(" NUMEXTCMDSxM number of external commands processed in last 1/5/15 minutes.\n"); printf("\n"); @@ -398,30 +380,21 @@ int main(int argc, char **argv) { exit(ERROR); } - /* read pre-processed stats file */ - if(nagiostats_file) { - result = read_nagiostats_file(); - if(result == ERROR && mrtg_mode == FALSE) { - printf("Error reading stats file '%s': %s\n", nagiostats_file, strerror(errno)); - return ERROR; - } - } - - /* else read the normal status file */ - else { + /* if we got no -s option, we must read the main config file */ + if (status_file == NULL) { /* read main config file */ result = read_config_file(); if(result == ERROR && mrtg_mode == FALSE) { printf("Error processing config file '%s'\n", main_config_file); return ERROR; } + } - /* read status file */ - result = read_status_file(); - if(result == ERROR && mrtg_mode == FALSE) { - printf("Error reading status file '%s': %s\n", status_file, strerror(errno)); - return ERROR; - } + /* read status file */ + result = read_status_file(); + if(result == ERROR && mrtg_mode == FALSE) { + printf("Error reading status file '%s': %s\n", status_file, strerror(errno)); + return ERROR; } /* display stats */ @@ -430,9 +403,6 @@ int main(int argc, char **argv) { else display_mrtg_values(); - if(nagiostats_file); - free(nagiostats_file); - /* Opsera patch - return based on error, because mrtg_mode was always returning OK */ if(result == ERROR) return ERROR; @@ -442,7 +412,7 @@ int main(int argc, char **argv) { -int display_mrtg_values(void) { +static int display_mrtg_values(void) { char *temp_ptr; time_t current_time; unsigned long time_difference; @@ -480,18 +450,11 @@ int display_mrtg_values(void) { else if(!strcmp(temp_ptr, "NAGIOSVERSION")) printf("%s%s", status_version, mrtg_delimiter); else if(!strcmp(temp_ptr, "NAGIOSPID")) - printf("%lu%s", nagios_pid, mrtg_delimiter); + printf("%d%s", nagios_pid, mrtg_delimiter); else if(!strcmp(temp_ptr, "NAGIOSVERPID")) - printf("Nagios %s (pid=%lu)%s", status_version, nagios_pid, mrtg_delimiter); + printf("Nagios %s (pid=%d)%s", status_version, nagios_pid, mrtg_delimiter); - else if(!strcmp(temp_ptr, "TOTCMDBUF")) - printf("%d%s", total_external_command_buffer_slots, mrtg_delimiter); - else if(!strcmp(temp_ptr, "USEDCMDBUF")) - printf("%d%s", used_external_command_buffer_slots, mrtg_delimiter); - else if(!strcmp(temp_ptr, "HIGHCMDBUF")) - printf("%d%s", high_external_command_buffer_slots, mrtg_delimiter); - else if(!strcmp(temp_ptr, "NUMSERVICES")) printf("%d%s", status_service_entries, mrtg_delimiter); else if(!strcmp(temp_ptr, "NUMHOSTS")) @@ -771,7 +734,7 @@ int display_mrtg_values(void) { } -int display_stats(void) { +static int display_stats(void) { time_t current_time; unsigned long time_difference; int days; @@ -783,7 +746,7 @@ int display_stats(void) { printf("CURRENT STATUS DATA\n"); printf("------------------------------------------------------\n"); - printf("Status File: %s\n", (nagiostats_file != NULL) ? nagiostats_file : status_file); + printf("Status File: %s\n", status_file); time_difference = (current_time - status_creation_date); get_time_breakdown(time_difference, &days, &hours, &minutes, &seconds); printf("Status File Age: %dd %dh %dm %ds\n", days, hours, minutes, seconds); @@ -792,8 +755,7 @@ int display_stats(void) { time_difference = (current_time - program_start); get_time_breakdown(time_difference, &days, &hours, &minutes, &seconds); printf("Program Running Time: %dd %dh %dm %ds\n", days, hours, minutes, seconds); - printf("Nagios PID: %lu\n", nagios_pid); - printf("Used/High/Total Command Buffers: %d / %d / %d\n", used_external_command_buffer_slots, high_external_command_buffer_slots, total_external_command_buffer_slots); + printf("Nagios PID: %d\n", nagios_pid); printf("\n"); printf("Total Services: %d\n", status_service_entries); printf("Services Checked: %d\n", services_checked); @@ -863,13 +825,19 @@ int display_stats(void) { } -int read_config_file(void) { +static int read_config_file(void) { char temp_buffer[MAX_INPUT_BUFFER]; FILE *fp; char *var; char *val; + char *main_cfg_dir = NULL; + char *slash = NULL; + main_cfg_dir = nspath_absolute(main_config_file, NULL); + if ((slash = strrchr(main_cfg_dir, '/'))) + *slash = 0; + fp = fopen(main_config_file, "r"); if(fp == NULL) return ERROR; @@ -891,7 +859,7 @@ int read_config_file(void) { if(!strcmp(var, "status_file") || !strcmp(var, "status_log") || !strcmp(var, "xsddefault_status_log")) { if(status_file) free(status_file); - status_file = strdup(val); + status_file = nspath_absolute(val, main_cfg_dir); } } @@ -902,7 +870,7 @@ int read_config_file(void) { } -int read_status_file(void) { +static int read_status_file(void) { char temp_buffer[MAX_INPUT_BUFFER]; FILE *fp = NULL; int data_type = STATUS_NO_DATA; @@ -914,7 +882,7 @@ int read_status_file(void) { double execution_time = 0.0; double latency = 0.0; - int check_type = SERVICE_CHECK_ACTIVE; + int check_type = CHECK_TYPE_ACTIVE; int current_state = STATE_OK; double state_change = 0.0; int is_flapping = FALSE; @@ -984,7 +952,7 @@ int read_status_file(void) { have_max_host_state_change = TRUE; max_host_state_change = state_change; } - if(check_type == HOST_CHECK_ACTIVE) { + if(check_type == CHECK_TYPE_ACTIVE) { active_host_checks++; average_active_host_latency = (((average_active_host_latency * ((double)active_host_checks - 1.0)) + latency) / (double)active_host_checks); if(have_min_active_host_latency == FALSE || min_active_host_latency > latency) { @@ -1086,7 +1054,7 @@ int read_status_file(void) { have_max_service_state_change = TRUE; max_service_state_change = state_change; } - if(check_type == SERVICE_CHECK_ACTIVE) { + if(check_type == CHECK_TYPE_ACTIVE) { active_service_checks++; average_active_service_latency = (((average_active_service_latency * ((double)active_service_checks - 1.0)) + latency) / (double)active_service_checks); if(have_min_active_service_latency == FALSE || min_active_service_latency > latency) { @@ -1220,12 +1188,6 @@ int read_status_file(void) { case STATUS_PROGRAM_DATA: if(!strcmp(var, "program_start")) program_start = strtoul(val, NULL, 10); - else if(!strcmp(var, "total_external_command_buffer_slots")) - total_external_command_buffer_slots = atoi(val); - else if(!strcmp(var, "used_external_command_buffer_slots")) - used_external_command_buffer_slots = atoi(val); - else if(!strcmp(var, "high_external_command_buffer_slots")) - high_external_command_buffer_slots = atoi(val); else if(!strcmp(var, "nagios_pid")) nagios_pid = strtoul(val, NULL, 10); else if(!strcmp(var, "active_scheduled_host_check_stats")) { @@ -1377,342 +1339,6 @@ int read_status_file(void) { } -int read_nagiostats_file(void) { - char temp_buffer[MAX_INPUT_BUFFER]; - FILE *fp = NULL; - char *var = NULL; - char *val = NULL; - char *temp_ptr = NULL; - time_t current_time; - - time(¤t_time); - - fp = fopen(nagiostats_file, "r"); - if(fp == NULL) - return ERROR; - - /* read all lines in the status file */ - while(fgets(temp_buffer, sizeof(temp_buffer) - 1, fp)) { - - /* skip comments */ - if(temp_buffer[0] == '#') - continue; - - strip(temp_buffer); - - var = strtok(temp_buffer, "="); - val = strtok(NULL, "\n"); - if(val == NULL) - continue; - - /**** INFO ****/ - if(!strcmp(var, "created")) - status_creation_date = strtoul(val, NULL, 10); - else if(!strcmp(var, "nagios_version")) - status_version = strdup(val); - - /**** PROGRAM INFO ****/ - else if(!strcmp(var, "program_start")) - program_start = strtoul(val, NULL, 10); - else if(!strcmp(var, "total_external_command_buffer_slots")) - total_external_command_buffer_slots = atoi(val); - else if(!strcmp(var, "used_external_command_buffer_slots")) - used_external_command_buffer_slots = atoi(val); - else if(!strcmp(var, "high_external_command_buffer_slots")) - high_external_command_buffer_slots = atoi(val); - else if(!strcmp(var, "nagios_pid")) - nagios_pid = strtoul(val, NULL, 10); - else if(!strcmp(var, "active_scheduled_host_check_stats")) { - if((temp_ptr = strtok(val, ","))) - active_scheduled_host_checks_last_1min = atoi(temp_ptr); - if((temp_ptr = strtok(NULL, ","))) - active_scheduled_host_checks_last_5min = atoi(temp_ptr); - if((temp_ptr = strtok(NULL, ","))) - active_scheduled_host_checks_last_15min = atoi(temp_ptr); - } - else if(!strcmp(var, "active_ondemand_host_check_stats")) { - if((temp_ptr = strtok(val, ","))) - active_ondemand_host_checks_last_1min = atoi(temp_ptr); - if((temp_ptr = strtok(NULL, ","))) - active_ondemand_host_checks_last_5min = atoi(temp_ptr); - if((temp_ptr = strtok(NULL, ","))) - active_ondemand_host_checks_last_15min = atoi(temp_ptr); - } - else if(!strcmp(var, "cached_host_check_stats")) { - if((temp_ptr = strtok(val, ","))) - active_cached_host_checks_last_1min = atoi(temp_ptr); - if((temp_ptr = strtok(NULL, ","))) - active_cached_host_checks_last_5min = atoi(temp_ptr); - if((temp_ptr = strtok(NULL, ","))) - active_cached_host_checks_last_15min = atoi(temp_ptr); - } - else if(!strcmp(var, "passive_host_check_stats")) { - if((temp_ptr = strtok(val, ","))) - passive_host_checks_last_1min = atoi(temp_ptr); - if((temp_ptr = strtok(NULL, ","))) - passive_host_checks_last_5min = atoi(temp_ptr); - if((temp_ptr = strtok(NULL, ","))) - passive_host_checks_last_15min = atoi(temp_ptr); - } - else if(!strcmp(var, "active_scheduled_service_check_stats")) { - if((temp_ptr = strtok(val, ","))) - active_scheduled_service_checks_last_1min = atoi(temp_ptr); - if((temp_ptr = strtok(NULL, ","))) - active_scheduled_service_checks_last_5min = atoi(temp_ptr); - if((temp_ptr = strtok(NULL, ","))) - active_scheduled_service_checks_last_15min = atoi(temp_ptr); - } - else if(!strcmp(var, "active_ondemand_service_check_stats")) { - if((temp_ptr = strtok(val, ","))) - active_ondemand_service_checks_last_1min = atoi(temp_ptr); - if((temp_ptr = strtok(NULL, ","))) - active_ondemand_service_checks_last_5min = atoi(temp_ptr); - if((temp_ptr = strtok(NULL, ","))) - active_ondemand_service_checks_last_15min = atoi(temp_ptr); - } - else if(!strcmp(var, "cached_service_check_stats")) { - if((temp_ptr = strtok(val, ","))) - active_cached_service_checks_last_1min = atoi(temp_ptr); - if((temp_ptr = strtok(NULL, ","))) - active_cached_service_checks_last_5min = atoi(temp_ptr); - if((temp_ptr = strtok(NULL, ","))) - active_cached_service_checks_last_15min = atoi(temp_ptr); - } - else if(!strcmp(var, "passive_service_check_stats")) { - if((temp_ptr = strtok(val, ","))) - passive_service_checks_last_1min = atoi(temp_ptr); - if((temp_ptr = strtok(NULL, ","))) - passive_service_checks_last_5min = atoi(temp_ptr); - if((temp_ptr = strtok(NULL, ","))) - passive_service_checks_last_15min = atoi(temp_ptr); - } - else if(!strcmp(var, "external_command_stats")) { - if((temp_ptr = strtok(val, ","))) - external_commands_last_1min = atoi(temp_ptr); - if((temp_ptr = strtok(NULL, ","))) - external_commands_last_5min = atoi(temp_ptr); - if((temp_ptr = strtok(NULL, ","))) - external_commands_last_15min = atoi(temp_ptr); - } - else if(!strcmp(var, "parallel_host_check_stats")) { - if((temp_ptr = strtok(val, ","))) - parallel_host_checks_last_1min = atoi(temp_ptr); - if((temp_ptr = strtok(NULL, ","))) - parallel_host_checks_last_5min = atoi(temp_ptr); - if((temp_ptr = strtok(NULL, ","))) - parallel_host_checks_last_15min = atoi(temp_ptr); - } - else if(!strcmp(var, "serial_host_check_stats")) { - if((temp_ptr = strtok(val, ","))) - serial_host_checks_last_1min = atoi(temp_ptr); - if((temp_ptr = strtok(NULL, ","))) - serial_host_checks_last_5min = atoi(temp_ptr); - if((temp_ptr = strtok(NULL, ","))) - serial_host_checks_last_15min = atoi(temp_ptr); - } - - /***** HOST INFO *****/ - - else if(!strcmp(var, "total_hosts")) - status_host_entries = atoi(val); - else if(!strcmp(var, "hosts_checked")) - hosts_checked = atoi(val); - else if(!strcmp(var, "hosts_scheduled")) - hosts_scheduled = atoi(val); - else if(!strcmp(var, "hosts_flapping")) - hosts_flapping = atoi(val); - else if(!strcmp(var, "hosts_in_downtime")) - hosts_in_downtime = atoi(val); - else if(!strcmp(var, "hosts_up")) - hosts_up = atoi(val); - else if(!strcmp(var, "hosts_down")) - hosts_down = atoi(val); - else if(!strcmp(var, "hosts_unreachable")) - hosts_unreachable = atoi(val); - else if(!strcmp(var, "hosts_actively_checked")) - active_host_checks = atoi(val); - else if(!strcmp(var, "hosts_passively_checked")) - passive_host_checks = atoi(val); - else if(!strcmp(var, "total_host_state_change")) { - if((temp_ptr = strtok(val, ","))) - min_host_state_change = strtod(temp_ptr, NULL); - if((temp_ptr = strtok(NULL, ","))) - max_host_state_change = strtod(temp_ptr, NULL); - if((temp_ptr = strtok(NULL, ","))) - average_host_state_change = strtod(temp_ptr, NULL); - } - else if(!strcmp(var, "active_host_latency")) { - if((temp_ptr = strtok(val, ","))) - min_active_host_latency = strtod(temp_ptr, NULL); - if((temp_ptr = strtok(NULL, ","))) - max_active_host_latency = strtod(temp_ptr, NULL); - if((temp_ptr = strtok(NULL, ","))) - average_active_host_latency = strtod(temp_ptr, NULL); - } - else if(!strcmp(var, "active_host_execution_time")) { - if((temp_ptr = strtok(val, ","))) - min_active_host_execution_time = strtod(temp_ptr, NULL); - if((temp_ptr = strtok(NULL, ","))) - max_active_host_execution_time = strtod(temp_ptr, NULL); - if((temp_ptr = strtok(NULL, ","))) - average_active_host_execution_time = strtod(temp_ptr, NULL); - } - else if(!strcmp(var, "active_host_state_change")) { - if((temp_ptr = strtok(val, ","))) - min_active_host_state_change = strtod(temp_ptr, NULL); - if((temp_ptr = strtok(NULL, ","))) - max_active_host_state_change = strtod(temp_ptr, NULL); - if((temp_ptr = strtok(NULL, ","))) - average_active_host_state_change = strtod(temp_ptr, NULL); - } - else if(!strcmp(var, "active_hosts_last_x")) { - if((temp_ptr = strtok(val, ","))) - active_hosts_checked_last_1min = atoi(temp_ptr); - if((temp_ptr = strtok(NULL, ","))) - active_hosts_checked_last_5min = atoi(temp_ptr); - if((temp_ptr = strtok(NULL, ","))) - active_hosts_checked_last_15min = atoi(temp_ptr); - if((temp_ptr = strtok(NULL, ","))) - active_hosts_checked_last_1hour = atoi(temp_ptr); - } - else if(!strcmp(var, "passive_host_latency")) { - if((temp_ptr = strtok(val, ","))) - min_passive_host_latency = strtod(temp_ptr, NULL); - if((temp_ptr = strtok(NULL, ","))) - max_passive_host_latency = strtod(temp_ptr, NULL); - if((temp_ptr = strtok(NULL, ","))) - average_passive_host_latency = strtod(temp_ptr, NULL); - } - else if(!strcmp(var, "passive_host_state_change")) { - if((temp_ptr = strtok(val, ","))) - min_passive_host_state_change = strtod(temp_ptr, NULL); - if((temp_ptr = strtok(NULL, ","))) - max_passive_host_state_change = strtod(temp_ptr, NULL); - if((temp_ptr = strtok(NULL, ","))) - average_passive_host_state_change = strtod(temp_ptr, NULL); - } - else if(!strcmp(var, "passive_hosts_last_x")) { - if((temp_ptr = strtok(val, ","))) - passive_hosts_checked_last_1min = atoi(temp_ptr); - if((temp_ptr = strtok(NULL, ","))) - passive_hosts_checked_last_5min = atoi(temp_ptr); - if((temp_ptr = strtok(NULL, ","))) - passive_hosts_checked_last_15min = atoi(temp_ptr); - if((temp_ptr = strtok(NULL, ","))) - passive_hosts_checked_last_1hour = atoi(temp_ptr); - } - - - /***** SERVICE INFO *****/ - - else if(!strcmp(var, "total_services")) - status_service_entries = atoi(val); - else if(!strcmp(var, "services_checked")) - services_checked = atoi(val); - else if(!strcmp(var, "services_scheduled")) - services_scheduled = atoi(val); - else if(!strcmp(var, "services_flapping")) - services_flapping = atoi(val); - else if(!strcmp(var, "services_in_downtime")) - services_in_downtime = atoi(val); - else if(!strcmp(var, "services_ok")) - services_ok = atoi(val); - else if(!strcmp(var, "services_warning")) - services_warning = atoi(val); - else if(!strcmp(var, "services_critical")) - services_critical = atoi(val); - else if(!strcmp(var, "services_unknown")) - services_unknown = atoi(val); - else if(!strcmp(var, "services_actively_checked")) - active_service_checks = atoi(val); - else if(!strcmp(var, "services_passively_checked")) - passive_service_checks = atoi(val); - else if(!strcmp(var, "total_service_state_change")) { - if((temp_ptr = strtok(val, ","))) - min_service_state_change = strtod(temp_ptr, NULL); - if((temp_ptr = strtok(NULL, ","))) - max_service_state_change = strtod(temp_ptr, NULL); - if((temp_ptr = strtok(NULL, ","))) - average_service_state_change = strtod(temp_ptr, NULL); - } - else if(!strcmp(var, "active_service_latency")) { - if((temp_ptr = strtok(val, ","))) - min_active_service_latency = strtod(temp_ptr, NULL); - if((temp_ptr = strtok(NULL, ","))) - max_active_service_latency = strtod(temp_ptr, NULL); - if((temp_ptr = strtok(NULL, ","))) - average_active_service_latency = strtod(temp_ptr, NULL); - } - else if(!strcmp(var, "active_service_execution_time")) { - if((temp_ptr = strtok(val, ","))) - min_active_service_execution_time = strtod(temp_ptr, NULL); - if((temp_ptr = strtok(NULL, ","))) - max_active_service_execution_time = strtod(temp_ptr, NULL); - if((temp_ptr = strtok(NULL, ","))) - average_active_service_execution_time = strtod(temp_ptr, NULL); - } - else if(!strcmp(var, "active_service_state_change")) { - if((temp_ptr = strtok(val, ","))) - min_active_service_state_change = strtod(temp_ptr, NULL); - if((temp_ptr = strtok(NULL, ","))) - max_active_service_state_change = strtod(temp_ptr, NULL); - if((temp_ptr = strtok(NULL, ","))) - average_active_service_state_change = strtod(temp_ptr, NULL); - } - else if(!strcmp(var, "active_services_last_x")) { - if((temp_ptr = strtok(val, ","))) - active_services_checked_last_1min = atoi(temp_ptr); - if((temp_ptr = strtok(NULL, ","))) - active_services_checked_last_5min = atoi(temp_ptr); - if((temp_ptr = strtok(NULL, ","))) - active_services_checked_last_15min = atoi(temp_ptr); - if((temp_ptr = strtok(NULL, ","))) - active_services_checked_last_1hour = atoi(temp_ptr); - } - else if(!strcmp(var, "passive_service_latency")) { - if((temp_ptr = strtok(val, ","))) - min_passive_service_latency = strtod(temp_ptr, NULL); - if((temp_ptr = strtok(NULL, ","))) - max_passive_service_latency = strtod(temp_ptr, NULL); - if((temp_ptr = strtok(NULL, ","))) - average_passive_service_latency = strtod(temp_ptr, NULL); - } - else if(!strcmp(var, "passive_service_state_change")) { - if((temp_ptr = strtok(val, ","))) - min_passive_service_state_change = strtod(temp_ptr, NULL); - if((temp_ptr = strtok(NULL, ","))) - max_passive_service_state_change = strtod(temp_ptr, NULL); - if((temp_ptr = strtok(NULL, ","))) - average_passive_service_state_change = strtod(temp_ptr, NULL); - } - else if(!strcmp(var, "passive_services_last_x")) { - if((temp_ptr = strtok(val, ","))) - passive_services_checked_last_1min = atoi(temp_ptr); - if((temp_ptr = strtok(NULL, ","))) - passive_services_checked_last_5min = atoi(temp_ptr); - if((temp_ptr = strtok(NULL, ","))) - passive_services_checked_last_15min = atoi(temp_ptr); - if((temp_ptr = strtok(NULL, ","))) - passive_services_checked_last_1hour = atoi(temp_ptr); - } - } - - fclose(fp); - - /* 02-15-2008 exclude cached host checks from total (they were ondemand checks that never actually executed) */ - active_host_checks_last_1min = active_scheduled_host_checks_last_1min + active_ondemand_host_checks_last_1min; - active_host_checks_last_5min = active_scheduled_host_checks_last_5min + active_ondemand_host_checks_last_5min; - active_host_checks_last_15min = active_scheduled_host_checks_last_15min + active_ondemand_host_checks_last_15min; - - /* 02-15-2008 exclude cached service checks from total (they were ondemand checks that never actually executed) */ - active_service_checks_last_1min = active_scheduled_service_checks_last_1min + active_ondemand_service_checks_last_1min; - active_service_checks_last_5min = active_scheduled_service_checks_last_5min + active_ondemand_service_checks_last_5min; - active_service_checks_last_15min = active_scheduled_service_checks_last_15min + active_ondemand_service_checks_last_15min; - - return OK; - } - - /* strip newline, carriage return, and tab characters from beginning and end of a string */ void strip(char *buffer) { register int x; @@ -1775,4 +1401,3 @@ void get_time_breakdown(unsigned long raw_time, int *days, int *hours, int *minu return; } - diff --git a/base/nebmods.c b/base/nebmods.c index 5b7dca7..e6bee18 100644 --- a/base/nebmods.c +++ b/base/nebmods.c @@ -2,8 +2,6 @@ * * NEBMODS.C - Event Broker Module Functions * - * Copyright (c) 2002-2008 Ethan Galstad (egalstad@nagios.org) - * Last Modified: 11-02-2008 * * License: * @@ -32,14 +30,21 @@ #ifdef USE_EVENT_BROKER -nebmodule *neb_module_list = NULL; -nebcallback **neb_callback_list = NULL; - -extern char *temp_path; - - -/*#define DEBUG*/ +static nebmodule *neb_module_list; +static nebcallback **neb_callback_list; +/* compat stuff for USE_LTDL */ +#ifdef USE_LTDL +# define dlopen(p, flags) lt_dlopen(p) +# define dlclose(p) lt_dlclose(p) +# define dlerror() lt_dlerror() +# define dlsym(hdl, sym) lt_dlsym(hdl, sym) +# define RTLD_NOW 0 +# define RTLD_GLOBAL 0 +#else +# define lt_dlinit() 0 +# define lt_dlexit() 0 +#endif /****************************************************************************/ /****************************************************************************/ @@ -49,39 +54,20 @@ extern char *temp_path; /* initialize module routines */ int neb_init_modules(void) { -#ifdef USE_LTDL - int result = OK; -#endif - - /* initialize library */ -#ifdef USE_LTDL - result = lt_dlinit(); - if(result) + if(lt_dlinit()) return ERROR; -#endif - return OK; } /* deinitialize module routines */ int neb_deinit_modules(void) { -#ifdef USE_LTDL - int result = OK; -#endif - - /* deinitialize library */ -#ifdef USE_LTDL - result = lt_dlexit(); - if(result) + if(lt_dlexit()) return ERROR; -#endif - return OK; } - /* add a new module to module list */ int neb_add_module(char *filename, char *args, int should_be_loaded) { nebmodule *new_module = NULL; @@ -91,7 +77,7 @@ int neb_add_module(char *filename, char *args, int should_be_loaded) { return ERROR; /* allocate memory */ - new_module = (nebmodule *)malloc(sizeof(nebmodule)); + new_module = (nebmodule *)calloc(1, sizeof(nebmodule)); if(new_module == NULL) return ERROR; @@ -105,9 +91,6 @@ int neb_add_module(char *filename, char *args, int should_be_loaded) { new_module->module_handle = NULL; new_module->init_func = NULL; new_module->deinit_func = NULL; -#ifdef HAVE_PTHREAD_H - new_module->thread_id = (pthread_t)NULL; -#endif /* add module to head of list */ new_module->next = neb_module_list; @@ -119,20 +102,38 @@ int neb_add_module(char *filename, char *args, int should_be_loaded) { } +int neb_add_core_module(nebmodule *mod) { + mod->should_be_loaded = FALSE; + mod->is_currently_loaded = TRUE; + mod->core_module = TRUE; +#ifdef USE_LTDL + mod->module_handle = (lt_dlhandle)mod; +#else + mod->module_handle = mod; +#endif + mod->next = neb_module_list; + neb_module_list = mod; + return 0; + } + /* free memory allocated to module list */ int neb_free_module_list(void) { nebmodule *temp_module = NULL; nebmodule *next_module = NULL; int x = OK; - for(temp_module = neb_module_list; temp_module;) { + for(temp_module = neb_module_list; temp_module; temp_module = next_module) { next_module = temp_module->next; - my_free(temp_module->filename); - my_free(temp_module->args); + for(x = 0; x < NEBMODULE_MODINFO_NUMITEMS; x++) my_free(temp_module->info[x]); + + /* don't free this stuff for core modules */ + if (temp_module->core_module) + continue; + my_free(temp_module->filename); + my_free(temp_module->args); my_free(temp_module); - temp_module = next_module; } neb_module_list = NULL; @@ -152,27 +153,27 @@ int neb_free_module_list(void) { /* load all modules */ int neb_load_all_modules(void) { nebmodule *temp_module = NULL; - int result = OK; + int ret, errors = 0; for(temp_module = neb_module_list; temp_module; temp_module = temp_module->next) { - result = neb_load_module(temp_module); + ret = neb_load_module(temp_module); + if (ret != OK) { + logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Failed to load module '%s'.\n", temp_module->filename ? temp_module->filename : "(no file?)"); + errors++; + } } - return OK; + return errors ? ERROR : OK; } -#ifndef PATH_MAX -# define PATH_MAX 4096 -#endif /* load a particular module */ int neb_load_module(nebmodule *mod) { int (*initfunc)(int, char *, void *); int *module_version_ptr = NULL; - char output_file[PATH_MAX]; - int dest_fd, result = OK; + int result = OK; - if(mod == NULL || mod->filename == NULL) + if(mod == NULL) return ERROR; /* don't reopen the module */ @@ -180,50 +181,13 @@ int neb_load_module(nebmodule *mod) { return OK; /* don't load modules unless they should be loaded */ - if(mod->should_be_loaded == FALSE) + if(mod->should_be_loaded == FALSE || mod->filename == NULL) return ERROR; - /********** - Using dlopen() is great, but a real danger as-is. The problem with loaded modules is that if you overwrite the original file (e.g. using 'mv'), - you do not alter the inode of the original file. Since the original file/module is memory-mapped in some fashion, Nagios will segfault the next - time an event broker call is directed to one of the module's callback functions. This is extremely problematic when it comes to upgrading NEB - modules while Nagios is running. A workaround is to (1) 'mv' the original/loaded module file to another name (on the same filesystem) - and (2) copy the new module file to the location of the original one (using the original filename). In this scenario, dlopen() will keep referencing - the original file/inode for callbacks. This is not an ideal solution. A better one is to delete the module file once it is loaded by dlopen(). - This prevents other processed from unintentially overwriting the original file, which would cause Nagios to crash. However, if we delete the file - before anyone else can muck with it, things should be good. 'lsof' shows that a deleted file is still referenced by the kernel and callback - functions continue to work once the module has been loaded. Long story, but this took quite a while to figure out, as there isn't much - of anything I could find on the subject other than some sketchy info on similar problems on HP-UX. Hopefully this will save future coders some time. - So... the trick is to (1) copy the module to a temp file, (2) dlopen() the temp file, and (3) immediately delete the temp file. - ************/ - - /* - * open a temp file for copying the module. We use my_fdcopy() so - * we re-use the destination file descriptor returned by mkstemp(3), - * which we have to close ourselves. - */ - snprintf(output_file, sizeof(output_file) - 1, "%s/nebmodXXXXXX", temp_path); - dest_fd = mkstemp(output_file); - result = my_fdcopy(mod->filename, output_file, dest_fd); - close(dest_fd); - if(result == ERROR) { - logit(NSLOG_RUNTIME_ERROR, FALSE, "Error: Failed to safely copy module '%s'. The module will not be loaded\n", mod->filename); - return ERROR; - } - - /* load the module (use the temp copy we just made) */ -#ifdef USE_LTDL - mod->module_handle = lt_dlopen(output_file); -#else - mod->module_handle = (void *)dlopen(output_file, RTLD_NOW | RTLD_GLOBAL); -#endif + /* load the module */ + mod->module_handle = dlopen(mod->filename, RTLD_NOW | RTLD_GLOBAL); if(mod->module_handle == NULL) { - -#ifdef USE_LTDL - logit(NSLOG_RUNTIME_ERROR, FALSE, "Error: Could not load module '%s' -> %s\n", mod->filename, lt_dlerror()); -#else - logit(NSLOG_RUNTIME_ERROR, FALSE, "Error: Could not load module '%s' -> %s\n", mod->filename, dlerror()); -#endif + logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Could not load module '%s' -> %s\n", mod->filename, dlerror()); return ERROR; } @@ -231,28 +195,13 @@ int neb_load_module(nebmodule *mod) { /* mark the module as being loaded */ mod->is_currently_loaded = TRUE; - /* delete the temp copy of the module we just created and loaded */ - /* this will prevent other processes from overwriting the file (using the same inode), which would cause Nagios to crash */ - /* the kernel will keep the deleted file in memory until we unload it */ - /* NOTE: This *should* be portable to most Unices, but I've only tested it on Linux */ - if(unlink(output_file) == -1) { - logit(NSLOG_RUNTIME_ERROR, FALSE, "Error: Could not delete temporary file '%s' used for module '%s'. The module will be unloaded: %s\n", output_file, mod->filename, strerror(errno)); - neb_unload_module(mod, NEBMODULE_FORCE_UNLOAD, NEBMODULE_ERROR_API_VERSION); - - return ERROR; - } - /* find module API version */ -#ifdef USE_LTDL - module_version_ptr = (int *)lt_dlsym(mod->module_handle, "__neb_api_version"); -#else module_version_ptr = (int *)dlsym(mod->module_handle, "__neb_api_version"); -#endif /* check the module API version */ if(module_version_ptr == NULL || ((*module_version_ptr) != CURRENT_NEB_API_VERSION)) { - logit(NSLOG_RUNTIME_ERROR, FALSE, "Error: Module '%s' is using an old or unspecified version of the event broker API. Module will be unloaded.\n", mod->filename); + logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Module '%s' is using an old or unspecified version of the event broker API. Module will be unloaded.\n", mod->filename); neb_unload_module(mod, NEBMODULE_FORCE_UNLOAD, NEBMODULE_ERROR_API_VERSION); @@ -260,16 +209,12 @@ int neb_load_module(nebmodule *mod) { } /* locate the initialization function */ -#ifdef USE_LTDL - mod->init_func = lt_dlsym(mod->module_handle, "nebmodule_init"); -#else - mod->init_func = (void *)dlsym(mod->module_handle, "nebmodule_init"); -#endif + mod->init_func = dlsym(mod->module_handle, "nebmodule_init"); /* if the init function could not be located, unload the module */ if(mod->init_func == NULL) { - logit(NSLOG_RUNTIME_ERROR, FALSE, "Error: Could not locate nebmodule_init() in module '%s'. Module will be unloaded.\n", mod->filename); + logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Could not locate nebmodule_init() in module '%s'. Module will be unloaded.\n", mod->filename); neb_unload_module(mod, NEBMODULE_FORCE_UNLOAD, NEBMODULE_ERROR_NO_INIT); @@ -283,21 +228,17 @@ int neb_load_module(nebmodule *mod) { /* if the init function returned an error, unload the module */ if(result != OK) { - logit(NSLOG_RUNTIME_ERROR, FALSE, "Error: Function nebmodule_init() in module '%s' returned an error. Module will be unloaded.\n", mod->filename); + logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Function nebmodule_init() in module '%s' returned an error. Module will be unloaded.\n", mod->filename); neb_unload_module(mod, NEBMODULE_FORCE_UNLOAD, NEBMODULE_ERROR_BAD_INIT); return ERROR; } - logit(NSLOG_INFO_MESSAGE, FALSE, "Event broker module '%s' initialized successfully.\n", mod->filename); + logit(NSLOG_INFO_MESSAGE, TRUE, "Event broker module '%s' initialized successfully.\n", mod->filename); /* locate the de-initialization function (may or may not be present) */ -#ifdef USE_LTDL - mod->deinit_func = lt_dlsym(mod->module_handle, "nebmodule_deinit"); -#else - mod->deinit_func = (void *)dlsym(mod->module_handle, "nebmodule_deinit"); -#endif + mod->deinit_func = dlsym(mod->module_handle, "nebmodule_deinit"); log_debug_info(DEBUGL_EVENTBROKER, 0, "Module '%s' loaded with return code of '%d'\n", mod->filename, result); if(mod->deinit_func != NULL) @@ -340,6 +281,12 @@ int neb_unload_module(nebmodule *mod, int flags, int reason) { log_debug_info(DEBUGL_EVENTBROKER, 0, "Attempting to unload module '%s': flags=%d, reason=%d\n", mod->filename, flags, reason); + /* remove the module's demand-loaded file */ + if(daemon_dumps_core == TRUE && mod->dl_file) { + (void)unlink(mod->dl_file); + my_free(mod->dl_file); + } + /* call the de-initialization function if available (and the module was initialized) */ if(mod->deinit_func && reason != NEBMODULE_ERROR_BAD_INIT) { @@ -356,12 +303,16 @@ int neb_unload_module(nebmodule *mod, int flags, int reason) { /* deregister all of the module's callbacks */ neb_deregister_module_callbacks(mod); - /* unload the module */ -#ifdef USE_LTDL - result = lt_dlclose(mod->module_handle); -#else - result = dlclose(mod->module_handle); -#endif + if(mod->core_module == FALSE) { + + /* unload the module */ + result = dlclose(mod->module_handle); + + if (result != 0) { + logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Could not unload module '%s' -> %s\n", mod->filename, dlerror()); + return ERROR; + } + } /* mark the module as being unloaded */ mod->is_currently_loaded = FALSE; @@ -395,7 +346,7 @@ int neb_set_module_info(void *handle, int type, char *data) { /* find the module */ for(temp_module = neb_module_list; temp_module != NULL; temp_module = temp_module->next) { - if((void *)temp_module->module_handle == (void *)handle) + if(temp_module->module_handle == handle) break; } if(temp_module == NULL) @@ -441,7 +392,7 @@ int neb_register_callback(int callback_type, void *mod_handle, int priority, int /* make sure module handle is valid */ for(temp_module = neb_module_list; temp_module; temp_module = temp_module->next) { - if((void *)temp_module->module_handle == (void *)mod_handle) + if(temp_module->module_handle == mod_handle) break; } if(temp_module == NULL) @@ -453,8 +404,8 @@ int neb_register_callback(int callback_type, void *mod_handle, int priority, int return NEBERROR_NOMEM; new_callback->priority = priority; - new_callback->module_handle = (void *)mod_handle; - new_callback->callback_func = (void *)callback_func; + new_callback->module_handle = mod_handle; + new_callback->callback_func = callback_func; /* add new function to callback list, sorted by priority (first come, first served for same priority) */ new_callback->next = NULL; @@ -499,7 +450,7 @@ int neb_deregister_module_callbacks(nebmodule *mod) { for(callback_type = 0; callback_type < NEBCALLBACK_NUMITEMS; callback_type++) { for(temp_callback = neb_callback_list[callback_type]; temp_callback != NULL; temp_callback = next_callback) { next_callback = temp_callback->next; - if((void *)temp_callback->module_handle == (void *)mod->module_handle) + if(temp_callback->module_handle == mod->module_handle) neb_deregister_callback(callback_type, (int(*)(int, void*))temp_callback->callback_func); } @@ -530,7 +481,7 @@ int neb_deregister_callback(int callback_type, int (*callback_func)(int, void *) next_callback = temp_callback->next; /* we found it */ - if(temp_callback->callback_func == (void *)callback_func) + if(temp_callback->callback_func == callback_func) break; last_callback = temp_callback; diff --git a/base/nerd.c b/base/nerd.c new file mode 100644 index 0000000..ffa8bd3 --- /dev/null +++ b/base/nerd.c @@ -0,0 +1,495 @@ +/* + * Nagios Event Radio Dispatcher + * + * This is a subscriber service which initiates a unix domain socket, + * listens to it and lets other programs connect to it and subscribe + * to various channels using a simple text-based syntax. + * + * This code uses the eventbroker api to get its data, which means + * we're finally eating our own dogfood in that respect. + */ + +#define _GNU_SOURCE 1 +#include +#include "include/config.h" +#include +#include +#include "lib/libnagios.h" +#include "include/common.h" +#include "include/objects.h" +#include "include/broker.h" +#include "include/nebmods.h" +#include "include/nebmodules.h" +#include "include/nebstructs.h" + +struct nerd_channel { + const char *name; /* name of this channel */ + const char *description; /* user-presentable string to document the purpouse of this channel */ + unsigned int id; /* channel id (might vary between invocations) */ + unsigned int required_options; /* event_broker_options required for this channel */ + unsigned int num_callbacks; + unsigned int callbacks[NEBCALLBACK_NUMITEMS]; + int (*handler)(int , void *); /* callback handler for this channel */ + objectlist *subscriptions; /* subscriber list */ +}; + +static nebmodule nerd_mod; /* fake module to get our callbacks accepted */ +static struct nerd_channel **channels; +static unsigned int num_channels, alloc_channels; +static unsigned int chan_host_checks_id, chan_service_checks_id; +static unsigned int chan_opath_checks_id; + + +static struct nerd_channel *find_channel(const char *name) +{ + unsigned int i; + + for(i = 0; i < num_channels; i++) { + struct nerd_channel *chan = channels[i]; + if(!strcmp(name, chan->name)) { + return chan; + } + } + return NULL; +} + +int nerd_get_channel_id(const char *name) +{ + struct nerd_channel *chan; + + chan = find_channel(name); + if (!chan) + return -1; + + return chan->id; +} + +static struct nerd_channel *nerd_get_channel(unsigned int chan_id) +{ + return chan_id >= num_channels ? NULL : channels[chan_id]; +} + +objectlist *nerd_get_subscriptions(int chan_id) +{ + struct nerd_channel *chan = nerd_get_channel(chan_id); + + return chan ? chan->subscriptions : NULL; +} + +static int nerd_register_channel_callbacks(struct nerd_channel *chan) +{ + unsigned int i; + + for(i = 0; i < chan->num_callbacks; i++) { + int result = neb_register_callback(chan->callbacks[i], &nerd_mod, 0, chan->handler); + if(result != 0) { + logit(NSLOG_RUNTIME_ERROR, TRUE, "nerd: Failed to register callback %d for channel '%s': %d\n", + chan->callbacks[i], chan->name, result); + return -1; + } + } + return 0; +} + +static int nerd_deregister_channel_callbacks(struct nerd_channel *chan) +{ + unsigned int i; + + for(i = 0; i < chan->num_callbacks; i++) { + neb_deregister_callback(chan->callbacks[i], chan->handler); + } + return 0; +} + +static int subscribe(int sd, struct nerd_channel *chan, char *fmt) +{ + struct nerd_subscription *subscr; + + if(!(subscr = calloc(1, sizeof(*subscr)))) + return -1; + + subscr->sd = sd; + subscr->chan = chan; + subscr->format = fmt ? strdup(fmt) : NULL; + + if(!chan->subscriptions) { + nerd_register_channel_callbacks(chan); + } + + prepend_object_to_objectlist(&chan->subscriptions, subscr); + return 0; +} + +static int cancel_channel_subscription(struct nerd_channel *chan, int sd) +{ + objectlist *list, *next, *prev = NULL; + int cancelled = 0; + + if(!chan) + return -1; + + for(list = chan->subscriptions; list; list = next) { + struct nerd_subscription *subscr = (struct nerd_subscription *)list->object_ptr; + next = list->next; + + if(subscr->sd == sd) { + cancelled++; + free(list); + free(subscr); + if(prev) { + prev->next = next; + } else { + chan->subscriptions = next; + } + continue; + } + prev = list; + } + + if(cancelled) { + logit(NSLOG_INFO_MESSAGE, TRUE, "nerd: Cancelled %d subscription%s to channel '%s' for %d\n", + cancelled, cancelled == 1 ? "" : "s", chan->name, sd); + } + + if(chan->subscriptions == NULL) + nerd_deregister_channel_callbacks(chan); + + return 0; +} + +static int unsubscribe(int sd, struct nerd_channel *chan) +{ + objectlist *list, *next, *prev = NULL; + + for(list = chan->subscriptions; list; list = next) { + struct nerd_subscription *subscr = (struct nerd_subscription *)list->object_ptr; + next = list->next; + if(subscr->sd == sd) { + /* found it, so remove it */ + free(subscr); + free(list); + if(!prev) { + chan->subscriptions = next; + continue; + } else { + prev->next = next; + } + continue; + } + prev = list; + } + + if(chan->subscriptions == NULL) { + nerd_deregister_channel_callbacks(chan); + } + return 0; +} + +/* removes a subscriber entirely and closes its socket */ +int nerd_cancel_subscriber(int sd) +{ + unsigned int i; + + for(i = 0; i < num_channels; i++) { + cancel_channel_subscription(channels[i], sd); + } + + iobroker_close(nagios_iobs, sd); + return 0; +} + +int nerd_broadcast(unsigned int chan_id, void *buf, unsigned int len) +{ + struct nerd_channel *chan; + objectlist *list, *next; + + if (!(chan = nerd_get_channel(chan_id))) + return -1; + + for(list = chan->subscriptions; list; list = next) { + struct nerd_subscription *subscr = (struct nerd_subscription *)list->object_ptr; + int result; + + next = list->next; + + result = send(subscr->sd, buf, len, 0); + if(result < 0) { + if (errno == EAGAIN) + return 0; + + nerd_cancel_subscriber(subscr->sd); + return 500; + } + } + + return 0; +} + + +static int chan_host_checks(int cb, void *data) +{ + nebstruct_host_check_data *ds = (nebstruct_host_check_data *)data; + check_result *cr = (check_result *)ds->check_result_ptr; + host *h; + char *buf; + int len; + + if(ds->type != NEBTYPE_HOSTCHECK_PROCESSED) + return 0; + + if(channels[chan_host_checks_id]->subscriptions == NULL) + return 0; + + h = (host *)ds->object_ptr; + len = asprintf(&buf, "%s from %d -> %d: %s\n", h->name, h->last_state, h->current_state, cr->output); + nerd_broadcast(chan_host_checks_id, buf, len); + free(buf); + return 0; +} + +static int chan_service_checks(int cb, void *data) +{ + nebstruct_service_check_data *ds = (nebstruct_service_check_data *)data; + check_result *cr = (check_result *)ds->check_result_ptr; + service *s; + char *buf; + int len; + + if(ds->type != NEBTYPE_SERVICECHECK_PROCESSED) + return 0; + s = (service *)ds->object_ptr; + len = asprintf(&buf, "%s;%s from %d -> %d: %s\n", s->host_name, s->description, s->last_state, s->current_state, cr->output); + nerd_broadcast(chan_service_checks_id, buf, len); + free(buf); + return 0; +} + +static char **host_parent_path_cache; +static const char *host_parent_path(host *leaf, char sep) +{ + char *ret; + unsigned int len = 0, pos = 0; + objectlist *stack = NULL, *list, *next; + host *h = leaf; + + if(!h->parent_hosts) + return h->name; + + if(!host_parent_path_cache) { + host_parent_path_cache = calloc(num_objects.hosts, sizeof(char *)); + } + if(host_parent_path_cache[h->id]) { + return host_parent_path_cache[h->id]; + } + + while(h) { + len += strlen(h->name) + 2; /* room for separator */ + prepend_object_to_objectlist(&stack, h->name); + if(h->parent_hosts && h->parent_hosts->host_ptr) + h = h->parent_hosts->host_ptr; + else + break; + } + + ret = malloc(len + 1); + for(list = stack; list; list = next) { + char *ppart = (char *)list->object_ptr; + next = list->next; + free(list); + ret[pos++] = sep; + memcpy(ret + pos, ppart, strlen(ppart)); + pos += strlen(ppart); + } + ret[pos++] = 0; + host_parent_path_cache[leaf->id] = ret; + return ret; +} + +static int chan_opath_checks(int cb, void *data) +{ + const int red = 0xff0000, green = 0xff00, blue = 0xff, pale = 0x555555; + unsigned int color; + check_result *cr; + host *h; + const char *name = "_HOST_"; + char *buf = NULL; + + if(cb == NEBCALLBACK_HOST_CHECK_DATA) { + nebstruct_host_check_data *ds = (nebstruct_host_check_data *)data; + + if(ds->type != NEBTYPE_HOSTCHECK_PROCESSED) + return 0; + + cr = ds->check_result_ptr; + h = ds->object_ptr; + color = red | green; + } else if(cb == NEBCALLBACK_SERVICE_CHECK_DATA) { + nebstruct_service_check_data *ds = (nebstruct_service_check_data *)data; + service *s; + + if(ds->type != NEBTYPE_SERVICECHECK_PROCESSED) + return 0; + s = (service *)ds->object_ptr; + h = s->host_ptr; + cr = ds->check_result_ptr; + color = (red | green | blue) ^ pale; + name = s->description; + } else + return 0; + + asprintf(&buf, "%lu|%s|M|%s/%s|%06X\n", cr->finish_time.tv_sec, + check_result_source(cr), host_parent_path(h, '/'), name, color); + nerd_broadcast(chan_opath_checks_id, buf, strlen(buf)); + free(buf); + return 0; +} + + +static int nerd_deinit(void) +{ + unsigned int i; + + if(host_parent_path_cache) { + for(i = 0; i < num_objects.hosts; i++) { + my_free(host_parent_path_cache[i]); + } + my_free(host_parent_path_cache); + } + + for(i = 0; i < num_channels; i++) { + struct nerd_channel *chan = channels[i]; + objectlist *list, *next; + + for(list = chan->subscriptions; list; list = next) { + struct nerd_subscription *subscr = (struct nerd_subscription *)list->object_ptr; + iobroker_close(nagios_iobs, subscr->sd); + next = list->next; + free(list); + free(subscr); + } + chan->subscriptions = NULL; + my_free(chan); + } + my_free(channels); + num_channels = 0; + alloc_channels = 0; + + return 0; +} + +int nerd_mkchan(const char *name, const char *description, int (*handler)(int, void *), unsigned int callbacks) +{ + struct nerd_channel *chan, **ptr; + int i; + + if(num_channels + 1 >= alloc_channels) { + alloc_channels = alloc_nr(alloc_channels); + ptr = realloc(channels, alloc_channels * sizeof(struct nerd_channel *)); + if(!ptr) + return -1; + channels = ptr; + } + + if(!(chan = calloc(1, sizeof(*chan)))) + return -1; + + chan->name = name; + chan->description = description; + chan->handler = handler; + for(i = 0; callbacks && i < NEBCALLBACK_NUMITEMS; i++) { + if(!(callbacks & (1 << i))) + continue; + + chan->callbacks[chan->num_callbacks++] = i; + } + + channels[num_channels++] = chan; + + logit(NSLOG_INFO_MESSAGE, TRUE, "nerd: Channel %s registered successfully\n", chan->name); + return num_channels - 1; +} + +#define NERD_SUBSCRIBE 0 +#define NERD_UNSUBSCRIBE 1 +static int nerd_qh_handler(int sd, char *request, unsigned int len) +{ + char *chan_name, *fmt; + struct nerd_channel *chan; + int action; + + if (!*request || !strcmp(request, "help")) { + nsock_printf_nul(sd, "Manage subscriptions to NERD channels.\n" + "Valid commands:\n" + " list list available channels\n" + " subscribe subscribe to a channel\n" + " unsubscribe unsubscribe to a channel\n"); + return 0; + } + + if (!strcmp(request, "list")) { + unsigned int i; + for (i = 0; i < num_channels; i++) { + chan = channels[i]; + nsock_printf(sd, "%-15s %s\n", chan->name, chan->description); + } + nsock_printf(sd, "%c", 0); + return 0; + } + + chan_name = strchr(request, ' '); + if(!chan_name) + return 400; + + *chan_name = 0; + chan_name++; + if(!strcmp(request, "subscribe")) + action = NERD_SUBSCRIBE; + else if(!strcmp(request, "unsubscribe")) + action = NERD_UNSUBSCRIBE; + else { + return 400; + } + + /* might have a format-string */ + if((fmt = strchr(chan_name, ':'))) + *(fmt++) = 0; + + chan = find_channel(chan_name); + if(!chan) { + return 400; + } + + if(action == NERD_SUBSCRIBE) + subscribe(sd, chan, fmt); + else + unsubscribe(sd, chan); + + return 0; +} + +/* nebmod_init(), but loaded even if no modules are */ +int nerd_init(void) +{ + nerd_mod.deinit_func = nerd_deinit; + nerd_mod.filename = (char *)"NERD"; /* something to log */ + + if(qh_register_handler("nerd", "Nagios Event Radio Dispatcher - Subscriber Service", 0, nerd_qh_handler) < 0) { + logit(NSLOG_RUNTIME_ERROR, TRUE, "nerd: Failed to register with query handler\n"); + return ERROR; + } + + neb_add_core_module(&nerd_mod); + + chan_host_checks_id = nerd_mkchan("hostchecks", + "Host check results", + chan_host_checks, nebcallback_flag(NEBCALLBACK_HOST_CHECK_DATA)); + chan_service_checks_id = nerd_mkchan("servicechecks", + "Service check results", + chan_service_checks, nebcallback_flag(NEBCALLBACK_SERVICE_CHECK_DATA)); + chan_opath_checks_id = nerd_mkchan("opathchecks", + "Host and service checks in gource's log format", + chan_opath_checks, nebcallback_flag(NEBCALLBACK_HOST_CHECK_DATA) | nebcallback_flag(NEBCALLBACK_SERVICE_CHECK_DATA)); + + logit(NSLOG_INFO_MESSAGE, TRUE, "nerd: Fully initialized and ready to rock!\n"); + return 0; +} diff --git a/base/netutils.c b/base/netutils.c index 2b7f6c2..91d91a1 100644 --- a/base/netutils.c +++ b/base/netutils.c @@ -2,9 +2,7 @@ * * NETUTILS.C - Network connection utility functions for Nagios * - * Copyright (c) 1999,2008 Ethan Galstad (egalstad@nagios.org) * Portions Copyright (c) 1999-2008 Nagios Plugin development team - * Last Modified: 12-04-2008 * * License: * @@ -29,7 +27,7 @@ /* connect to a TCP socket in nonblocking fashion */ -int my_tcp_connect(char *host_name, int port, int *sd, int timeout) { +int my_tcp_connect(const char *host_name, int port, int *sd, int timeout) { struct addrinfo hints; struct addrinfo *res; int result; @@ -154,7 +152,7 @@ int my_tcp_connect(char *host_name, int port, int *sd, int timeout) { /* based on Beej's sendall - thanks Beej! */ -int my_sendall(int s, char *buf, int *len, int timeout) { +int my_sendall(int s, const char *buf, int *len, int timeout) { int total_sent = 0; int bytes_left = 0; int n; diff --git a/base/notifications.c b/base/notifications.c index ffe3b68..4b52a3d 100644 --- a/base/notifications.c +++ b/base/notifications.c @@ -2,9 +2,6 @@ * * NOTIFICATIONS.C - Service and host notification functions for Nagios * - * Copyright (c) 2009-2010 Nagios Core Development Team and Community Contributors - * Copyright (c) 1999-2008 Ethan Galstad (egalstad@nagios.org) - * Last Modified: 08-04-2010 * * License: * @@ -31,25 +28,37 @@ #include "../include/nagios.h" #include "../include/broker.h" #include "../include/neberrors.h" +#include "../include/workers.h" +#include "../include/downtime.h" -extern notification *notification_list; -extern contact *contact_list; -extern serviceescalation *serviceescalation_list; -extern hostescalation *hostescalation_list; +/*** silly helpers ****/ +static contact *find_contact_by_name_or_alias(const char *name) +{ + contact *c = NULL; -extern time_t program_start; + if (!name || !(c = find_contact(name))) + return c; + for (c = contact_list; c; c = c->next) + if (!strcmp(c->alias, name)) + break; -extern int interval_length; -extern int log_notifications; + return c; +} -extern int enable_notifications; +const char *notification_reason_name(unsigned int reason_type) +{ + static const char *names[] = { + "NORMAL", "ACKNOWLEDGEMENT", + "FLAPPINGSTART", "FLAPPINGSTOP", "FLAPPINGDISABLED", + "DOWNTIMESTART", "DOWNTIMEEND", "DOWNTIMECANCELLED", + "CUSTOM" + }; -extern int notification_timeout; - -extern unsigned long next_notification_id; - -extern char *generic_summary; + if (reason_type < sizeof(names)) + return names[reason_type]; + return "(unknown)"; +} /******************************************************************/ @@ -78,7 +87,7 @@ int service_notification(service *svc, int type, char *not_author, char *not_dat time(¤t_time); gettimeofday(&start_time, NULL); - log_debug_info(DEBUGL_NOTIFICATIONS, 0, "** Service Notification Attempt ** Host: '%s', Service: '%s', Type: %d, Options: %d, Current State: %d, Last Notification: %s", svc->host_name, svc->description, type, options, svc->current_state, ctime(&svc->last_notification)); + log_debug_info(DEBUGL_NOTIFICATIONS, 0, "** Service Notification Attempt ** Host: '%s', Service: '%s', Type: %s, Options: %d, Current State: %d, Last Notification: %s", svc->host_name, svc->description, notification_reason_name(type), options, svc->current_state, ctime(&svc->last_notification)); /* if we couldn't find the host, return an error */ if((temp_host = svc->host_ptr) == NULL) { @@ -89,6 +98,14 @@ int service_notification(service *svc, int type, char *not_author, char *not_dat /* check the viability of sending out a service notification */ if(check_service_notification_viability(svc, type, options) == ERROR) { log_debug_info(DEBUGL_NOTIFICATIONS, 0, "Notification viability test failed. No notification will be sent out.\n"); + /* Set next_notification time if we're in a downtime and + notification_interval = zero, otherwise if the service + doesn't recover after downtime ends, it will never send + the notification */ + if (svc->notification_interval == 0.0) { + if (temp_host->scheduled_downtime_depth > 0 || svc->scheduled_downtime_depth > 0) + svc->next_notification = current_time; + } return OK; } @@ -113,13 +130,11 @@ int service_notification(service *svc, int type, char *not_author, char *not_dat end_time.tv_sec = 0L; end_time.tv_usec = 0L; neb_result = broker_notification_data(NEBTYPE_NOTIFICATION_START, NEBFLAG_NONE, NEBATTR_NONE, SERVICE_NOTIFICATION, type, start_time, end_time, (void *)svc, not_author, not_data, escalated, 0, NULL); - if(NEBERROR_CALLBACKCANCEL == neb_result) { + if(neb_result == NEBERROR_CALLBACKCANCEL || neb_result == NEBERROR_CALLBACKOVERRIDE) { + log_debug_info(DEBUGL_CHECKS, 0, "Service notification to %s;%s (id=%u) was blocked by a module\n", + svc->host_name, svc->description, svc->id); free_notification_list(); - return ERROR; - } - else if(NEBERROR_CALLBACKOVERRIDE == neb_result) { - free_notification_list(); - return OK; + return neb_result == NEBERROR_CALLBACKOVERRIDE ? OK : ERROR; } #endif @@ -128,23 +143,21 @@ int service_notification(service *svc, int type, char *not_author, char *not_dat /* create the contact notification list for this service */ - /* 2011-11-01 MF: - check viability before adding a contact - to the notification list, requires type - this prevents us from running through all - the steps until notify_contact_of_host|service - is reached. furthermore the $NOTIFICATIONRECIPIENTS$ - macro only gets populated with actual recipients, - not all contacts assigned to that host|service. - - note: checks against timeperiod will happen now(), - and not when the notification is actually being sent. - - original patch by Opsview Team - */ + /* + * check viability before adding a contact to the notification + * list and build up the $NOTIFICATIONRECIPIENTS$ macro while + * we're at it. + * This prevents us from running through all the steps again in + * notify_contact_of_host|service. + * Furthermore the $NOTIFICATIONRECIPIENTS$ macro will contain + * only actual recipients (as the name implies), and not all + * contacts assigned to that host|service. + * + * note: checks against timeperiod will happen now(), + * and not when the notification is actually being sent. + */ create_notification_list_from_service(&mac, svc, options, &escalated, type); - /* XXX: crazy indent */ /* we have contacts to notify... */ if(notification_list != NULL) { @@ -154,14 +167,7 @@ int service_notification(service *svc, int type, char *not_author, char *not_dat /* if this notification has an author, attempt to lookup the associated contact */ if(not_author != NULL) { - - /* see if we can find the contact - first by name, then by alias */ - if((temp_contact = find_contact(not_author)) == NULL) { - for(temp_contact = contact_list; temp_contact != NULL; temp_contact = temp_contact->next) { - if(!strcmp(temp_contact->alias, not_author)) - break; - } - } + temp_contact = find_contact_by_name_or_alias(not_author); } /* get author and comment macros */ @@ -262,9 +268,13 @@ int service_notification(service *svc, int type, char *not_author, char *not_dat */ clear_summary_macros_r(&mac); clear_contact_macros_r(&mac); + clear_contactgroup_macros_r(&mac); clear_argv_macros_r(&mac); clear_host_macros_r(&mac); + clear_hostgroup_macros_r(&mac); clear_service_macros_r(&mac); + clear_servicegroup_macros_r(&mac); + clear_datetime_macros_r(&mac); if(type == NOTIFICATION_NORMAL) { @@ -280,12 +290,7 @@ int service_notification(service *svc, int type, char *not_author, char *not_dat svc->last_notification = current_time; /* update notifications flags */ - if(svc->current_state == STATE_UNKNOWN) - svc->notified_on_unknown = TRUE; - else if(svc->current_state == STATE_WARNING) - svc->notified_on_warning = TRUE; - else if(svc->current_state == STATE_CRITICAL) - svc->notified_on_critical = TRUE; + add_notified_on(svc, svc->current_state); } /* we didn't end up notifying anyone */ @@ -366,6 +371,22 @@ int check_service_notification_viability(service *svc, int type, int options) { return ERROR; } + /* if all parents are bad (usually just one), we shouldn't notify */ + if(svc->parents) { + int bad_parents = 0, total_parents = 0; + servicesmember *sm; + for(sm = svc->parents; sm; sm = sm->next) { + /* @todo: tweak this so it handles hard states and whatnot */ + if(sm->service_ptr->current_state == STATE_OK) + bad_parents += !!sm->service_ptr->current_state; + total_parents++; + } + if(bad_parents == total_parents) { + log_debug_info(DEBUGL_NOTIFICATIONS, 1, "This service has no good parents, so notification will be blocked.\n"); + return ERROR; + } + } + /* if the service has no notification period, inherit one from the host */ temp_period = svc->notification_period_ptr; if(temp_period == NULL) { @@ -418,9 +439,9 @@ int check_service_notification_viability(service *svc, int type, int options) { - /****************************************/ - /*** SPECIAL CASE FOR ACKNOWLEGEMENTS ***/ - /****************************************/ + /*****************************************/ + /*** SPECIAL CASE FOR ACKNOWLEDGEMENTS ***/ + /*****************************************/ /* acknowledgements only have to pass three general filters, although they have another test of their own... */ if(type == NOTIFICATION_ACKNOWLEDGEMENT) { @@ -444,7 +465,7 @@ int check_service_notification_viability(service *svc, int type, int options) { if(type == NOTIFICATION_FLAPPINGSTART || type == NOTIFICATION_FLAPPINGSTOP || type == NOTIFICATION_FLAPPINGDISABLED) { /* don't send a notification if we're not supposed to... */ - if(svc->notify_on_flapping == FALSE) { + if(flag_isset(svc->notification_options, OPT_FLAPPING) == FALSE) { log_debug_info(DEBUGL_NOTIFICATIONS, 1, "We shouldn't notify about FLAPPING events for this service.\n"); return ERROR; } @@ -468,7 +489,7 @@ int check_service_notification_viability(service *svc, int type, int options) { if(type == NOTIFICATION_DOWNTIMESTART || type == NOTIFICATION_DOWNTIMEEND || type == NOTIFICATION_DOWNTIMECANCELLED) { /* don't send a notification if we're not supposed to... */ - if(svc->notify_on_downtime == FALSE) { + if(flag_isset(svc->notification_options, OPT_DOWNTIME) == FALSE) { log_debug_info(DEBUGL_NOTIFICATIONS, 1, "We shouldn't notify about DOWNTIME events for this service.\n"); return ERROR; } @@ -513,44 +534,24 @@ int check_service_notification_viability(service *svc, int type, int options) { } /* see if we should notify about problems with this service */ - if(svc->current_state == STATE_UNKNOWN && svc->notify_on_unknown == FALSE) { - log_debug_info(DEBUGL_NOTIFICATIONS, 1, "We shouldn't notify about UNKNOWN states for this service.\n"); + if(should_notify(svc) == FALSE) { + log_debug_info(DEBUGL_NOTIFICATIONS, 1, "We shouldn't notify about %s states for this service.\n", service_state_name(svc->current_state)); return ERROR; } - if(svc->current_state == STATE_WARNING && svc->notify_on_warning == FALSE) { - log_debug_info(DEBUGL_NOTIFICATIONS, 1, "We shouldn't notify about WARNING states for this service.\n"); + if(svc->current_state == STATE_OK && svc->notified_on == 0) { + log_debug_info(DEBUGL_NOTIFICATIONS, 1, "We shouldn't notify about this recovery.\n"); return ERROR; } - if(svc->current_state == STATE_CRITICAL && svc->notify_on_critical == FALSE) { - log_debug_info(DEBUGL_NOTIFICATIONS, 1, "We shouldn't notify about CRITICAL states for this service.\n"); - return ERROR; - } - if(svc->current_state == STATE_OK) { - if(svc->notify_on_recovery == FALSE) { - log_debug_info(DEBUGL_NOTIFICATIONS, 1, "We shouldn't notify about RECOVERY states for this service.\n"); - return ERROR; - } - if(!(svc->notified_on_unknown == TRUE || svc->notified_on_warning == TRUE || svc->notified_on_critical == TRUE)) { - log_debug_info(DEBUGL_NOTIFICATIONS, 1, "We shouldn't notify about this recovery.\n"); - return ERROR; - } - } + /* see if enough time has elapsed for first notification (Mathias Sundman) */ /* 10/02/07 don't place restrictions on recoveries or non-normal notifications, must use last time ok (or program start) in calculation */ - /* it is reasonable to assume that if the host was never up, the program start time should be used in this calculation */ + /* it is reasonable to assume that if the service was never up, the program start time should be used in this calculation */ if(type == NOTIFICATION_NORMAL && svc->current_notification_number == 0 && svc->current_state != STATE_OK) { - /* determine the time to use of the first problem point */ - first_problem_time = svc->last_time_ok; /* not accurate, but its the earliest time we could use in the comparison */ - if((svc->last_time_warning < first_problem_time) && (svc->last_time_warning > svc->last_time_ok)) - first_problem_time = svc->last_time_warning; - if((svc->last_time_unknown < first_problem_time) && (svc->last_time_unknown > svc->last_time_ok)) - first_problem_time = svc->last_time_unknown; - if((svc->last_time_critical < first_problem_time) && (svc->last_time_critical > svc->last_time_ok)) - first_problem_time = svc->last_time_critical; + first_problem_time = svc->last_time_ok > 0 ? svc->last_time_ok : program_start; - if(current_time < (time_t)((first_problem_time == (time_t)0L) ? program_start : first_problem_time) + (time_t)(svc->first_notification_delay * interval_length)) { + if(current_time < first_problem_time + (time_t)(svc->first_notification_delay * interval_length)) { log_debug_info(DEBUGL_NOTIFICATIONS, 1, "Not enough time has elapsed since the service changed to a non-OK state, so we should not notify about this problem yet\n"); return ERROR; } @@ -573,7 +574,7 @@ int check_service_notification_viability(service *svc, int type, int options) { } /* if the host is down or unreachable, don't notify contacts about service failures */ - if(temp_host->current_state != HOST_UP) { + if(temp_host->current_state != STATE_UP && temp_host->state_type == HARD_STATE) { log_debug_info(DEBUGL_NOTIFICATIONS, 1, "The host is either down or unreachable, so we won't notify contacts about this service.\n"); return ERROR; } @@ -597,6 +598,18 @@ int check_service_notification_viability(service *svc, int type, int options) { return ERROR; } + /* if this service is currently in a flex downtime period, don't send the notification */ + if(svc->pending_flex_downtime > 0 && is_service_in_pending_flex_downtime(svc) == TRUE) { + log_debug_info(DEBUGL_NOTIFICATIONS, 1, "This service is starting a flex downtime, so we won't send notifications.\n"); + return ERROR; + } + + /* if this host is currently in a flex downtime period, don't send the notification */ + if(temp_host->pending_flex_downtime > 0 && is_host_in_pending_flex_downtime(temp_host) == TRUE) { + log_debug_info(DEBUGL_NOTIFICATIONS, 1, "The host this service is associated with is starting a flex downtime, so we won't send notifications.\n"); + return ERROR; + } + return OK; } @@ -615,6 +628,12 @@ int check_contact_service_notification_viability(contact *cntct, service *svc, i return OK; } + /* is this service not important enough? */ + if(cntct->minimum_value > svc->hourly_value) { + log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Contact's minimum_importance is higher than service's importance. Notification will be blocked\n"); + return ERROR; + } + /* are notifications enabled? */ if(cntct->service_notifications_enabled == FALSE) { log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Service notifications are disabled for this contact.\n"); @@ -642,7 +661,7 @@ int check_contact_service_notification_viability(contact *cntct, service *svc, i if(type == NOTIFICATION_FLAPPINGSTART || type == NOTIFICATION_FLAPPINGSTOP || type == NOTIFICATION_FLAPPINGDISABLED) { - if(cntct->notify_on_service_flapping == FALSE) { + if((cntct->service_notification_options & OPT_FLAPPING) == FALSE) { log_debug_info(DEBUGL_NOTIFICATIONS, 2, "We shouldn't notify this contact about FLAPPING service events.\n"); return ERROR; } @@ -656,7 +675,7 @@ int check_contact_service_notification_viability(contact *cntct, service *svc, i if(type == NOTIFICATION_DOWNTIMESTART || type == NOTIFICATION_DOWNTIMEEND || type == NOTIFICATION_DOWNTIMECANCELLED) { - if(cntct->notify_on_service_downtime == FALSE) { + if((cntct->service_notification_options & OPT_DOWNTIME) == FALSE) { log_debug_info(DEBUGL_NOTIFICATIONS, 2, "We shouldn't notify this contact about DOWNTIME service events.\n"); return ERROR; } @@ -669,29 +688,19 @@ int check_contact_service_notification_viability(contact *cntct, service *svc, i /*************************************/ /* see if we should notify about problems with this service */ - if(svc->current_state == STATE_UNKNOWN && cntct->notify_on_service_unknown == FALSE) { - log_debug_info(DEBUGL_NOTIFICATIONS, 2, "We shouldn't notify this contact about UNKNOWN service states.\n"); - return ERROR; - } - - if(svc->current_state == STATE_WARNING && cntct->notify_on_service_warning == FALSE) { - log_debug_info(DEBUGL_NOTIFICATIONS, 2, "We shouldn't notify this contact about WARNING service states.\n"); - return ERROR; - } - - if(svc->current_state == STATE_CRITICAL && cntct->notify_on_service_critical == FALSE) { - log_debug_info(DEBUGL_NOTIFICATIONS, 2, "We shouldn't notify this contact about CRITICAL service states.\n"); + if(!(cntct->service_notification_options & (1 << svc->current_state))) { + log_debug_info(DEBUGL_NOTIFICATIONS, 2, "We shouldn't notify this contact about %s service states.\n", service_state_name(svc->current_state)); return ERROR; } if(svc->current_state == STATE_OK) { - if(cntct->notify_on_service_recovery == FALSE) { + if((cntct->service_notification_options & OPT_RECOVERY) == FALSE) { log_debug_info(DEBUGL_NOTIFICATIONS, 2, "We shouldn't notify this contact about RECOVERY service states.\n"); return ERROR; } - if(!((svc->notified_on_unknown == TRUE && cntct->notify_on_service_unknown == TRUE) || (svc->notified_on_warning == TRUE && cntct->notify_on_service_warning == TRUE) || (svc->notified_on_critical == TRUE && cntct->notify_on_service_critical == TRUE))) { + if(!(svc->notified_on & cntct->service_notification_options)) { log_debug_info(DEBUGL_NOTIFICATIONS, 2, "We shouldn't notify about this recovery.\n"); return ERROR; } @@ -713,14 +722,11 @@ int notify_contact_of_service(nagios_macros *mac, contact *cntct, service *svc, char *processed_command = NULL; char *temp_buffer = NULL; char *processed_buffer = NULL; - int early_timeout = FALSE; - double exectime; struct timeval start_time, end_time; struct timeval method_start_time, method_end_time; int macro_options = STRIP_ILLEGAL_MACRO_CHARS | ESCAPE_MACRO_CHARS; int neb_result; - log_debug_info(DEBUGL_FUNCTIONS, 0, "notify_contact_of_service()\n"); log_debug_info(DEBUGL_NOTIFICATIONS, 2, "** Notifying contact '%s'\n", cntct->name); @@ -817,12 +823,7 @@ int notify_contact_of_service(nagios_macros *mac, contact *cntct, service *svc, } /* run the notification command */ - my_system_r(mac, processed_command, notification_timeout, &early_timeout, &exectime, NULL, 0); - - /* check to see if the notification command timed out */ - if(early_timeout == TRUE) { - logit(NSLOG_SERVICE_NOTIFICATION | NSLOG_RUNTIME_WARNING, TRUE, "Warning: Contact '%s' service notification command '%s' timed out after %d seconds\n", cntct->name, processed_command, notification_timeout); - } + wproc_notify(cntct->name, svc->host_name, svc->description, processed_command, mac); /* free memory */ my_free(command_name); @@ -887,18 +888,12 @@ int is_valid_escalation_for_service_notification(service *svc, serviceescalation if(se->last_notification != 0 && se->last_notification < notification_number) return FALSE; - /* skip this escalation if it has a timeperiod and the current time isn't valid */ - if(se->escalation_period != NULL && check_time_against_period(current_time, se->escalation_period_ptr) == ERROR) + /* skip this escalation if the state options don't match */ + if(flag_isset(se->escalation_options, 1 << svc->current_state) == FALSE) return FALSE; - /* skip this escalation if the state options don't match */ - if(svc->current_state == STATE_OK && se->escalate_on_recovery == FALSE) - return FALSE; - else if(svc->current_state == STATE_WARNING && se->escalate_on_warning == FALSE) - return FALSE; - else if(svc->current_state == STATE_UNKNOWN && se->escalate_on_unknown == FALSE) - return FALSE; - else if(svc->current_state == STATE_CRITICAL && se->escalate_on_critical == FALSE) + /* skip this escalation if it has a timeperiod and the current time isn't valid */ + if(se->escalation_period != NULL && check_time_against_period(current_time, se->escalation_period_ptr) == ERROR) return FALSE; return TRUE; @@ -907,13 +902,13 @@ int is_valid_escalation_for_service_notification(service *svc, serviceescalation /* checks to see whether a service notification should be escalation */ int should_service_notification_be_escalated(service *svc) { - serviceescalation *temp_se = NULL; - void *ptr = NULL; + objectlist *list; log_debug_info(DEBUGL_FUNCTIONS, 0, "should_service_notification_be_escalated()\n"); /* search the service escalation list */ - for(temp_se = get_first_serviceescalation_by_service(svc->host_name, svc->description, &ptr); temp_se != NULL; temp_se = get_next_serviceescalation_by_service(svc->host_name, svc->description, &ptr)) { + for (list = svc->escalation_list; list; list = list->next) { + serviceescalation *temp_se = (serviceescalation *)list->object_ptr; /* we found a matching entry, so escalate this notification! */ if(is_valid_escalation_for_service_notification(svc, temp_se, NOTIFICATION_OPTION_NONE) == TRUE) { @@ -936,7 +931,6 @@ int create_notification_list_from_service(nagios_macros *mac, service *svc, int contactgroupsmember *temp_contactgroupsmember = NULL; contactgroup *temp_contactgroup = NULL; int escalate_notification = FALSE; - void *ptr = NULL; log_debug_info(DEBUGL_FUNCTIONS, 0, "create_notification_list_from_service()\n"); @@ -958,11 +952,13 @@ int create_notification_list_from_service(nagios_macros *mac, service *svc, int /* use escalated contacts for this notification */ if(escalate_notification == TRUE || (options & NOTIFICATION_OPTION_BROADCAST)) { + objectlist *list; log_debug_info(DEBUGL_NOTIFICATIONS, 1, "Adding contacts from service escalation(s) to notification list.\n"); /* search all the escalation entries for valid matches */ - for(temp_se = get_first_serviceescalation_by_service(svc->host_name, svc->description, &ptr); temp_se != NULL; temp_se = get_next_serviceescalation_by_service(svc->host_name, svc->description, &ptr)) { + for(list = svc->escalation_list; list; list = list->next) { + temp_se = (serviceescalation *)list->object_ptr; /* skip this entry if it isn't appropriate */ if(is_valid_escalation_for_service_notification(svc, temp_se, options) == FALSE) @@ -975,10 +971,10 @@ int create_notification_list_from_service(nagios_macros *mac, service *svc, int if((temp_contact = temp_contactsmember->contact_ptr) == NULL) continue; /* check now if the contact can be notified */ - if(check_contact_service_notification_viability(temp_contact, svc, type, options) == OK) + if (check_contact_service_notification_viability(temp_contact, svc, type, options) == OK) add_notification(mac, temp_contact); else - log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Not adding contact '%s'\n", temp_contact->name); + log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Not adding contact '%s'\n",temp_contact->name); } log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Adding members of contact groups from service escalation(s) to notification list.\n"); @@ -992,10 +988,10 @@ int create_notification_list_from_service(nagios_macros *mac, service *svc, int if((temp_contact = temp_contactsmember->contact_ptr) == NULL) continue; /* check now if the contact can be notified */ - if(check_contact_service_notification_viability(temp_contact, svc, type, options) == OK) + if (check_contact_service_notification_viability(temp_contact, svc, type, options) == OK) add_notification(mac, temp_contact); else - log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Not adding contact '%s'\n", temp_contact->name); + log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Not adding contact '%s'\n",temp_contact->name); } } } @@ -1011,10 +1007,10 @@ int create_notification_list_from_service(nagios_macros *mac, service *svc, int if((temp_contact = temp_contactsmember->contact_ptr) == NULL) continue; /* check now if the contact can be notified */ - if(check_contact_service_notification_viability(temp_contact, svc, type, options) == OK) - add_notification(mac, temp_contact); - else - log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Not adding contact '%s'\n", temp_contact->name); + if (check_contact_service_notification_viability(temp_contact, svc, type, options) == OK) + add_notification(mac, temp_contact); + else + log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Not adding contact '%s'\n",temp_contact->name); } /* add all contacts that belong to contactgroups for this service */ @@ -1025,11 +1021,11 @@ int create_notification_list_from_service(nagios_macros *mac, service *svc, int for(temp_contactsmember = temp_contactgroup->members; temp_contactsmember != NULL; temp_contactsmember = temp_contactsmember->next) { if((temp_contact = temp_contactsmember->contact_ptr) == NULL) continue; - /* check now if the contact can be notified */ - if(check_contact_service_notification_viability(temp_contact, svc, type, options) == OK) - add_notification(mac, temp_contact); - else - log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Not adding contact '%s'\n", temp_contact->name); + /* check now if the contact can be notified */ + if (check_contact_service_notification_viability(temp_contact, svc, type, options) == OK) + add_notification(mac, temp_contact); + else + log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Not adding contact '%s'\n",temp_contact->name); } } } @@ -1064,7 +1060,7 @@ int host_notification(host *hst, int type, char *not_author, char *not_data, int time(¤t_time); gettimeofday(&start_time, NULL); - log_debug_info(DEBUGL_NOTIFICATIONS, 0, "** Host Notification Attempt ** Host: '%s', Type: %d, Options: %d, Current State: %d, Last Notification: %s", hst->name, type, options, hst->current_state, ctime(&hst->last_host_notification)); + log_debug_info(DEBUGL_NOTIFICATIONS, 0, "** Host Notification Attempt ** Host: '%s', Type: %s, Options: %d, Current State: %d, Last Notification: %s", hst->name, notification_reason_name(type), options, hst->current_state, ctime(&hst->last_notification)); /* check viability of sending out a host notification */ @@ -1094,36 +1090,31 @@ int host_notification(host *hst, int type, char *not_author, char *not_data, int end_time.tv_sec = 0L; end_time.tv_usec = 0L; neb_result = broker_notification_data(NEBTYPE_NOTIFICATION_START, NEBFLAG_NONE, NEBATTR_NONE, HOST_NOTIFICATION, type, start_time, end_time, (void *)hst, not_author, not_data, escalated, 0, NULL); - if(NEBERROR_CALLBACKCANCEL == neb_result) { + if(neb_result == NEBERROR_CALLBACKCANCEL || neb_result == NEBERROR_CALLBACKOVERRIDE) { + log_debug_info(DEBUGL_NOTIFICATIONS, 0, "Host notification to %s (id=%u) was blocked by a module.\n", hst->name, hst->id); free_notification_list(); - return ERROR; - } - else if(NEBERROR_CALLBACKOVERRIDE == neb_result) { - free_notification_list(); - return OK; + return neb_result == NEBERROR_CALLBACKOVERRIDE ? OK : ERROR; } #endif /* reset memory for local macro data */ memset(&mac, 0, sizeof(mac)); - /* 2011-11-01 MF: - check viability before adding a contact - to the notification list, requires type - this prevents us from running through all - the steps until notify_contact_of_host|service - is reached. furthermore the $NOTIFICATIONRECIPIENTS$ - macro only gets populated with actual recipients, - not all contacts assigned to that host|service. - - note: checks against timeperiod will happen now(), - and not when the notification is actually being sent. - - original patch by Opsview Team - */ + /* + * check viability before adding a contact to the notification + * list and build up the $NOTIFICATIONRECIPIENTS$ macro while + * we're at it. + * This prevents us from running through all the steps again in + * notify_contact_of_host|service. + * Furthermore the $NOTIFICATIONRECIPIENTS$ macro will contain + * only actual recipients (as the name implies), and not all + * contacts assigned to that host|service. + * + * note: checks against timeperiod will happen now(), + * and not when the notification is actually being sent. + */ create_notification_list_from_host(&mac, hst, options, &escalated, type); - /* XXX: crazy indent */ /* there are contacts to be notified... */ if(notification_list != NULL) { @@ -1132,14 +1123,7 @@ int host_notification(host *hst, int type, char *not_author, char *not_data, int /* if this notification has an author, attempt to lookup the associated contact */ if(not_author != NULL) { - - /* see if we can find the contact - first by name, then by alias */ - if((temp_contact = find_contact(not_author)) == NULL) { - for(temp_contact = contact_list; temp_contact != NULL; temp_contact = temp_contact->next) { - if(!strcmp(temp_contact->alias, not_author)) - break; - } - } + temp_contact = find_contact_by_name_or_alias(not_author); } /* get author and comment macros */ @@ -1243,8 +1227,11 @@ int host_notification(host *hst, int type, char *not_author, char *not_data, int */ clear_summary_macros_r(&mac); clear_contact_macros_r(&mac); + clear_contactgroup_macros_r(&mac); clear_argv_macros_r(&mac); clear_host_macros_r(&mac); + clear_hostgroup_macros_r(&mac); + clear_datetime_macros_r(&mac); if(type == NOTIFICATION_NORMAL) { @@ -1252,18 +1239,15 @@ int host_notification(host *hst, int type, char *not_author, char *not_data, int if(contacts_notified > 0) { /* calculate the next acceptable re-notification time */ - hst->next_host_notification = get_next_host_notification_time(hst, current_time); + hst->next_notification = get_next_host_notification_time(hst, current_time); /* update the last notification time for this host (this is needed for scheduling the next problem notification) */ - hst->last_host_notification = current_time; + hst->last_notification = current_time; /* update notifications flags */ - if(hst->current_state == HOST_DOWN) - hst->notified_on_down = TRUE; - else if(hst->current_state == HOST_UNREACHABLE) - hst->notified_on_unreachable = TRUE; + add_notified_on(hst, hst->current_state); - log_debug_info(DEBUGL_NOTIFICATIONS, 0, "%d contacts were notified. Next possible notification time: %s", contacts_notified, ctime(&hst->next_host_notification)); + log_debug_info(DEBUGL_NOTIFICATIONS, 0, "%d contacts were notified. Next possible notification time: %s", contacts_notified, ctime(&hst->next_notification)); } /* we didn't end up notifying anyone */ @@ -1272,7 +1256,7 @@ int host_notification(host *hst, int type, char *not_author, char *not_data, int /* adjust current notification number */ hst->current_notification_number--; - log_debug_info(DEBUGL_NOTIFICATIONS, 0, "No contacts were notified. Next possible notification time: %s", ctime(&hst->next_host_notification)); + log_debug_info(DEBUGL_NOTIFICATIONS, 0, "No contacts were notified. Next possible notification time: %s", ctime(&hst->next_notification)); } } @@ -1343,13 +1327,13 @@ int check_host_notification_viability(host *hst, int type, int options) { /* it looks like there is no notification time defined, so schedule next one far into the future (one year)... */ if(timeperiod_start == (time_t)0) - hst->next_host_notification = (time_t)(current_time + (60 * 60 * 24 * 365)); + hst->next_notification = (time_t)(current_time + (60 * 60 * 24 * 365)); /* else use the next valid notification time */ else - hst->next_host_notification = timeperiod_start; + hst->next_notification = timeperiod_start; - log_debug_info(DEBUGL_NOTIFICATIONS, 1, "Next possible notification time: %s\n", ctime(&hst->next_host_notification)); + log_debug_info(DEBUGL_NOTIFICATIONS, 1, "Next possible notification time: %s\n", ctime(&hst->next_notification)); } return ERROR; @@ -1377,9 +1361,9 @@ int check_host_notification_viability(host *hst, int type, int options) { - /****************************************/ - /*** SPECIAL CASE FOR ACKNOWLEGEMENTS ***/ - /****************************************/ + /*****************************************/ + /*** SPECIAL CASE FOR ACKNOWLEDGEMENTS ***/ + /*****************************************/ /* acknowledgements only have to pass three general filters, although they have another test of their own... */ if(type == NOTIFICATION_ACKNOWLEDGEMENT) { @@ -1403,7 +1387,7 @@ int check_host_notification_viability(host *hst, int type, int options) { if(type == NOTIFICATION_FLAPPINGSTART || type == NOTIFICATION_FLAPPINGSTOP || type == NOTIFICATION_FLAPPINGDISABLED) { /* don't send a notification if we're not supposed to... */ - if(hst->notify_on_flapping == FALSE) { + if(!(hst->notification_options & OPT_FLAPPING)) { log_debug_info(DEBUGL_NOTIFICATIONS, 1, "We shouldn't notify about FLAPPING events for this host.\n"); return ERROR; } @@ -1427,7 +1411,7 @@ int check_host_notification_viability(host *hst, int type, int options) { if(type == NOTIFICATION_DOWNTIMESTART || type == NOTIFICATION_DOWNTIMEEND || type == NOTIFICATION_DOWNTIMECANCELLED) { /* don't send a notification if we're not supposed to... */ - if(hst->notify_on_downtime == FALSE) { + if((hst->notification_options & OPT_DOWNTIME) == FALSE) { log_debug_info(DEBUGL_NOTIFICATIONS, 1, "We shouldn't notify about DOWNTIME events for this host.\n"); return ERROR; } @@ -1466,21 +1450,17 @@ int check_host_notification_viability(host *hst, int type, int options) { } /* see if we should notify about problems with this host */ - if(hst->current_state == HOST_UNREACHABLE && hst->notify_on_unreachable == FALSE) { - log_debug_info(DEBUGL_NOTIFICATIONS, 1, "We shouldn't notify about UNREACHABLE status for this host.\n"); - return ERROR; - } - if(hst->current_state == HOST_DOWN && hst->notify_on_down == FALSE) { - log_debug_info(DEBUGL_NOTIFICATIONS, 1, "We shouldn't notify about DOWN states for this host.\n"); + if((hst->notification_options & (1 << hst->current_state)) == FALSE) { + log_debug_info(DEBUGL_NOTIFICATIONS, 1, "We shouldn't notify about %s status for this host.\n", host_state_name(hst->current_state)); return ERROR; } if(hst->current_state == HOST_UP) { - if(hst->notify_on_recovery == FALSE) { + if((hst->notification_options & OPT_RECOVERY) == FALSE) { log_debug_info(DEBUGL_NOTIFICATIONS, 1, "We shouldn't notify about RECOVERY states for this host.\n"); return ERROR; } - if(!(hst->notified_on_down == TRUE || hst->notified_on_unreachable == TRUE)) { + if(!hst->notified_on) { log_debug_info(DEBUGL_NOTIFICATIONS, 1, "We shouldn't notify about this recovery.\n"); return ERROR; } @@ -1492,14 +1472,9 @@ int check_host_notification_viability(host *hst, int type, int options) { /* it is reasonable to assume that if the host was never up, the program start time should be used in this calculation */ if(type == NOTIFICATION_NORMAL && hst->current_notification_number == 0 && hst->current_state != HOST_UP) { - /* determine the time to use of the first problem point */ - first_problem_time = hst->last_time_up; /* not accurate, but its the earliest time we could use in the comparison */ - if((hst->last_time_down < first_problem_time) && (hst->last_time_down > hst->last_time_up)) - first_problem_time = hst->last_time_down; - if((hst->last_time_unreachable < first_problem_time) && (hst->last_time_unreachable > hst->last_time_unreachable)) - first_problem_time = hst->last_time_unreachable; + first_problem_time = hst->last_time_up > 0 ? hst->last_time_up : program_start; - if(current_time < (time_t)((first_problem_time == (time_t)0L) ? program_start : first_problem_time) + (time_t)(hst->first_notification_delay * interval_length)) { + if(current_time < first_problem_time + (time_t)(hst->first_notification_delay * interval_length)) { log_debug_info(DEBUGL_NOTIFICATIONS, 1, "Not enough time has elapsed since the host changed to a non-UP state (or since program start), so we shouldn't notify about this problem yet.\n"); return ERROR; } @@ -1528,9 +1503,9 @@ int check_host_notification_viability(host *hst, int type, int options) { } /* check if its time to re-notify the contacts about the host... */ - if(current_time < hst->next_host_notification) { + if(current_time < hst->next_notification) { log_debug_info(DEBUGL_NOTIFICATIONS, 1, "Its not yet time to re-notify the contacts about this host problem...\n"); - log_debug_info(DEBUGL_NOTIFICATIONS, 1, "Next acceptable notification time: %s", ctime(&hst->next_host_notification)); + log_debug_info(DEBUGL_NOTIFICATIONS, 1, "Next acceptable notification time: %s", ctime(&hst->next_notification)); return ERROR; } @@ -1558,6 +1533,12 @@ int check_contact_host_notification_viability(contact *cntct, host *hst, int typ return ERROR; } + /* is this host important enough? */ + if(cntct->minimum_value > hst->hourly_value + host_services_value(hst)) { + log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Contact's minimum_importance is greater than the importance of the host and all its services. Notification will be blocked\n"); + return ERROR; + } + /* see if the contact can be notified at this time */ if(check_time_against_period(time(NULL), cntct->host_notification_period_ptr) == ERROR) { log_debug_info(DEBUGL_NOTIFICATIONS, 2, "This contact shouldn't be notified at this time.\n"); @@ -1580,7 +1561,7 @@ int check_contact_host_notification_viability(contact *cntct, host *hst, int typ if(type == NOTIFICATION_FLAPPINGSTART || type == NOTIFICATION_FLAPPINGSTOP || type == NOTIFICATION_FLAPPINGDISABLED) { - if(cntct->notify_on_host_flapping == FALSE) { + if((cntct->host_notification_options & OPT_FLAPPING) == FALSE) { log_debug_info(DEBUGL_NOTIFICATIONS, 2, "We shouldn't notify this contact about FLAPPING host events.\n"); return ERROR; } @@ -1595,7 +1576,7 @@ int check_contact_host_notification_viability(contact *cntct, host *hst, int typ if(type == NOTIFICATION_DOWNTIMESTART || type == NOTIFICATION_DOWNTIMEEND || type == NOTIFICATION_DOWNTIMECANCELLED) { - if(cntct->notify_on_host_downtime == FALSE) { + if(flag_isset(cntct->host_notification_options, OPT_DOWNTIME) == FALSE) { log_debug_info(DEBUGL_NOTIFICATIONS, 2, "We shouldn't notify this contact about DOWNTIME host events.\n"); return ERROR; } @@ -1609,30 +1590,16 @@ int check_contact_host_notification_viability(contact *cntct, host *hst, int typ /*************************************/ /* see if we should notify about problems with this host */ - if(hst->current_state == HOST_DOWN && cntct->notify_on_host_down == FALSE) { - log_debug_info(DEBUGL_NOTIFICATIONS, 2, "We shouldn't notify this contact about DOWN states.\n"); + if(flag_isset(cntct->host_notification_options, 1 << hst->current_state) == FALSE) { + log_debug_info(DEBUGL_NOTIFICATIONS, 2, "We shouldn't notify this contact about %s states.\n", host_state_name(hst->current_state)); return ERROR; } - if(hst->current_state == HOST_UNREACHABLE && cntct->notify_on_host_unreachable == FALSE) { - log_debug_info(DEBUGL_NOTIFICATIONS, 2, "We shouldn't notify this contact about UNREACHABLE states,\n"); + if(hst->current_state == HOST_UP && hst->notified_on == 0) { + log_debug_info(DEBUGL_NOTIFICATIONS, 2, "We shouldn't notify about this recovery.\n"); return ERROR; } - if(hst->current_state == HOST_UP) { - - if(cntct->notify_on_host_recovery == FALSE) { - log_debug_info(DEBUGL_NOTIFICATIONS, 2, "We shouldn't notify this contact about RECOVERY states.\n"); - return ERROR; - } - - if(!((hst->notified_on_down == TRUE && cntct->notify_on_host_down == TRUE) || (hst->notified_on_unreachable == TRUE && cntct->notify_on_host_unreachable == TRUE))) { - log_debug_info(DEBUGL_NOTIFICATIONS, 2, "We shouldn't notify about this recovery.\n"); - return ERROR; - } - - } - log_debug_info(DEBUGL_NOTIFICATIONS, 2, "** Host notification viability for contact '%s' PASSED.\n", cntct->name); return OK; @@ -1649,8 +1616,6 @@ int notify_contact_of_host(nagios_macros *mac, contact *cntct, host *hst, int ty char *processed_buffer = NULL; char *raw_command = NULL; char *processed_command = NULL; - int early_timeout = FALSE; - double exectime; struct timeval start_time; struct timeval end_time; struct timeval method_start_time; @@ -1755,12 +1720,9 @@ int notify_contact_of_host(nagios_macros *mac, contact *cntct, host *hst, int ty } /* run the notification command */ - my_system_r(mac, processed_command, notification_timeout, &early_timeout, &exectime, NULL, 0); + wproc_notify(cntct->name, hst->name, NULL, processed_command, mac); - /* check to see if the notification timed out */ - if(early_timeout == TRUE) { - logit(NSLOG_HOST_NOTIFICATION | NSLOG_RUNTIME_WARNING, TRUE, "Warning: Contact '%s' host notification command '%s' timed out after %d seconds\n", cntct->name, processed_command, notification_timeout); - } + /* @todo Handle nebmod stuff when getting results from workers */ /* free memory */ my_free(command_name); @@ -1825,16 +1787,12 @@ int is_valid_escalation_for_host_notification(host *hst, hostescalation *he, int if(he->last_notification != 0 && he->last_notification < notification_number) return FALSE; - /* skip this escalation if it has a timeperiod and the current time isn't valid */ - if(he->escalation_period != NULL && check_time_against_period(current_time, he->escalation_period_ptr) == ERROR) + /* skip this escalation if the state options don't match */ + if(flag_isset(he->escalation_options, 1 << hst->current_state) == FALSE) return FALSE; - /* skip this escalation if the state options don't match */ - if(hst->current_state == HOST_UP && he->escalate_on_recovery == FALSE) - return FALSE; - else if(hst->current_state == HOST_DOWN && he->escalate_on_down == FALSE) - return FALSE; - else if(hst->current_state == HOST_UNREACHABLE && he->escalate_on_unreachable == FALSE) + /* skip this escalation if it has a timeperiod and the current time isn't valid */ + if(he->escalation_period != NULL && check_time_against_period(current_time, he->escalation_period_ptr) == ERROR) return FALSE; return TRUE; @@ -1844,8 +1802,7 @@ int is_valid_escalation_for_host_notification(host *hst, hostescalation *he, int /* checks to see whether a host notification should be escalation */ int should_host_notification_be_escalated(host *hst) { - hostescalation *temp_he = NULL; - void *ptr = NULL; + objectlist *list; log_debug_info(DEBUGL_FUNCTIONS, 0, "should_host_notification_be_escalated()\n"); @@ -1853,8 +1810,8 @@ int should_host_notification_be_escalated(host *hst) { return FALSE; /* search the host escalation list */ - for(temp_he = get_first_hostescalation_by_host(hst->name, &ptr); temp_he != NULL; temp_he = get_next_hostescalation_by_host(hst->name, &ptr)) { - + for (list = hst->escalation_list; list; list = list->next) { + hostescalation *temp_he = (hostescalation *)list->object_ptr; /* we found a matching entry, so escalate this notification! */ if(is_valid_escalation_for_host_notification(hst, temp_he, NOTIFICATION_OPTION_NONE) == TRUE) return TRUE; @@ -1874,7 +1831,6 @@ int create_notification_list_from_host(nagios_macros *mac, host *hst, int option contactgroupsmember *temp_contactgroupsmember = NULL; contactgroup *temp_contactgroup = NULL; int escalate_notification = FALSE; - void *ptr = NULL; log_debug_info(DEBUGL_FUNCTIONS, 0, "create_notification_list_from_host()\n"); @@ -1895,11 +1851,13 @@ int create_notification_list_from_host(nagios_macros *mac, host *hst, int option /* use escalated contacts for this notification */ if(escalate_notification == TRUE || (options & NOTIFICATION_OPTION_BROADCAST)) { + objectlist *list; log_debug_info(DEBUGL_NOTIFICATIONS, 1, "Adding contacts from host escalation(s) to notification list.\n"); /* check all the host escalation entries */ - for(temp_he = get_first_hostescalation_by_host(hst->name, &ptr); temp_he != NULL; temp_he = get_next_hostescalation_by_host(hst->name, &ptr)) { + for(list = hst->escalation_list; list; list = list->next) { + temp_he = (hostescalation *)list->object_ptr; /* see if this escalation if valid for this notification */ if(is_valid_escalation_for_host_notification(hst, temp_he, options) == FALSE) @@ -1912,7 +1870,7 @@ int create_notification_list_from_host(nagios_macros *mac, host *hst, int option if((temp_contact = temp_contactsmember->contact_ptr) == NULL) continue; /* check now if the contact can be notified */ - if(check_contact_host_notification_viability(temp_contact, hst, type, options) == OK) + if (check_contact_host_notification_viability(temp_contact, hst, type, options) == OK) add_notification(mac, temp_contact); else log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Not adding contact '%s'\n", temp_contact->name); @@ -1928,11 +1886,11 @@ int create_notification_list_from_host(nagios_macros *mac, host *hst, int option for(temp_contactsmember = temp_contactgroup->members; temp_contactsmember != NULL; temp_contactsmember = temp_contactsmember->next) { if((temp_contact = temp_contactsmember->contact_ptr) == NULL) continue; - /* check now if the contact can be notified */ - if(check_contact_host_notification_viability(temp_contact, hst, type, options) == OK) - add_notification(mac, temp_contact); - else - log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Not adding contact '%s'\n", temp_contact->name); + /* check now if the contact can be notified */ + if (check_contact_host_notification_viability(temp_contact, hst, type, options) == OK) + add_notification(mac, temp_contact); + else + log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Not adding contact '%s'\n", temp_contact->name); } } } @@ -1949,11 +1907,11 @@ int create_notification_list_from_host(nagios_macros *mac, host *hst, int option for(temp_contactsmember = hst->contacts; temp_contactsmember != NULL; temp_contactsmember = temp_contactsmember->next) { if((temp_contact = temp_contactsmember->contact_ptr) == NULL) continue; - /* check now if the contact can be notified */ - if(check_contact_host_notification_viability(temp_contact, hst, type, options) == OK) - add_notification(mac, temp_contact); - else - log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Not adding contact '%s'\n", temp_contact->name); + /* check now if the contact can be notified */ + if (check_contact_host_notification_viability(temp_contact, hst, type, options) == OK) + add_notification(mac, temp_contact); + else + log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Not adding contact '%s'\n", temp_contact->name); } log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Adding members of contact groups for host to notification list.\n"); @@ -1967,11 +1925,11 @@ int create_notification_list_from_host(nagios_macros *mac, host *hst, int option for(temp_contactsmember = temp_contactgroup->members; temp_contactsmember != NULL; temp_contactsmember = temp_contactsmember->next) { if((temp_contact = temp_contactsmember->contact_ptr) == NULL) continue; - /* check now if the contact can be notified */ - if(check_contact_host_notification_viability(temp_contact, hst, type, options) == OK) - add_notification(mac, temp_contact); - else - log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Not adding contact '%s'\n", temp_contact->name); + /* check now if the contact can be notified */ + if (check_contact_host_notification_viability(temp_contact, hst, type, options) == OK) + add_notification(mac, temp_contact); + else + log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Not adding contact '%s'\n", temp_contact->name); } } } @@ -1991,7 +1949,7 @@ int create_notification_list_from_host(nagios_macros *mac, host *hst, int option time_t get_next_service_notification_time(service *svc, time_t offset) { time_t next_notification = 0L; double interval_to_use = 0.0; - serviceescalation *temp_se = NULL; + objectlist *list; int have_escalated_interval = FALSE; log_debug_info(DEBUGL_FUNCTIONS, 0, "get_next_service_notification_time()\n"); @@ -2004,7 +1962,8 @@ time_t get_next_service_notification_time(service *svc, time_t offset) { log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Default interval: %f\n", interval_to_use); /* search all the escalation entries for valid matches for this service (at its current notification number) */ - for(temp_se = serviceescalation_list; temp_se != NULL; temp_se = temp_se->next) { + for(list = svc->escalation_list; list; list = list->next) { + serviceescalation *temp_se = (serviceescalation *)list->object_ptr; /* interval < 0 means to use non-escalated interval */ if(temp_se->notification_interval < 0.0) @@ -2049,7 +2008,7 @@ time_t get_next_service_notification_time(service *svc, time_t offset) { time_t get_next_host_notification_time(host *hst, time_t offset) { time_t next_notification = 0L; double interval_to_use = 0.0; - hostescalation *temp_he = NULL; + objectlist *list; int have_escalated_interval = FALSE; @@ -2063,7 +2022,8 @@ time_t get_next_host_notification_time(host *hst, time_t offset) { log_debug_info(DEBUGL_NOTIFICATIONS, 2, "Default interval: %f\n", interval_to_use); /* check all the host escalation entries for valid matches for this host (at its current notification number) */ - for(temp_he = hostescalation_list; temp_he != NULL; temp_he = temp_he->next) { + for(list = hst->escalation_list; list; list = list->next) { + hostescalation *temp_he = (hostescalation *)list->object_ptr; /* interval < 0 means to use non-escalated interval */ if(temp_he->notification_interval < 0.0) diff --git a/base/perfdata.c b/base/perfdata.c index 111082d..8b07aac 100644 --- a/base/perfdata.c +++ b/base/perfdata.c @@ -2,8 +2,6 @@ * * PERFDATA.C - Performance data routines for Nagios * - * Copyright (c) 2000-2004 Ethan Galstad (egalstad@nagios.org) - * Last Modified: 11-29-2004 * * License: * @@ -30,16 +28,7 @@ #include "../include/objects.h" #include "../include/perfdata.h" #include "../include/macros.h" - -/***** IMPLEMENTATION-SPECIFIC HEADER FILES *****/ - -#ifdef USE_XPDDEFAULT #include "../xdata/xpddefault.h" -#endif - - -extern int process_performance_data; - /******************************************************************/ @@ -47,25 +36,15 @@ extern int process_performance_data; /******************************************************************/ /* initializes performance data */ -int initialize_performance_data(char *config_file) { - -#ifdef USE_XPDDEFAULT - xpddefault_initialize_performance_data(config_file); -#endif - - return OK; +int initialize_performance_data(const char *cfgfile) { + return xpddefault_initialize_performance_data(cfgfile); } /* cleans up performance data */ -int cleanup_performance_data(char *config_file) { - -#ifdef USE_XPDDEFAULT - xpddefault_cleanup_performance_data(config_file); -#endif - - return OK; +int cleanup_performance_data(void) { + return xpddefault_cleanup_performance_data(); } @@ -87,9 +66,7 @@ int update_service_performance_data(service *svc) { return OK; /* process the performance data! */ -#ifdef USE_XPDDEFAULT xpddefault_update_service_performance_data(svc); -#endif return OK; } @@ -108,9 +85,7 @@ int update_host_performance_data(host *hst) { return OK; /* process the performance data! */ -#ifdef USE_XPDDEFAULT xpddefault_update_host_performance_data(hst); -#endif return OK; } diff --git a/base/query-handler.c b/base/query-handler.c new file mode 100644 index 0000000..44b0dfc --- /dev/null +++ b/base/query-handler.c @@ -0,0 +1,430 @@ +#include "include/config.h" +#include "include/nagios.h" +#include "lib/libnagios.h" +#include "lib/nsock.h" +#include +#include +#include + +/* A registered handler */ +struct query_handler { + const char *name; /* also "address" of this handler. Must be unique */ + const char *description; /* short description of this handler */ + unsigned int options; + qh_handler handler; + struct query_handler *prev_qh, *next_qh; +}; + +static struct query_handler *qhandlers; +static int qh_listen_sock = -1; /* the listening socket */ +static unsigned int qh_running; +unsigned int qh_max_running = 0; /* defaults to unlimited */ +static dkhash_table *qh_table; + +/* the echo service. stupid, but useful for testing */ +static int qh_echo(int sd, char *buf, unsigned int len) +{ + if (!strcmp(buf, "help")) { + nsock_printf_nul(sd, + "Query handler that simply echoes back what you send it."); + return 0; + } + (void)write(sd, buf, len); + return 0; +} + +static struct query_handler *qh_find_handler(const char *name) +{ + return (struct query_handler *)dkhash_get(qh_table, name, NULL); +} + +/* subset of http error codes */ +const char *qh_strerror(int code) +{ + if (code < 0) + return "Low-level system error"; + + if (code == 100) + return "Continue"; + if (code == 101) + return "Switching protocols"; + + if (code < 300) + return "OK"; + + if (code < 400) + return "Redirected (possibly deprecated address)"; + + switch (code) { + /* client errors */ + case 400: return "Bad request"; + case 401: return "Unauthorized"; + case 403: return "Forbidden (disabled by config)"; + case 404: return "Not found"; + case 405: return "Method not allowed"; + case 406: return "Not acceptable"; + case 407: return "Proxy authentication required"; + case 408: return "Request timed out"; + case 409: return "Conflict"; + case 410: return "Gone"; + case 411: return "Length required"; + case 412: return "Precondition failed"; + case 413: return "Request too large"; + case 414: return "Request-URI too long"; + + /* server errors */ + case 500: return "Internal server error"; + case 501: return "Not implemented"; + case 502: return "Bad gateway"; + case 503: return "Service unavailable"; + case 504: return "Gateway timeout"; + case 505: return "Version not supported"; + } + return "Unknown error"; +} + +static int qh_input(int sd, int events, void *ioc_) +{ + iocache *ioc = (iocache *)ioc_; + + /* input on main socket, so accept one */ + if(sd == qh_listen_sock) { + struct sockaddr sa; + socklen_t slen = 0; + int nsd; + + memset(&sa, 0, sizeof(sa)); /* shut valgrind up */ + nsd = accept(sd, &sa, &slen); + if(qh_max_running && qh_running >= qh_max_running) { + nsock_printf(nsd, "503: Server full"); + close(nsd); + return 0; + } + + if(!(ioc = iocache_create(16384))) { + logit(NSLOG_RUNTIME_ERROR, TRUE, "qh: Failed to create iocache for inbound request\n"); + nsock_printf(nsd, "500: Internal server error"); + close(nsd); + return 0; + } + + /* + * @todo: Stash the iocache and the socket in some + * addressable list so we can release them on deinit + */ + if(iobroker_register(nagios_iobs, nsd, ioc, qh_input) < 0) { + logit(NSLOG_RUNTIME_ERROR, TRUE, "qh: Failed to register input socket %d with I/O broker: %s\n", nsd, strerror(errno)); + iocache_destroy(ioc); + close(nsd); + return 0; + } + + /* make it non-blocking, but leave kernel buffers unchanged */ + worker_set_sockopts(nsd, 0); + qh_running++; + return 0; + } + else { + int result; + unsigned long len; + unsigned int query_len = 0; + char *buf, *space; + struct query_handler *qh; + char *handler = NULL, *query = NULL; + + result = iocache_read(ioc, sd); + /* disconnect? */ + if(result == 0 || (result < 0 && errno == EPIPE)) { + iocache_destroy(ioc); + iobroker_close(nagios_iobs, sd); + qh_running--; + return 0; + } + + /* + * A request looks like this: '[@|#][][]\0'. + * That is, optional '#' (oneshot) or '@' (keepalive), + * followed by the name of a registered handler, followed by + * an optional space and an optional query. If the handler + * has no "default" handler, a query is required or an error + * will be thrown. + */ + + /* Use data up to the first nul byte */ + buf = iocache_use_delim(ioc, "\0", 1, &len); + if(!buf) + return 0; + + /* Identify handler part and any magic query bytes */ + if (*buf == '@' || *buf == '#') { + handler = buf + 1; + } + + /* Locate query (if any) */ + if((space = strchr(buf, ' '))) { + *space = 0; + query = space + 1; + query_len = len - ((unsigned long)query - (unsigned long)buf); + } else { + query = ""; + query_len = 0; + } + + /* locate the handler */ + if(!(qh = qh_find_handler(handler))) { + /* not found. that's a 404 */ + nsock_printf(sd, "404: %s: No such handler", handler); + iobroker_close(nagios_iobs, sd); + iocache_destroy(ioc); + return 0; + } + + /* strip trailing newlines */ + while (query_len > 0 && (query[query_len - 1] == 0 || query[query_len - 1] == '\n')) + query[--query_len] = 0; + + /* now pass the query to the handler */ + if ((result = qh->handler(sd, query, query_len)) >= 100) { + nsock_printf_nul(sd, "%d: %s", result, qh_strerror(result)); + } + + if(result >= 300 || *buf == '#') { + /* error code or one-shot query */ + iobroker_close(nagios_iobs, sd); + iocache_destroy(ioc); + return 0; + } + + /* check for magic handler codes */ + switch (result) { + case QH_CLOSE: /* oneshot handler */ + case -1: /* general error */ + iobroker_close(nagios_iobs, sd); + /* fallthrough */ + case QH_TAKEOVER: /* handler takes over */ + case 101: /* switch protocol (takeover + message) */ + iocache_destroy(ioc); + break; + } + } + return 0; +} + +int qh_deregister_handler(const char *name) +{ + struct query_handler *qh, *next, *prev; + + if (!(qh = dkhash_remove(qh_table, name, NULL))) + return 0; + + next = qh->next_qh; + prev = qh->prev_qh; + if (next) + next->prev_qh = prev; + if (prev) + prev->next_qh = next; + else + qhandlers = next; + + free(qh); + + return 0; +} + +int qh_register_handler(const char *name, const char *description, unsigned int options, qh_handler handler) +{ + struct query_handler *qh; + int result; + + if(!name) + return -1; + + if(!handler) { + logit(NSLOG_RUNTIME_ERROR, TRUE, "qh: Failed to register handler '%s': No handler function specified\n", name); + return -1; + } + + if(strlen(name) > 128) { + logit(NSLOG_RUNTIME_ERROR, TRUE, "qh: Failed to register handler '%s': Name too long\n", name); + return -ENAMETOOLONG; + } + + /* names must be unique */ + if(qh_find_handler(name)) { + logit(NSLOG_RUNTIME_WARNING, TRUE, "qh: Handler '%s' registered more than once\n", name); + return -1; + } + + if (!(qh = calloc(1, sizeof(*qh)))) { + logit(NSLOG_RUNTIME_ERROR, TRUE, "qh: Failed to allocate memory for handler '%s'\n", name); + return -errno; + } + + qh->name = name; + qh->description = description; + qh->handler = handler; + qh->options = options; + qh->next_qh = qhandlers; + if (qhandlers) + qhandlers->prev_qh = qh; + qhandlers = qh; + + result = dkhash_insert(qh_table, qh->name, NULL, qh); + if(result < 0) { + logit(NSLOG_RUNTIME_ERROR, TRUE, + "qh: Failed to insert query handler '%s' (%p) into hash table %p (%d): %s\n", + name, qh, qh_table, result, strerror(errno)); + free(qh); + return result; + } + + return 0; +} + +void qh_deinit(const char *path) +{ + struct query_handler *qh, *next; + + for(qh = qhandlers; qh; qh = next) { + next = qh->next_qh; + qh_deregister_handler(qh->name); + } + dkhash_destroy(qh_table); + qh_table = NULL; + qhandlers = NULL; + + if(!path) + return; + + unlink(path); +} + +static int qh_help(int sd, char *buf, unsigned int len) +{ + struct query_handler *qh; + + if (!*buf || !strcmp(buf, "help")) { + nsock_printf_nul(sd, + " help show help for handler \n" + " help list list registered handlers\n"); + return 0; + } + + if (!strcmp(buf, "list")) { + for (qh = qhandlers; qh; qh = qh->next_qh) { + nsock_printf(sd, "%-10s %s\n", qh->name, qh->description ? qh->description : "(No description available)"); + } + nsock_printf(sd, "%c", 0); + return 0; + } + + if (!(qh = qh_find_handler(buf))) { + nsock_printf_nul(sd, "No handler named '%s' is registered\n", buf); + } else if (qh->handler(sd, "help", 4) > 200) { + nsock_printf_nul(sd, "The handler %s doesn't have any help yet.", buf); + } + + return 0; +} + +static int qh_core(int sd, char *buf, unsigned int len) +{ + char *space; + + if (!*buf || !strcmp(buf, "help")) { + nsock_printf_nul(sd, "Query handler for manipulating nagios core.\n" + "Available commands:\n" + " loadctl Print information about current load control settings\n" + " loadctl Configure nagios load control.\n" + " The options are the same parameters and format as\n" + " returned above.\n" + " squeuestats scheduling queue statistics\n" + ); + return 0; + } + if ((space = memchr(buf, ' ', len))) + *(space++) = 0; + if (!space && !strcmp(buf, "loadctl")) { + nsock_printf_nul + (sd, "jobs_max=%u;jobs_min=%u;" + "jobs_running=%u;jobs_limit=%u;" + "load=%.2f;" + "backoff_limit=%.2f;backoff_change=%u;" + "rampup_limit=%.2f;rampup_change=%u;" + "nproc_limit=%u;nofile_limit=%u;" + "options=%u;changes=%u;", + loadctl.jobs_max, loadctl.jobs_min, + loadctl.jobs_running, loadctl.jobs_limit, + loadctl.load[0], + loadctl.backoff_limit, loadctl.backoff_change, + loadctl.rampup_limit, loadctl.rampup_change, + loadctl.nproc_limit, loadctl.nofile_limit, + loadctl.options, loadctl.changes); + return 0; + } + + if (!space && !strcmp(buf, "squeuestats")) + return dump_event_stats(sd); + + if (space) { + len -= (unsigned long)space - (unsigned long)buf; + if (!strcmp(buf, "loadctl")) { + return set_loadctl_options(space, len) == OK ? 200 : 400; + } + } + + /* No matching command found */ + return 404; +} + +int qh_init(const char *path) +{ + int result, old_umask; + + if(qh_listen_sock >= 0) + iobroker_close(nagios_iobs, qh_listen_sock); + + if(!path) { + logit(NSLOG_RUNTIME_ERROR, TRUE, "qh: query_socket is NULL. What voodoo is this?\n"); + return ERROR; + } + + old_umask = umask(0117); + errno = 0; + qh_listen_sock = nsock_unix(path, NSOCK_TCP | NSOCK_UNLINK); + umask(old_umask); + if(qh_listen_sock < 0) { + logit(NSLOG_RUNTIME_ERROR, TRUE, "qh: Failed to init socket '%s'. %s: %s\n", + path, nsock_strerror(qh_listen_sock), strerror(errno)); + return ERROR; + } + + /* plugins shouldn't have this socket */ + (void)fcntl(qh_listen_sock, F_SETFD, FD_CLOEXEC); + + /* most likely overkill, but it's small, so... */ + if(!(qh_table = dkhash_create(1024))) { + logit(NSLOG_RUNTIME_ERROR, TRUE, "qh: Failed to create hash table\n"); + close(qh_listen_sock); + return ERROR; + } + + errno = 0; + result = iobroker_register(nagios_iobs, qh_listen_sock, NULL, qh_input); + if(result < 0) { + dkhash_destroy(qh_table); + close(qh_listen_sock); + logit(NSLOG_RUNTIME_ERROR, TRUE, "qh: Failed to register socket with io broker: %s; errno=%d: %s\n", iobroker_strerror(result), errno, strerror(errno)); + return ERROR; + } + + logit(NSLOG_INFO_MESSAGE, FALSE, "qh: Socket '%s' successfully initialized\n", path); + + /* now register our the in-core handlers */ + if(!qh_register_handler("core", "Nagios Core control and info", 0, qh_core)) + logit(NSLOG_INFO_MESSAGE, FALSE, "qh: core query handler registered\n"); + qh_register_handler("echo", "The Echo Service - What You Put Is What You Get", 0, qh_echo); + qh_register_handler("help", "Help for the query handler", 0, qh_help); + + return 0; +} diff --git a/base/sehandlers.c b/base/sehandlers.c index fbecc07..c51d904 100644 --- a/base/sehandlers.c +++ b/base/sehandlers.c @@ -2,8 +2,6 @@ * * SEHANDLERS.C - Service and host event and state handlers for Nagios * - * Copyright (c) 1999-2010 Ethan Galstad (egalstad@nagios.org) - * Last Modified: 08-05-2010 * * License: * @@ -31,38 +29,12 @@ #include "../include/nagios.h" #include "../include/perfdata.h" #include "../include/broker.h" +#include "../include/workers.h" #ifdef USE_EVENT_BROKER #include "../include/neberrors.h" #endif -extern int enable_event_handlers; -extern int obsess_over_services; -extern int obsess_over_hosts; - -extern int log_event_handlers; - -extern unsigned long next_event_id; -extern unsigned long next_problem_id; - -extern int event_handler_timeout; -extern int ocsp_timeout; -extern int ochp_timeout; - -extern char *global_host_event_handler; -extern char *global_service_event_handler; -extern command *global_host_event_handler_ptr; -extern command *global_service_event_handler_ptr; - -extern char *ocsp_command; -extern char *ochp_command; -extern command *ocsp_command_ptr; -extern command *ochp_command_ptr; - -extern time_t program_start; - - - /******************************************************************/ /************* OBSESSIVE COMPULSIVE HANDLER FUNCTIONS *************/ /******************************************************************/ @@ -73,8 +45,6 @@ int obsessive_compulsive_service_check_processor(service *svc) { char *raw_command = NULL; char *processed_command = NULL; host *temp_host = NULL; - int early_timeout = FALSE; - double exectime = 0.0; int macro_options = STRIP_ILLEGAL_MACRO_CHARS | ESCAPE_MACRO_CHARS; nagios_macros mac; @@ -84,9 +54,7 @@ int obsessive_compulsive_service_check_processor(service *svc) { return ERROR; /* bail out if we shouldn't be obsessing */ - if(obsess_over_services == FALSE) - return OK; - if(svc->obsess_over_service == FALSE) + if(obsess_over_services == FALSE || svc->obsess == FALSE) return OK; /* if there is no valid command, exit */ @@ -121,16 +89,11 @@ int obsessive_compulsive_service_check_processor(service *svc) { log_debug_info(DEBUGL_CHECKS, 2, "Processed obsessive compulsive service processor command line: %s\n", processed_command); - /* run the command */ - my_system_r(&mac, processed_command, ocsp_timeout, &early_timeout, &exectime, NULL, 0); - - clear_volatile_macros_r(&mac); - - /* check to see if the command timed out */ - if(early_timeout == TRUE) - logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: OCSP command '%s' for service '%s' on host '%s' timed out after %d seconds\n", processed_command, svc->description, svc->host_name, ocsp_timeout); + /* run the command through a worker */ + wproc_run_service_job(WPJOB_OCSP, ocsp_timeout, svc, processed_command, &mac); /* free memory */ + clear_volatile_macros_r(&mac); my_free(processed_command); return OK; @@ -142,8 +105,6 @@ int obsessive_compulsive_service_check_processor(service *svc) { int obsessive_compulsive_host_check_processor(host *hst) { char *raw_command = NULL; char *processed_command = NULL; - int early_timeout = FALSE; - double exectime = 0.0; int macro_options = STRIP_ILLEGAL_MACRO_CHARS | ESCAPE_MACRO_CHARS; nagios_macros mac; @@ -153,9 +114,7 @@ int obsessive_compulsive_host_check_processor(host *hst) { return ERROR; /* bail out if we shouldn't be obsessing */ - if(obsess_over_hosts == FALSE) - return OK; - if(hst->obsess_over_host == FALSE) + if(obsess_over_hosts == FALSE || hst->obsess == FALSE) return OK; /* if there is no valid command, exit */ @@ -185,15 +144,11 @@ int obsessive_compulsive_host_check_processor(host *hst) { log_debug_info(DEBUGL_CHECKS, 2, "Processed obsessive compulsive host processor command line: %s\n", processed_command); - /* run the command */ - my_system_r(&mac, processed_command, ochp_timeout, &early_timeout, &exectime, NULL, 0); - clear_volatile_macros_r(&mac); - - /* check to see if the command timed out */ - if(early_timeout == TRUE) - logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: OCHP command '%s' for host '%s' timed out after %d seconds\n", processed_command, hst->name, ochp_timeout); + /* run the command through a worker */ + wproc_run_host_job(WPJOB_OCHP, ochp_timeout, hst, processed_command, &mac); /* free memory */ + clear_volatile_macros_r(&mac); my_free(processed_command); return OK; @@ -245,9 +200,6 @@ int handle_service_event(service *svc) { run_service_event_handler(&mac, svc); clear_volatile_macros_r(&mac); - /* check for external commands - the event handler may have given us some directives... */ - check_for_external_commands(); - return OK; } @@ -328,8 +280,9 @@ int run_global_service_event_handler(nagios_macros *mac, service *svc) { } #endif - /* run the command */ - result = my_system_r(mac, processed_command, event_handler_timeout, &early_timeout, &exectime, &command_output, 0); + /* run the command through a worker */ + /* XXX FIXME make base/workers.c handle the eventbroker stuff below */ + result = wproc_run(WPJOB_GLOBAL_SVC_EVTHANDLER, processed_command, event_handler_timeout, mac); /* check to see if the event handler timed out */ if(early_timeout == TRUE) @@ -427,8 +380,9 @@ int run_service_event_handler(nagios_macros *mac, service *svc) { } #endif - /* run the command */ - result = my_system_r(mac, processed_command, event_handler_timeout, &early_timeout, &exectime, &command_output, 0); + /* run the command through a worker */ + /* XXX FIXME make base/workers.c handle the eventbroker stuff below */ + result = wproc_run(WPJOB_SVC_EVTHANDLER, processed_command, event_handler_timeout, mac); /* check to see if the event handler timed out */ if(early_timeout == TRUE) @@ -492,9 +446,6 @@ int handle_host_event(host *hst) { if(hst->event_handler != NULL) run_host_event_handler(&mac, hst); - /* check for external commands - the event handler may have given us some directives... */ - check_for_external_commands(); - return OK; } @@ -573,8 +524,9 @@ int run_global_host_event_handler(nagios_macros *mac, host *hst) { } #endif - /* run the command */ - result = my_system_r(mac, processed_command, event_handler_timeout, &early_timeout, &exectime, &command_output, 0); + /* run the command through a worker */ + /* XXX FIXME make base/workers.c handle the eventbroker stuff below */ + wproc_run(WPJOB_GLOBAL_HOST_EVTHANDLER, processed_command, event_handler_timeout, mac); /* check for a timeout in the execution of the event handler command */ if(early_timeout == TRUE) @@ -670,8 +622,8 @@ int run_host_event_handler(nagios_macros *mac, host *hst) { } #endif - /* run the command */ - result = my_system_r(mac, processed_command, event_handler_timeout, &early_timeout, &exectime, &command_output, 0); + /* run the command through a worker */ + result = wproc_run(WPJOB_HOST_EVTHANDLER, processed_command, event_handler_timeout, mac); /* check to see if the event handler timed out */ if(early_timeout == TRUE) @@ -695,6 +647,3 @@ int run_host_event_handler(nagios_macros *mac, host *hst) { return OK; } - - - diff --git a/base/sretention.c b/base/sretention.c index b0ede5b..b8b5d3e 100644 --- a/base/sretention.c +++ b/base/sretention.c @@ -2,8 +2,6 @@ * * SRETENTION.C - State retention routines for Nagios * - * Copyright (c) 1999-2006 Ethan Galstad (egalstad@nagios.org) - * Last Modified: 10-18-2006 * * License: * @@ -31,19 +29,7 @@ #include "../include/nagios.h" #include "../include/sretention.h" #include "../include/broker.h" - -extern int retain_state_information; - - - -/**** IMPLEMENTATION SPECIFIC HEADER FILES ****/ -#ifdef USE_XRDDEFAULT #include "../xdata/xrddefault.h" /* default routines */ -#endif - - - - /******************************************************************/ @@ -52,29 +38,15 @@ extern int retain_state_information; /* initializes retention data at program start */ -int initialize_retention_data(char *config_file) { - int result = OK; - - /**** IMPLEMENTATION-SPECIFIC CALLS ****/ -#ifdef USE_XRDDEFAULT - result = xrddefault_initialize_retention_data(config_file); -#endif - - return result; +int initialize_retention_data(const char *cfgfile) { + return xrddefault_initialize_retention_data(cfgfile); } /* cleans up retention data before program termination */ -int cleanup_retention_data(char *config_file) { - int result = OK; - - /**** IMPLEMENTATION-SPECIFIC CALLS ****/ -#ifdef USE_XRDDEFAULT - result = xrddefault_cleanup_retention_data(config_file); -#endif - - return result; +int cleanup_retention_data(void) { + return xrddefault_cleanup_retention_data(); } @@ -91,10 +63,7 @@ int save_state_information(int autosave) { broker_retention_data(NEBTYPE_RETENTIONDATA_STARTSAVE, NEBFLAG_NONE, NEBATTR_NONE, NULL); #endif - /********* IMPLEMENTATION-SPECIFIC OUTPUT FUNCTION ********/ -#ifdef USE_XRDDEFAULT result = xrddefault_save_state_information(); -#endif #ifdef USE_EVENT_BROKER /* send data to event broker */ @@ -112,7 +81,6 @@ int save_state_information(int autosave) { - /* reads in initial host and state information */ int read_initial_state_information(void) { int result = OK; @@ -125,10 +93,7 @@ int read_initial_state_information(void) { broker_retention_data(NEBTYPE_RETENTIONDATA_STARTLOAD, NEBFLAG_NONE, NEBATTR_NONE, NULL); #endif - /********* IMPLEMENTATION-SPECIFIC INPUT FUNCTION ********/ -#ifdef USE_XRDDEFAULT result = xrddefault_read_state_information(); -#endif #ifdef USE_EVENT_BROKER /* send data to event broker */ @@ -140,6 +105,3 @@ int read_initial_state_information(void) { return OK; } - - - diff --git a/base/utils.c b/base/utils.c index da3de8b..d098b26 100644 --- a/base/utils.c +++ b/base/utils.c @@ -2,8 +2,6 @@ * * UTILS.C - Miscellaneous utility functions for Nagios * - * Copyright (c) 1999-2009 Ethan Galstad (egalstad@nagios.org) - * Last Modified: 06-16-2009 * * License: * @@ -33,255 +31,209 @@ #include "../include/broker.h" #include "../include/nebmods.h" #include "../include/nebmodules.h" +#include "../include/workers.h" + +/* global variables only used by the daemon */ +char *nagios_binary_path = NULL; +char *config_file = NULL; +char *command_file; +char *temp_file; +char *temp_path; +char *check_result_path; +char *lock_file; + +int num_check_workers; +char *qh_socket_path; + +char *nagios_user; +char *nagios_group; + +char *ocsp_command; +char *ochp_command; +command *ocsp_command_ptr = NULL; +command *ochp_command_ptr = NULL; +int ocsp_timeout; +int ochp_timeout; + +char *illegal_object_chars; + +int use_regexp_matches; +int use_true_regexp_matching; + +int use_syslog; +char *log_file; +char *log_archive_path; +int log_notifications; +int log_service_retries; +int log_host_retries; +int log_event_handlers; +int log_initial_states; +int log_current_states; +int log_external_commands; +int log_passive_checks; +unsigned long logging_options = 0; +unsigned long syslog_options = 0; + +int service_check_timeout; +int service_check_timeout_state; +int host_check_timeout; +int event_handler_timeout; +int notification_timeout; -#ifdef EMBEDDEDPERL -#include "../include/epn_nagios.h" -static PerlInterpreter *my_perl = NULL; -int use_embedded_perl = TRUE; -#endif +char *object_precache_file; -extern char *config_file; -extern char *log_file; -extern char *command_file; -extern char *temp_file; -extern char *temp_path; -extern char *check_result_path; -extern char *check_result_path; -extern char *lock_file; -extern char *log_archive_path; -extern char *auth_file; -extern char *p1_file; +char *global_host_event_handler; +char *global_service_event_handler; +command *global_host_event_handler_ptr = NULL; +command *global_service_event_handler_ptr = NULL; -extern char *xodtemplate_cache_file; -extern char *xodtemplate_precache_file; -extern char *xsddefault_status_log; -extern char *xrddefault_retention_file; -extern char *xpddefault_host_perfdata_file; -extern char *xpddefault_service_perfdata_file; +int service_inter_check_delay_method; +int host_inter_check_delay_method; +int service_interleave_factor_method; +int max_host_check_spread; +int max_service_check_spread; -extern char *nagios_user; -extern char *nagios_group; +int check_reaper_interval; +int max_check_reaper_time; +int service_freshness_check_interval; +int host_freshness_check_interval; +int auto_rescheduling_interval; -extern char *macro_x_names[MACRO_X_COUNT]; -extern char *macro_user[MAX_USER_MACROS]; -extern customvariablesmember *macro_custom_host_vars; -extern customvariablesmember *macro_custom_service_vars; -extern customvariablesmember *macro_custom_contact_vars; +struct load_control loadctl; -extern host *macro_host_ptr; -extern hostgroup *macro_hostgroup_ptr; -extern service *macro_service_ptr; -extern servicegroup *macro_servicegroup_ptr; -extern contact *macro_contact_ptr; -extern contactgroup *macro_contactgroup_ptr; +int check_orphaned_services; +int check_orphaned_hosts; +int check_service_freshness; +int check_host_freshness; +int auto_reschedule_checks; +int auto_rescheduling_window; -extern char *global_host_event_handler; -extern char *global_service_event_handler; -extern command *global_host_event_handler_ptr; -extern command *global_service_event_handler_ptr; +int additional_freshness_latency; -extern char *ocsp_command; -extern char *ochp_command; -extern command *ocsp_command_ptr; -extern command *ochp_command_ptr; +int check_for_updates; +int bare_update_check; +time_t last_update_check = 0L; +unsigned long update_uid = 0L; +int update_available = FALSE; +char *last_program_version = NULL; +char *new_program_version = NULL; -extern char *illegal_object_chars; -extern char *illegal_output_chars; +time_t last_program_stop = 0L; -extern int use_regexp_matches; -extern int use_true_regexp_matching; +int use_aggressive_host_checking; +time_t cached_host_check_horizon; +time_t cached_service_check_horizon; +int enable_predictive_host_dependency_checks; +int enable_predictive_service_dependency_checks; -extern int sigshutdown; -extern int sigrestart; -extern char *sigs[35]; -extern int caught_signal; -extern int sig_id; +int soft_state_dependencies; -extern int daemon_mode; -extern int daemon_dumps_core; +int retain_state_information; +int retention_update_interval; +int use_retained_program_state; +int use_retained_scheduling_info; +int retention_scheduling_horizon; +char *retention_file; -extern int nagios_pid; +unsigned long modified_process_attributes = MODATTR_NONE; +unsigned long modified_host_process_attributes = MODATTR_NONE; +unsigned long modified_service_process_attributes = MODATTR_NONE; +unsigned long retained_host_attribute_mask; +unsigned long retained_service_attribute_mask; +unsigned long retained_contact_host_attribute_mask; +unsigned long retained_contact_service_attribute_mask; +unsigned long retained_process_host_attribute_mask; +unsigned long retained_process_service_attribute_mask; -extern int use_syslog; -extern int log_notifications; -extern int log_service_retries; -extern int log_host_retries; -extern int log_event_handlers; -extern int log_external_commands; -extern int log_passive_checks; +unsigned long next_event_id = 0L; +unsigned long next_problem_id = 1L; +unsigned long next_comment_id = 0L; +unsigned long next_notification_id = 0L; -extern unsigned long logging_options; -extern unsigned long syslog_options; +int verify_config = FALSE; +int test_scheduling = FALSE; +int precache_objects = FALSE; +int use_precached_objects = FALSE; -extern int service_check_timeout; -extern int service_check_timeout_state; -extern int host_check_timeout; -extern int event_handler_timeout; -extern int notification_timeout; -extern int ocsp_timeout; -extern int ochp_timeout; +int sigshutdown = FALSE; +int sigrestart = FALSE; +int caught_signal = FALSE; +int sig_id = 0; -extern int log_initial_states; +int daemon_dumps_core; -extern double sleep_time; -extern int interval_length; -extern int service_inter_check_delay_method; -extern int host_inter_check_delay_method; -extern int service_interleave_factor_method; -extern int max_host_check_spread; -extern int max_service_check_spread; +int max_parallel_service_checks; +int currently_running_service_checks = 0; +int currently_running_host_checks = 0; -extern int command_check_interval; -extern int check_reaper_interval; -extern int max_check_reaper_time; -extern int service_freshness_check_interval; -extern int host_freshness_check_interval; -extern int auto_rescheduling_interval; -extern int auto_rescheduling_window; +time_t event_start = 0L; -extern int check_external_commands; -extern int check_orphaned_services; -extern int check_orphaned_hosts; -extern int check_service_freshness; -extern int check_host_freshness; -extern int auto_reschedule_checks; +int translate_passive_host_checks; +int passive_host_checks_are_soft; -extern int additional_freshness_latency; +int status_update_interval; -extern int check_for_updates; -extern int bare_update_check; -extern time_t last_update_check; -extern unsigned long update_uid; -extern char *last_program_version; -extern int update_available; -extern char *last_program_version; -extern char *new_program_version; +int time_change_threshold; -extern int use_aggressive_host_checking; -extern unsigned long cached_host_check_horizon; -extern unsigned long cached_service_check_horizon; -extern int enable_predictive_host_dependency_checks; -extern int enable_predictive_service_dependency_checks; +unsigned long event_broker_options; -extern int soft_state_dependencies; +double low_service_flap_threshold; +double high_service_flap_threshold; +double low_host_flap_threshold; +double high_host_flap_threshold; -extern int retain_state_information; -extern int retention_update_interval; -extern int use_retained_program_state; -extern int use_retained_scheduling_info; -extern int retention_scheduling_horizon; -extern unsigned long modified_host_process_attributes; -extern unsigned long modified_service_process_attributes; -extern unsigned long retained_host_attribute_mask; -extern unsigned long retained_service_attribute_mask; -extern unsigned long retained_contact_host_attribute_mask; -extern unsigned long retained_contact_service_attribute_mask; -extern unsigned long retained_process_host_attribute_mask; -extern unsigned long retained_process_service_attribute_mask; +int use_large_installation_tweaks; +int enable_environment_macros; +int free_child_process_memory; +int child_processes_fork_twice; -extern unsigned long next_comment_id; -extern unsigned long next_downtime_id; -extern unsigned long next_event_id; -extern unsigned long next_notification_id; +char *use_timezone; -extern int log_rotation_method; +int allow_empty_hostgroup_assignment; -extern time_t program_start; +int host_down_disable_service_checks; -extern time_t last_command_check; -extern time_t last_command_status_update; -extern time_t last_log_rotation; +/*** perfdata variables ***/ +int perfdata_timeout; +char *host_perfdata_command; +char *service_perfdata_command; +char *host_perfdata_file_template; +char *service_perfdata_file_template; +char *host_perfdata_file; +char *service_perfdata_file; +int host_perfdata_file_append; +int service_perfdata_file_append; +int host_perfdata_file_pipe; +int service_perfdata_file_pipe; +unsigned long host_perfdata_file_processing_interval; +unsigned long service_perfdata_file_processing_interval; +char *host_perfdata_file_processing_command; +char *service_perfdata_file_processing_command; +int host_perfdata_process_empty_results; +int service_perfdata_process_empty_results; +/*** end perfdata variables */ -extern int verify_config; -extern int test_scheduling; +/* Filename variables used by handle_sigxfsz */ +extern char *status_file; -extern check_result check_result_info; +static long long check_file_size(char *, unsigned long, struct rlimit); -extern int max_parallel_service_checks; -extern int currently_running_service_checks; +notification *notification_list; -extern int enable_notifications; -extern int execute_service_checks; -extern int accept_passive_service_checks; -extern int execute_host_checks; -extern int accept_passive_host_checks; -extern int enable_event_handlers; -extern int obsess_over_services; -extern int obsess_over_hosts; -extern int enable_failure_prediction; -extern int process_performance_data; +time_t max_check_result_file_age; -extern int translate_passive_host_checks; -extern int passive_host_checks_are_soft; +check_stats check_statistics[MAX_CHECK_STATS_TYPES]; -extern int aggregate_status_updates; -extern int status_update_interval; +char *debug_file; +int debug_level; +int debug_verbosity; +unsigned long max_debug_file_size; -extern int time_change_threshold; +iobroker_set *nagios_iobs = NULL; +squeue_t *nagios_squeue = NULL; /* our scheduling queue */ -extern unsigned long event_broker_options; - -extern int process_performance_data; - -extern int enable_flap_detection; - -extern double low_service_flap_threshold; -extern double high_service_flap_threshold; -extern double low_host_flap_threshold; -extern double high_host_flap_threshold; - -extern int use_large_installation_tweaks; -extern int enable_environment_macros; -extern int free_child_process_memory; -extern int child_processes_fork_twice; - -extern int enable_embedded_perl; -extern int use_embedded_perl_implicitly; - -extern int date_format; - -extern contact *contact_list; -extern contactgroup *contactgroup_list; -extern host *host_list; -extern hostgroup *hostgroup_list; -extern service *service_list; -extern servicegroup *servicegroup_list; -extern timed_event *event_list_high; -extern timed_event *event_list_low; -extern notification *notification_list; -extern command *command_list; -extern timeperiod *timeperiod_list; - -extern int command_file_fd; -extern FILE *command_file_fp; -extern int command_file_created; - -#ifdef HAVE_TZNAME -#ifdef CYGWIN -extern char *_tzname[2] __declspec(dllimport); -#else -extern char *tzname[2]; -#endif -#endif - -extern check_result *check_result_list; -extern unsigned long max_check_result_file_age; - -extern dbuf check_result_dbuf; - -extern pthread_t worker_threads[TOTAL_WORKER_THREADS]; -extern circular_buffer external_command_buffer; -extern circular_buffer check_result_buffer; -extern circular_buffer event_broker_buffer; -extern int external_command_buffer_slots; - -extern check_stats check_statistics[MAX_CHECK_STATS_TYPES]; - -extern char *debug_file; -extern int debug_level; -extern int debug_verbosity; -extern unsigned long max_debug_file_size; +sched_info scheduling_info; /* from GNU defines errno as a macro, since it's a per-thread variable */ #ifndef errno @@ -289,7 +241,260 @@ extern int errno; #endif -static long long check_file_size(char *, unsigned long, struct rlimit); +/* Initialize the non-shared main configuration variables */ +void init_main_cfg_vars(int first_time) { + + /* Initialize only the first time */ + if(first_time) { + num_check_workers = 0; /* auto-decide */ + qh_socket_path = NULL; /* disabled */ + } + + log_file = NULL; + temp_file = NULL; + temp_path = NULL; + check_result_path = NULL; + command_file = NULL; + lock_file = NULL; + log_archive_path = NULL; + debug_file = NULL; + + object_precache_file = (char *)strdup(DEFAULT_PRECACHED_OBJECT_FILE); + + nagios_user = NULL; + nagios_group = NULL; + + use_regexp_matches = FALSE; + use_true_regexp_matching = FALSE; + + use_syslog = DEFAULT_USE_SYSLOG; + log_service_retries = DEFAULT_LOG_SERVICE_RETRIES; + log_host_retries = DEFAULT_LOG_HOST_RETRIES; + log_initial_states = DEFAULT_LOG_INITIAL_STATES; + if(first_time) { + /* Not sure why this is not reset in reset_variables() */ + log_current_states = DEFAULT_LOG_CURRENT_STATES; + } + + log_notifications = DEFAULT_NOTIFICATION_LOGGING; + log_event_handlers = DEFAULT_LOG_EVENT_HANDLERS; + log_external_commands = DEFAULT_LOG_EXTERNAL_COMMANDS; + log_passive_checks = DEFAULT_LOG_PASSIVE_CHECKS; + + service_check_timeout = DEFAULT_SERVICE_CHECK_TIMEOUT; + if(first_time) { + /* Not sure why this is not reset in reset_variables() */ + service_check_timeout_state = STATE_CRITICAL; + } + host_check_timeout = DEFAULT_HOST_CHECK_TIMEOUT; + event_handler_timeout = DEFAULT_EVENT_HANDLER_TIMEOUT; + notification_timeout = DEFAULT_NOTIFICATION_TIMEOUT; + ocsp_timeout = DEFAULT_OCSP_TIMEOUT; + ochp_timeout = DEFAULT_OCHP_TIMEOUT; + + if(first_time) { + /* Not sure why this is not reset in reset_variables() */ + illegal_object_chars = NULL; + } + service_inter_check_delay_method = ICD_SMART; + host_inter_check_delay_method = ICD_SMART; + service_interleave_factor_method = ILF_SMART; + max_service_check_spread = DEFAULT_SERVICE_CHECK_SPREAD; + max_host_check_spread = DEFAULT_HOST_CHECK_SPREAD; + + use_aggressive_host_checking = DEFAULT_AGGRESSIVE_HOST_CHECKING; + cached_host_check_horizon = DEFAULT_CACHED_HOST_CHECK_HORIZON; + cached_service_check_horizon = DEFAULT_CACHED_SERVICE_CHECK_HORIZON; + enable_predictive_host_dependency_checks = + DEFAULT_ENABLE_PREDICTIVE_HOST_DEPENDENCY_CHECKS; + enable_predictive_service_dependency_checks = + DEFAULT_ENABLE_PREDICTIVE_SERVICE_DEPENDENCY_CHECKS; + + soft_state_dependencies = FALSE; + + retain_state_information = FALSE; + retention_update_interval = DEFAULT_RETENTION_UPDATE_INTERVAL; + use_retained_program_state = TRUE; + use_retained_scheduling_info = FALSE; + retention_scheduling_horizon = DEFAULT_RETENTION_SCHEDULING_HORIZON; + if(first_time) { + /* Not sure why this is not reset in reset_variables() */ + retention_file = NULL; + } + retained_host_attribute_mask = 0L; + retained_service_attribute_mask = 0L; + retained_process_host_attribute_mask = 0L; + retained_process_service_attribute_mask = 0L; + retained_contact_host_attribute_mask = 0L; + retained_contact_service_attribute_mask = 0L; + + check_reaper_interval = DEFAULT_CHECK_REAPER_INTERVAL; + max_check_reaper_time = DEFAULT_MAX_REAPER_TIME; + max_check_result_file_age = DEFAULT_MAX_CHECK_RESULT_AGE; + service_freshness_check_interval = DEFAULT_FRESHNESS_CHECK_INTERVAL; + host_freshness_check_interval = DEFAULT_FRESHNESS_CHECK_INTERVAL; + auto_rescheduling_interval = DEFAULT_AUTO_RESCHEDULING_INTERVAL; + auto_rescheduling_window = DEFAULT_AUTO_RESCHEDULING_WINDOW; + + check_orphaned_services = DEFAULT_CHECK_ORPHANED_SERVICES; + check_orphaned_hosts = DEFAULT_CHECK_ORPHANED_HOSTS; + check_service_freshness = DEFAULT_CHECK_SERVICE_FRESHNESS; + check_host_freshness = DEFAULT_CHECK_HOST_FRESHNESS; + auto_reschedule_checks = DEFAULT_AUTO_RESCHEDULE_CHECKS; + + if(first_time) { + /* Not sure why this is not reset in reset_variables() */ + daemon_dumps_core = TRUE; + } + + max_parallel_service_checks = DEFAULT_MAX_PARALLEL_SERVICE_CHECKS; + + status_update_interval = DEFAULT_STATUS_UPDATE_INTERVAL; + + event_broker_options = BROKER_NOTHING; + + time_change_threshold = DEFAULT_TIME_CHANGE_THRESHOLD; + + low_service_flap_threshold = DEFAULT_LOW_SERVICE_FLAP_THRESHOLD; + high_service_flap_threshold = DEFAULT_HIGH_SERVICE_FLAP_THRESHOLD; + low_host_flap_threshold = DEFAULT_LOW_HOST_FLAP_THRESHOLD; + high_host_flap_threshold = DEFAULT_HIGH_HOST_FLAP_THRESHOLD; + + translate_passive_host_checks = DEFAULT_TRANSLATE_PASSIVE_HOST_CHECKS; + passive_host_checks_are_soft = DEFAULT_PASSIVE_HOST_CHECKS_SOFT; + + use_large_installation_tweaks = DEFAULT_USE_LARGE_INSTALLATION_TWEAKS; + enable_environment_macros = FALSE; + free_child_process_memory = -1; + child_processes_fork_twice = -1; + + if(first_time) { + /* Not sure why these are not reset in reset_variables() */ + use_timezone = NULL; + allow_empty_hostgroup_assignment = + DEFAULT_ALLOW_EMPTY_HOSTGROUP_ASSIGNMENT; + host_down_disable_service_checks = FALSE; + perfdata_timeout = 0; + host_perfdata_command = NULL; + service_perfdata_command = NULL; + host_perfdata_file_template = NULL; + service_perfdata_file_template = NULL; + host_perfdata_file = NULL; + service_perfdata_file = NULL; + host_perfdata_file_pipe = FALSE; + host_perfdata_file_append = TRUE; + service_perfdata_file_pipe = FALSE; + service_perfdata_file_append = TRUE; + host_perfdata_file_processing_interval = 0L; + service_perfdata_file_processing_interval = 0L; + host_perfdata_file_processing_command = NULL; + service_perfdata_file_processing_command = NULL; + host_perfdata_process_empty_results = + DEFAULT_HOST_PERFDATA_PROCESS_EMPTY_RESULTS; + service_perfdata_process_empty_results = + DEFAULT_SERVICE_PERFDATA_PROCESS_EMPTY_RESULTS; + } + + additional_freshness_latency = DEFAULT_ADDITIONAL_FRESHNESS_LATENCY; + + if(first_time) { + /* Not sure why these are not reset in reset_variables() */ + check_for_updates = DEFAULT_CHECK_FOR_UPDATES; + bare_update_check = DEFAULT_BARE_UPDATE_CHECK; + debug_level = DEFAULT_DEBUG_LEVEL; + debug_verbosity = DEFAULT_DEBUG_VERBOSITY; + max_debug_file_size = DEFAULT_MAX_DEBUG_FILE_SIZE; + } + + global_host_event_handler = NULL; + global_service_event_handler = NULL; + + ocsp_command = NULL; + ochp_command = NULL; + + return; + } + + +static const char *worker_source_name(const void *source) { + return source ? (const char *)source : "unknown internal source (voodoo, perhaps?)"; + } + +static const char *spool_file_source_name(const void *source) { + return "check result spool dir"; + } + +struct check_engine nagios_check_engine = { + "Nagios Core", + worker_source_name, + NULL, +}; + +static struct check_engine nagios_spool_check_engine = { + "Spooled checkresult file", + spool_file_source_name, + NULL, +}; + +const char *check_result_source(check_result *cr) { + if(cr->engine) + return cr->engine->source_name(cr->source); + return cr->source ? (const char *)cr->source : "(unknown engine)"; + } + + +int set_loadctl_options(char *opts, unsigned int len) +{ + struct kvvec *kvv; + int i; + + kvv = buf2kvvec(opts, len, '=', ';', 0); + for (i = 0; i < kvv->kv_pairs; i++) { + struct key_value *kv = &kvv->kv[i]; + + if (!strcmp(kv->key, "enabled")) { + if (*kv->value == '1') { + if (!(loadctl.options & LOADCTL_ENABLED)) + logit(0, 0, "Warning: Enabling experimental load control\n"); + loadctl.options |= LOADCTL_ENABLED; + } + else { + if (loadctl.options & LOADCTL_ENABLED) + logit(0, 0, "Warning: Disabling experimental load control\n"); + loadctl.options &= (~LOADCTL_ENABLED); + } + } else if (!strcmp(kv->key, "jobs_max")) { + loadctl.jobs_max = atoi(kv->value); + } else if (!strcmp(kv->key, "jobs_min")) { + loadctl.jobs_min = atoi(kv->value); + } else if (!strcmp(kv->key, "jobs_limit")) { + loadctl.jobs_limit = atoi(kv->value); + } else if (!strcmp(kv->key, "check_interval")) { + loadctl.check_interval = strtoul(kv->value, NULL, 10); + } else if (!strcmp(kv->key, "backoff_limit")) { + loadctl.backoff_limit = strtod(kv->value, NULL); + } else if (!strcmp(kv->key, "rampup_limit")) { + loadctl.rampup_limit = strtod(kv->value, NULL); + } else if (!strcmp(kv->key, "backoff_change")) { + loadctl.backoff_change = atoi(kv->value); + } else if (!strcmp(kv->key, "rampup_change")) { + loadctl.rampup_change = atoi(kv->value); + } else { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Bad loadctl option; %s = %s\n", kv->key, kv->value); + return 400; + } + } + + /* precedence order is "jobs_min -> jobs_max -> jobs_limit" */ + if (loadctl.jobs_max < loadctl.jobs_min) + loadctl.jobs_max = loadctl.jobs_min; + if (loadctl.jobs_limit > loadctl.jobs_max) + loadctl.jobs_limit = loadctl.jobs_max; + if (loadctl.jobs_limit < loadctl.jobs_min) + loadctl.jobs_limit = loadctl.jobs_min; + kvvec_destroy(kvv, 0); + return 0; +} /******************************************************************/ /******************** SYSTEM COMMAND FUNCTIONS ********************/ @@ -302,7 +507,6 @@ int my_system_r(nagios_macros *mac, char *cmd, int timeout, int *early_timeout, int status = 0; int result = 0; char buffer[MAX_INPUT_BUFFER] = ""; - char *temp_buffer = NULL; int fd[2]; FILE *fp = NULL; int bytes_read = 0; @@ -310,19 +514,9 @@ int my_system_r(nagios_macros *mac, char *cmd, int timeout, int *early_timeout, dbuf output_dbuf; int dbuf_chunk = 1024; int flags; -#ifdef EMBEDDEDPERL - char fname[512] = ""; - char *args[5] = {"", DO_CLEAN, "", "", NULL }; - SV *plugin_hndlr_cr = NULL; - char *perl_output = NULL; - int count; - int use_epn = FALSE; -#ifdef aTHX - dTHX; +#ifdef HAVE_SIGACTION + struct sigaction sig_action; #endif - dSP; -#endif - log_debug_info(DEBUGL_FUNCTIONS, 0, "my_system_r()\n"); @@ -338,71 +532,6 @@ int my_system_r(nagios_macros *mac, char *cmd, int timeout, int *early_timeout, log_debug_info(DEBUGL_COMMANDS, 1, "Running command '%s'...\n", cmd); -#ifdef EMBEDDEDPERL - - /* get"filename" component of command */ - strncpy(fname, cmd, strcspn(cmd, " ")); - fname[strcspn(cmd, " ")] = '\x0'; - - /* should we use the embedded Perl interpreter to run this script? */ - use_epn = file_uses_embedded_perl(fname); - - /* if yes, do some initialization */ - if(use_epn == TRUE) { - - args[0] = fname; - args[2] = ""; - - if(strchr(cmd, ' ') == NULL) - args[3] = ""; - else - args[3] = cmd + strlen(fname) + 1; - - /* call our perl interpreter to compile and optionally cache the compiled script. */ - - ENTER; - SAVETMPS; - PUSHMARK(SP); - - XPUSHs(sv_2mortal(newSVpv(args[0], 0))); - XPUSHs(sv_2mortal(newSVpv(args[1], 0))); - XPUSHs(sv_2mortal(newSVpv(args[2], 0))); - XPUSHs(sv_2mortal(newSVpv(args[3], 0))); - - PUTBACK; - - call_pv("Embed::Persistent::eval_file", G_EVAL); - - SPAGAIN; - - if(SvTRUE(ERRSV)) { - /* - * XXXX need pipe open to send the compilation failure message back to Nagios ? - */ - (void) POPs ; - - asprintf(&temp_buffer, "%s", SvPVX(ERRSV)); - - log_debug_info(DEBUGL_COMMANDS, 0, "Embedded perl failed to compile %s, compile error %s\n", fname, temp_buffer); - - logit(NSLOG_RUNTIME_WARNING, TRUE, "%s\n", temp_buffer); - - my_free(temp_buffer); - - return STATE_UNKNOWN; - } - else { - plugin_hndlr_cr = newSVsv(POPs); - - log_debug_info(DEBUGL_COMMANDS, 0, "Embedded perl successfully compiled %s and returned plugin handler (Perl subroutine code ref)\n", fname); - - PUTBACK ; - FREETMPS ; - LEAVE ; - } - } -#endif - /* create a pipe */ pipe(fd); @@ -425,7 +554,7 @@ int my_system_r(nagios_macros *mac, char *cmd, int timeout, int *early_timeout, /* return an error if we couldn't fork */ if(pid == -1) { - logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: fork() in my_system_r() failed for command \"%s\"\n", cmd); + logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: fork() in my_system_r() failed for command \"%s\" - errno: %s\n", cmd, strerror(errno)); /* close both ends of the pipe */ close(fd[0]); @@ -459,59 +588,17 @@ int my_system_r(nagios_macros *mac, char *cmd, int timeout, int *early_timeout, fcntl(fd[1], F_SETFD, flags); /* trap commands that timeout */ +#ifdef HAVE_SIGACTION + sig_action.sa_sigaction = NULL; + sig_action.sa_handler = my_system_sighandler; + sigfillset(&sig_action.sa_mask); + sig_action.sa_flags = SA_NODEFER|SA_RESTART; + sigaction(SIGALRM, &sig_action, NULL); +#else signal(SIGALRM, my_system_sighandler); +#endif /* HAVE_SIGACTION */ alarm(timeout); - - /******** BEGIN EMBEDDED PERL CODE EXECUTION ********/ - -#ifdef EMBEDDEDPERL - if(use_epn == TRUE) { - - /* execute our previously compiled script - by call_pv("Embed::Persistent::eval_file",..) */ - ENTER; - SAVETMPS; - PUSHMARK(SP); - - XPUSHs(sv_2mortal(newSVpv(args[0], 0))); - XPUSHs(sv_2mortal(newSVpv(args[1], 0))); - XPUSHs(plugin_hndlr_cr); - XPUSHs(sv_2mortal(newSVpv(args[3], 0))); - - PUTBACK; - - count = call_pv("Embed::Persistent::run_package", G_ARRAY); - /* count is a debug hook. It should always be two (2), because the persistence framework tries to return two (2) args */ - - SPAGAIN; - - perl_output = POPpx ; - strip(perl_output); - strncpy(buffer, (perl_output == NULL) ? "" : perl_output, sizeof(buffer)); - buffer[sizeof(buffer) - 1] = '\x0'; - status = POPi ; - - PUTBACK; - FREETMPS; - LEAVE; - - log_debug_info(DEBUGL_COMMANDS, 0, "Embedded perl ran command %s with output %d, %s\n", fname, status, buffer); - - /* write the output back to the parent process */ - write(fd[1], buffer, strlen(buffer) + 1); - - /* close pipe for writing */ - close(fd[1]); - - /* reset the alarm */ - alarm(0); - - _exit(status); - } -#endif - /******** END EMBEDDED PERL CODE EXECUTION ********/ - - /* run the command */ fp = (FILE *)popen(cmd, "r"); @@ -586,7 +673,6 @@ int my_system_r(nagios_macros *mac, char *cmd, int timeout, int *early_timeout, /* check for possibly missing scripts/binaries/etc */ if(result == 126 || result == 127) { - temp_buffer = "\163\157\151\147\141\156\040\145\144\151\163\156\151"; logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Attempting to execute the command \"%s\" resulted in a return code of %d. Make sure the script or binary you are trying to execute actually exists...\n", cmd, result); } @@ -652,7 +738,7 @@ int my_system_r(nagios_macros *mac, char *cmd, int timeout, int *early_timeout, while(1); /* cap output length - this isn't necessary, but it keeps runaway plugin output from causing problems */ - if(max_output_length > 0 && output_dbuf.used_size > max_output_length) + if(max_output_length > 0 && (int)output_dbuf.used_size > max_output_length) output_dbuf.buf[max_output_length] = '\x0'; if(output != NULL && output_dbuf.buf) @@ -694,7 +780,6 @@ int get_raw_command_line_r(nagios_macros *mac, command *cmd_ptr, char *cmd, char register int x = 0; register int y = 0; register int arg_index = 0; - register int escaped = FALSE; log_debug_info(DEBUGL_FUNCTIONS, 0, "get_raw_command_line_r()\n"); @@ -729,24 +814,19 @@ int get_raw_command_line_r(nagios_macros *mac, command *cmd_ptr, char *cmd, char /* get the next argument */ /* can't use strtok(), as that's used in process_macros... */ - for(arg_index++, y = 0; y < sizeof(temp_arg) - 1; arg_index++) { + for(arg_index++, y = 0; y < (int)sizeof(temp_arg) - 1; arg_index++) { - /* backslashes escape */ - if(cmd[arg_index] == '\\' && escaped == FALSE) { - escaped = TRUE; - continue; - } - - /* end of argument */ - if((cmd[arg_index] == '!' && escaped == FALSE) || cmd[arg_index] == '\x0') + /* handle escaped argument delimiters */ + if(cmd[arg_index] == '\\' && cmd[arg_index+1] == '!') { + arg_index++; + } else if(cmd[arg_index] == '!' || cmd[arg_index] == '\x0') { + /* end of argument */ break; + } - /* normal of escaped char */ + /* copy the character */ temp_arg[y] = cmd[arg_index]; y++; - - /* clear escaped flag */ - escaped = FALSE; } temp_arg[y] = '\x0'; @@ -792,7 +872,6 @@ int set_environment_var(char *name, char *value, int set) { /* set the environment variable */ if(set == TRUE) { - #ifdef HAVE_SETENV setenv(name, (value == NULL) ? "" : value, 1); #else @@ -822,13 +901,13 @@ int set_environment_var(char *name, char *value, int set) { /* Checks if the given time is in daylight time saving period */ -int is_dst_time(time_t *time) { +static int is_dst_time(time_t *time) { struct tm *bt = localtime(time); return bt->tm_isdst; } /* Returns the shift in seconds if the given times are across the daylight time saving period change */ -int get_dst_shift(time_t *start, time_t *end) { +static int get_dst_shift(time_t *start, time_t *end) { int shift = 0, dst_end, dst_start; dst_start = is_dst_time(start); dst_end = is_dst_time(end); @@ -843,51 +922,28 @@ int get_dst_shift(time_t *start, time_t *end) { /*#define TEST_TIMEPERIODS_A 1*/ -/* see if the specified time falls into a valid time range in the given time period */ -int check_time_against_period(time_t test_time, timeperiod *tperiod) { - timeperiodexclusion *temp_timeperiodexclusion = NULL; - timeperiodexclusion *first_timeperiodexclusion = NULL; +static timerange* _get_matching_timerange(time_t test_time, timeperiod *tperiod) { daterange *temp_daterange = NULL; - timerange *temp_timerange = NULL; - time_t midnight = (time_t)0L; time_t start_time = (time_t)0L; time_t end_time = (time_t)0L; - int found_match = FALSE; + unsigned long days = 0L; + int year = 0; + int shift = 0; + time_t midnight = (time_t)0L; struct tm *t, tm_s; int daterange_type = 0; - unsigned long days = 0L; - time_t day_range_start = (time_t)0L; - time_t day_range_end = (time_t)0L; int test_time_year = 0; int test_time_mon = 0; - int test_time_mday = 0; int test_time_wday = 0; - int year = 0; - int shift; - log_debug_info(DEBUGL_FUNCTIONS, 0, "check_time_against_period()\n"); + log_debug_info(DEBUGL_FUNCTIONS, 0, "_get_matching_timerange()\n"); - /* if no period was specified, assume the time is good */ if(tperiod == NULL) - return OK; + return NULL; - /* test exclusions first - if exclusions match current time, bail out with an error */ - /* clear exclusions list before recursing (and restore afterwards) to prevent endless loops... */ - first_timeperiodexclusion = tperiod->exclusions; - tperiod->exclusions = NULL; - for(temp_timeperiodexclusion = first_timeperiodexclusion; temp_timeperiodexclusion != NULL; temp_timeperiodexclusion = temp_timeperiodexclusion->next) { - if(check_time_against_period(test_time, temp_timeperiodexclusion->timeperiod_ptr) == OK) { - tperiod->exclusions = first_timeperiodexclusion; - return ERROR; - } - } - tperiod->exclusions = first_timeperiodexclusion; - - /* save values for later */ t = localtime_r((time_t *)&test_time, &tm_s); test_time_year = t->tm_year; test_time_mon = t->tm_mon; - test_time_mday = t->tm_mday; test_time_wday = t->tm_wday; /* calculate the start of the day (midnight, 00:00 hours) when the specified test time occurs */ @@ -903,8 +959,8 @@ int check_time_against_period(time_t test_time, timeperiod *tperiod) { #ifdef TEST_TIMEPERIODS_A printf("TYPE: %d\n", daterange_type); - printf("TEST: %lu = %s", (unsigned long)test_time, ctime(&test_time)); - printf("MIDNIGHT: %lu = %s", (unsigned long)midnight, ctime(&midnight)); + printf("TEST: %llu = %s", (unsigned long long)test_time, ctime(&test_time)); + printf("MIDNIGHT: %llu = %s", (unsigned long long)midnight, ctime(&midnight)); #endif /* get the start time */ @@ -980,8 +1036,8 @@ int check_time_against_period(time_t test_time, timeperiod *tperiod) { } #ifdef TEST_TIMEPERIODS_A - printf("START: %lu = %s", (unsigned long)start_time, ctime(&start_time)); - printf("END: %lu = %s", (unsigned long)end_time, ctime(&end_time)); + printf("START: %llu = %s", (unsigned long long)start_time, ctime(&start_time)); + printf("END: %llu = %s", (unsigned long long)end_time, ctime(&end_time)); #endif /* start date was bad, so skip this date range */ @@ -1061,62 +1117,63 @@ int check_time_against_period(time_t test_time, timeperiod *tperiod) { } #ifdef TEST_TIMEPERIODS_A - printf("NEW START: %lu = %s", (unsigned long)start_time, ctime(&start_time)); - printf("NEW END: %lu = %s", (unsigned long)end_time, ctime(&end_time)); + printf("NEW START: %llu = %s", (unsigned long long)start_time, ctime(&start_time)); + printf("NEW END: %llu = %s", (unsigned long long)end_time, ctime(&end_time)); printf("%d DAYS PASSED\n", days); - printf("DLST SHIFT: %d", shift); + printf("DLST SHIFT: %i\n", shift); #endif - /* time falls into the range of days */ - if(midnight >= start_time && midnight <= end_time) - found_match = TRUE; - - /* found a day match, so see if time ranges are good */ - if(found_match == TRUE) { - - for(temp_timerange = temp_daterange->times; temp_timerange != NULL; temp_timerange = temp_timerange->next) { - - /* ranges with start/end of zero mean exlude this day */ - if(temp_timerange->range_start == 0 && temp_timerange->range_end == 0) { + /* time falls inside the range of days + * end time < start_time when range covers end-of-$unit + * (fe. end-of-month) */ + if((midnight + 84800UL >= start_time && (midnight <= end_time || start_time > end_time)) || (midnight <= end_time && start_time > end_time)) { #ifdef TEST_TIMEPERIODS_A - printf("0 MINUTE RANGE EXCLUSION\n"); + printf("(MATCH)\n"); #endif - continue; - } - - day_range_start = (time_t)(midnight + temp_timerange->range_start); - day_range_end = (time_t)(midnight + temp_timerange->range_end); - -#ifdef TEST_TIMEPERIODS_A - printf(" RANGE START: %lu (%lu) = %s", temp_timerange->range_start, (unsigned long)day_range_start, ctime(&day_range_start)); - printf(" RANGE END: %lu (%lu) = %s", temp_timerange->range_end, (unsigned long)day_range_end, ctime(&day_range_end)); -#endif - - /* if the user-specified time falls in this range, return with a positive result */ - if(test_time >= day_range_start && test_time <= day_range_end) - return OK; - } - - /* no match, so bail with error */ - return ERROR; + return temp_daterange->times; } } } + return tperiod->days[test_time_wday]; +} - /**** check normal, weekly rotating schedule last ****/ +/* see if the specified time falls into a valid time range in the given time period */ +int check_time_against_period(time_t test_time, timeperiod *tperiod) { + timerange *temp_timerange = NULL; + timeperiodexclusion *temp_timeperiodexclusion = NULL; + struct tm *t, tm_s; + time_t midnight = (time_t)0L; + time_t day_range_start = (time_t)0L; + time_t day_range_end = (time_t)0L; - /* check weekday time ranges */ - for(temp_timerange = tperiod->days[test_time_wday]; temp_timerange != NULL; temp_timerange = temp_timerange->next) { + log_debug_info(DEBUGL_FUNCTIONS, 0, "check_time_against_period()\n"); + + t = localtime_r((time_t *)&test_time, &tm_s); + + t->tm_sec = 0; + t->tm_min = 0; + t->tm_hour = 0; + midnight = mktime(t); + + /* if no period was specified, assume the time is good */ + if(tperiod == NULL) + return OK; + + for(temp_timeperiodexclusion = tperiod->exclusions; temp_timeperiodexclusion != NULL; temp_timeperiodexclusion = temp_timeperiodexclusion->next) { + if(check_time_against_period(test_time, temp_timeperiodexclusion->timeperiod_ptr) == OK) { + return ERROR; + } + } + + for(temp_timerange = _get_matching_timerange(test_time, tperiod); temp_timerange != NULL; temp_timerange = temp_timerange->next) { day_range_start = (time_t)(midnight + temp_timerange->range_start); day_range_end = (time_t)(midnight + temp_timerange->range_end); - /* if the user-specified time falls in this range, return with a positive result */ if(test_time >= day_range_start && test_time <= day_range_end) return OK; } - return ERROR; } @@ -1124,414 +1181,167 @@ int check_time_against_period(time_t test_time, timeperiod *tperiod) { /*#define TEST_TIMEPERIODS_B 1*/ -/* Separate this out from public get_next_valid_time for testing, so we can mock current_time */ -void _get_next_valid_time(time_t pref_time, time_t current_time, time_t *valid_time, timeperiod *tperiod) { - time_t preferred_time = (time_t)0L; - timerange *temp_timerange; - daterange *temp_daterange; - time_t midnight = (time_t)0L; +void _get_next_valid_time(time_t pref_time, time_t *valid_time, timeperiod *tperiod); + +static void _get_next_invalid_time(time_t pref_time, time_t *invalid_time, timeperiod *tperiod) { + timeperiodexclusion *temp_timeperiodexclusion = NULL; + int depth = 0; + int max_depth = 300; // commonly roughly equal to "days in the future" struct tm *t, tm_s; - time_t day_start = (time_t)0L; + time_t earliest_time = pref_time; + time_t last_earliest_time = 0; + time_t midnight = (time_t)0L; time_t day_range_start = (time_t)0L; time_t day_range_end = (time_t)0L; - time_t start_time = (time_t)0L; - time_t end_time = (time_t)0L; - int have_earliest_time = FALSE; - time_t earliest_time = (time_t)0L; - time_t earliest_day = (time_t)0L; - time_t potential_time = (time_t)0L; - int weekday = 0; - int has_looped = FALSE; - int days_into_the_future = 0; - int daterange_type = 0; - unsigned long days = 0L; - unsigned long advance_interval = 0L; - int year = 0; /* new */ - int month = 0; /* new */ - int pref_time_year = 0; - int pref_time_mon = 0; - int pref_time_mday = 0; - int pref_time_wday = 0; - int current_time_year = 0; - int current_time_mon = 0; - int current_time_mday = 0; - int current_time_wday = 0; - int shift; - - /* preferred time must be now or in the future */ - preferred_time = (pref_time < current_time) ? current_time : pref_time; - - /* if no timeperiod, go with preferred time */ + /* if no period was specified, assume the time is good */ if(tperiod == NULL) { - *valid_time = preferred_time; + *invalid_time = pref_time; return; - } + } - /* if the preferred time is valid in timeperiod, go with it */ - /* this is necessary because the code below won't catch exceptions where preferred day is last (or only) date in timeperiod (date range) and last valid time has already passed */ - /* performing this check and bailing out early allows us to skip having to check the next instance of a date range exception or weekday to determine the next valid time */ - if(check_time_against_period(preferred_time, tperiod) == OK) { -#ifdef TEST_TIMEPERIODS_B - printf("PREF TIME IS VALID\n"); -#endif - *valid_time = preferred_time; - return; - } + while (earliest_time != last_earliest_time && depth < max_depth) { + time_t potential_time = 0; + depth++; + last_earliest_time = earliest_time; - /* calculate the start of the day (midnight, 00:00 hours) of preferred time */ - t = localtime_r(&preferred_time, &tm_s); - t->tm_sec = 0; - t->tm_min = 0; - t->tm_hour = 0; - midnight = mktime(t); + t = localtime_r((time_t *)&earliest_time, &tm_s); + t->tm_sec = 0; + t->tm_min = 0; + t->tm_hour = 0; + midnight = mktime(t); - /* save pref time values for later */ - pref_time_year = t->tm_year; - pref_time_mon = t->tm_mon; - pref_time_mday = t->tm_mday; - pref_time_wday = t->tm_wday; + timerange *temp_timerange = _get_matching_timerange(earliest_time, tperiod); - /* save current time values for later */ - t = localtime_r(¤t_time, &tm_s); - current_time_year = t->tm_year; - current_time_mon = t->tm_mon; - current_time_mday = t->tm_mday; - current_time_wday = t->tm_wday; - -#ifdef TEST_TIMEPERIODS_B - printf("PREF TIME: %lu = %s", (unsigned long)preferred_time, ctime(&preferred_time)); - printf("CURRENT TIME: %lu = %s", (unsigned long)current_time, ctime(¤t_time)); - printf("PREF YEAR: %d, MON: %d, MDAY: %d, WDAY: %d\n", pref_time_year, pref_time_mon, pref_time_mday, pref_time_wday); - printf("CURRENT YEAR: %d, MON: %d, MDAY: %d, WDAY: %d\n", current_time_year, current_time_mon, current_time_mday, current_time_wday); -#endif - - /**** check exceptions (in this timeperiod definition) first ****/ - for(daterange_type = 0; daterange_type < DATERANGE_TYPES; daterange_type++) { - -#ifdef TEST_TIMEPERIODS_B - printf("TYPE: %d\n", daterange_type); -#endif - - for(temp_daterange = tperiod->exceptions[daterange_type]; temp_daterange != NULL; temp_daterange = temp_daterange->next) { - - /* get the start time */ - switch(daterange_type) { - case DATERANGE_CALENDAR_DATE: /* 2009-08-11 */ - t->tm_sec = 0; - t->tm_min = 0; - t->tm_hour = 0; - t->tm_mday = temp_daterange->smday; - t->tm_mon = temp_daterange->smon; - t->tm_year = (temp_daterange->syear - 1900); - t->tm_isdst = -1; - start_time = mktime(t); - break; - case DATERANGE_MONTH_DATE: /* january 1 */ - /* what year should we use? */ - year = (pref_time_year < current_time_year) ? current_time_year : pref_time_year; - /* advance an additional year if we already passed the end month date */ - if((temp_daterange->emon < current_time_mon) || ((temp_daterange->emon == current_time_mon) && temp_daterange->emday < current_time_mday)) - year++; - start_time = calculate_time_from_day_of_month(year, temp_daterange->smon, temp_daterange->smday); - break; - case DATERANGE_MONTH_DAY: /* day 3 */ - /* what year should we use? */ - year = (pref_time_year < current_time_year) ? current_time_year : pref_time_year; - /* use current month */ - month = current_time_mon; - /* advance an additional month (and possibly the year) if we already passed the end day of month */ - if(temp_daterange->emday < current_time_mday) { - /*if(month==1){*/ - if(month == 11) { - month = 0; - year++; - } - else - month++; - } - start_time = calculate_time_from_day_of_month(year, month, temp_daterange->smday); - break; - case DATERANGE_MONTH_WEEK_DAY: /* thursday 2 april */ - /* what year should we use? */ - year = (pref_time_year < current_time_year) ? current_time_year : pref_time_year; - /* calculate time of specified weekday of specific month */ - start_time = calculate_time_from_weekday_of_month(year, temp_daterange->smon, temp_daterange->swday, temp_daterange->swday_offset); - /* advance to next year if we've passed this month weekday already this year */ - if(start_time < preferred_time) { - year++; - start_time = calculate_time_from_weekday_of_month(year, temp_daterange->smon, temp_daterange->swday, temp_daterange->swday_offset); - } - break; - case DATERANGE_WEEK_DAY: /* wednesday 1 */ - /* what year should we use? */ - year = (pref_time_year < current_time_year) ? current_time_year : pref_time_year; - /* calculate time of specified weekday of month */ - start_time = calculate_time_from_weekday_of_month(year, pref_time_mon, temp_daterange->swday, temp_daterange->swday_offset); - /* advance to next month (or year) if we've passed this weekday of this month already */ - if(start_time < preferred_time) { - month = pref_time_mon; - if(month == 11) { - month = 0; - year++; - } - else - month++; - start_time = calculate_time_from_weekday_of_month(year, month, temp_daterange->swday, temp_daterange->swday_offset); - } - break; - default: - continue; - break; - } - -#ifdef TEST_TIMEPERIODS_B - printf("START TIME: %lu = %s", start_time, ctime(&start_time)); -#endif - - /* get the end time */ - switch(daterange_type) { - case DATERANGE_CALENDAR_DATE: - t->tm_sec = 0; - t->tm_min = 0; - t->tm_hour = 0; - t->tm_mday = temp_daterange->emday; - t->tm_mon = temp_daterange->emon; - t->tm_year = (temp_daterange->eyear - 1900); - t->tm_isdst = -1; - end_time = mktime(t); - break; - case DATERANGE_MONTH_DATE: - /* use same year as was calculated for start time above */ - end_time = calculate_time_from_day_of_month(year, temp_daterange->emon, temp_daterange->emday); - /* advance a year if necessary: august 5 - feburary 2 */ - if(end_time < start_time) { - year++; - end_time = calculate_time_from_day_of_month(year, temp_daterange->emon, temp_daterange->emday); - } - break; - case DATERANGE_MONTH_DAY: - /* use same year and month as was calculated for start time above */ - end_time = calculate_time_from_day_of_month(year, month, temp_daterange->emday); - break; - case DATERANGE_MONTH_WEEK_DAY: - /* use same year as was calculated for start time above */ - end_time = calculate_time_from_weekday_of_month(year, temp_daterange->emon, temp_daterange->ewday, temp_daterange->ewday_offset); - /* advance a year if necessary: thursday 2 august - monday 3 february */ - if(end_time < start_time) { - year++; - end_time = calculate_time_from_weekday_of_month(year, temp_daterange->emon, temp_daterange->ewday, temp_daterange->ewday_offset); - } - break; - case DATERANGE_WEEK_DAY: - /* use same year and month as was calculated for start time above */ - end_time = calculate_time_from_weekday_of_month(year, month, temp_daterange->ewday, temp_daterange->ewday_offset); - break; - default: - continue; - break; - } - -#ifdef TEST_TIMEPERIODS_B - printf("STARTTIME: %lu = %s", (unsigned long)start_time, ctime(&start_time)); - printf("ENDTIME1: %lu = %s", (unsigned long)end_time, ctime(&end_time)); -#endif - - /* start date was bad, so skip this date range */ - if((unsigned long)start_time == 0L) + for(; temp_timerange != NULL; temp_timerange = temp_timerange->next) { + /* ranges with start/end of zero mean exclude this day */ + if(temp_timerange->range_start == 0 && temp_timerange->range_end == 0) continue; - /* end date was bad - see if we can handle the error */ - if((unsigned long)end_time == 0L) { - switch(daterange_type) { - case DATERANGE_CALENDAR_DATE: - continue; - break; - case DATERANGE_MONTH_DATE: - /* end date can't be helped, so skip it */ - if(temp_daterange->emday < 0) - continue; - - /* else end date slipped past end of month, so use last day of month as end date */ - end_time = calculate_time_from_day_of_month(year, temp_daterange->emon, -1); - break; - case DATERANGE_MONTH_DAY: - /* end date can't be helped, so skip it */ - if(temp_daterange->emday < 0) - continue; - - /* else end date slipped past end of month, so use last day of month as end date */ - end_time = calculate_time_from_day_of_month(year, month, -1); - break; - case DATERANGE_MONTH_WEEK_DAY: - /* end date can't be helped, so skip it */ - if(temp_daterange->ewday_offset < 0) - continue; - - /* else end date slipped past end of month, so use last day of month as end date */ - end_time = calculate_time_from_day_of_month(year, pref_time_mon, -1); - break; - case DATERANGE_WEEK_DAY: - /* end date can't be helped, so skip it */ - if(temp_daterange->ewday_offset < 0) - continue; - - /* else end date slipped past end of month, so use last day of month as end date */ - end_time = calculate_time_from_day_of_month(year, month, -1); - break; - default: - continue; - break; - } - } + day_range_start = (time_t)(midnight + temp_timerange->range_start); + day_range_end = (time_t)(midnight + temp_timerange->range_end); #ifdef TEST_TIMEPERIODS_B - printf("ENDTIME2: %lu = %s", (unsigned long)end_time, ctime(&end_time)); + printf(" INVALID RANGE START: %lu (%lu) = %s", temp_timerange->range_start, (unsigned long)day_range_start, ctime(&day_range_start)); + printf(" INVALID RANGE END: %lu (%lu) = %s", temp_timerange->range_end, (unsigned long)day_range_end, ctime(&day_range_end)); #endif - /* if skipping days... */ - if(temp_daterange->skip_interval > 1) { - - /* advance to the next possible skip date */ - if(start_time < preferred_time) { - /* check if interval is across dlst change and gets the compensation */ - shift = get_dst_shift(&start_time, &midnight); - - /* how many days have passed between skip start date and preferred time? */ - days = (shift + (unsigned long)midnight - (unsigned long)start_time) / (3600 * 24); - -#ifdef TEST_TIMEPERIODS_B - printf("MIDNIGHT: %lu = %s", midnight, ctime(&midnight)); - printf("%lu SECONDS PASSED\n", (midnight - (unsigned long)start_time)); - printf("%d DAYS PASSED\n", days); - printf("REMAINDER: %d\n", (days % temp_daterange->skip_interval)); - printf("SKIP INTERVAL: %d\n", temp_daterange->skip_interval); - printf("DLST SHIFT: %d", shift); -#endif - - /* advance start date to next skip day */ - if((days % temp_daterange->skip_interval) == 0) - start_time += (days * 3600 * 24); - else - start_time += ((days - (days % temp_daterange->skip_interval) + temp_daterange->skip_interval) * 3600 * 24); - } - - /* if skipping has no end, use start date as end */ - if((daterange_type == DATERANGE_CALENDAR_DATE) && is_daterange_single_day(temp_daterange) == TRUE) - end_time = start_time; - } - -#ifdef TEST_TIMEPERIODS_B - printf("\nSTART: %lu = %s", (unsigned long)start_time, ctime(&start_time)); - printf("END: %lu = %s", (unsigned long)end_time, ctime(&end_time)); - printf("PREFERRED: %lu = %s", (unsigned long)preferred_time, ctime(&preferred_time)); - printf("CURRENT: %lu = %s", (unsigned long)current_time, ctime(¤t_time)); -#endif - - /* skip this date range its out of bounds with what we want */ - if(preferred_time > end_time) - continue; - - /* how many days at a time should we advance? */ - if(temp_daterange->skip_interval > 1) - advance_interval = temp_daterange->skip_interval; + if(day_range_start <= earliest_time && day_range_end > earliest_time) + potential_time = day_range_end + 60; else - advance_interval = 1; - - /* advance through the date range */ - for(day_start = start_time; day_start <= end_time; day_start += (advance_interval * 3600 * 24)) { - - /* we already found a time from a higher-precendence date range exception */ - if(day_start >= earliest_day && have_earliest_time == TRUE) - continue; - - for(temp_timerange = temp_daterange->times; temp_timerange != NULL; temp_timerange = temp_timerange->next) { - - /* ranges with start/end of zero mean exlude this day */ - if(temp_timerange->range_start == 0 && temp_timerange->range_end == 0) - continue; - - day_range_start = (time_t)(day_start + temp_timerange->range_start); - day_range_end = (time_t)(day_start + temp_timerange->range_end); + potential_time = earliest_time; + if(potential_time > earliest_time) { + earliest_time = potential_time; #ifdef TEST_TIMEPERIODS_B - printf(" RANGE START: %lu (%lu) = %s", temp_timerange->range_start, (unsigned long)day_range_start, ctime(&day_range_start)); - printf(" RANGE END: %lu (%lu) = %s", temp_timerange->range_end, (unsigned long)day_range_end, ctime(&day_range_end)); + printf(" EARLIEST INVALID TIME: %llu = %s", (unsigned long long)earliest_time, ctime(&earliest_time)); #endif - - /* range is out of bounds */ - if(day_range_end < preferred_time) - continue; - - /* preferred time occurs before range start, so use range start time as earliest potential time */ - if(day_range_start >= preferred_time) - potential_time = day_range_start; - /* preferred time occurs between range start/end, so use preferred time as earliest potential time */ - else if(day_range_end >= preferred_time) - potential_time = preferred_time; - - /* is this the earliest time found thus far? */ - if(have_earliest_time == FALSE || potential_time < earliest_time) { - have_earliest_time = TRUE; - earliest_time = potential_time; - earliest_day = day_start; -#ifdef TEST_TIMEPERIODS_B - printf(" EARLIEST TIME: %lu = %s", (unsigned long)earliest_time, ctime(&earliest_time)); -#endif - } - } } } + for(temp_timeperiodexclusion = tperiod->exclusions; temp_timeperiodexclusion != NULL; temp_timeperiodexclusion = temp_timeperiodexclusion->next) { + _get_next_valid_time(last_earliest_time, &potential_time, temp_timeperiodexclusion->timeperiod_ptr); + if (potential_time + 60 < earliest_time) + earliest_time = potential_time + 60; + } } +#ifdef TEST_TIMEPERIODS_B + printf(" FINAL EARLIEST INVALID TIME: %llu = %s", (unsigned long long)earliest_time, ctime(&earliest_time)); +#endif + if (depth == max_depth) + *invalid_time = pref_time; + else + *invalid_time = earliest_time; + } - /**** find next available time from normal, weekly rotating schedule (in this timeperiod definition) ****/ +/* Separate this out from public get_next_valid_time for testing */ +void _get_next_valid_time(time_t pref_time, time_t *valid_time, timeperiod *tperiod) { + timeperiodexclusion *temp_timeperiodexclusion = NULL; + int depth = 0; + int max_depth = 300; // commonly roughly equal to "days in the future" + time_t earliest_time = pref_time; + time_t last_earliest_time = 0; + struct tm *t, tm_s; + time_t midnight = (time_t)0L; + time_t day_range_start = (time_t)0L; + time_t day_range_end = (time_t)0L; + int have_earliest_time = FALSE; - /* check a one week rotation of time */ - has_looped = FALSE; - for(weekday = pref_time_wday, days_into_the_future = 0;; weekday++, days_into_the_future++) { + /* if no period was specified, assume the time is good */ + if(tperiod == NULL) { + *valid_time = pref_time; + return; + } - /* break out of the loop if we have checked an entire week already */ - if(has_looped == TRUE && weekday >= pref_time_wday) - break; + while (earliest_time != last_earliest_time && depth < max_depth) { + time_t potential_time = 0; + have_earliest_time = FALSE; + depth++; + last_earliest_time = earliest_time; - if(weekday >= 7) { - weekday -= 7; - has_looped = TRUE; + t = localtime_r((time_t *)&earliest_time, &tm_s); + t->tm_sec = 0; + t->tm_min = 0; + t->tm_hour = 0; + midnight = mktime(t); + + timerange *temp_timerange = _get_matching_timerange(earliest_time, tperiod); +#ifdef TEST_TIMEPERIODS_B + printf(" RANGE START: %lu\n", temp_timerange ? temp_timerange->range_start : 0); + printf(" RANGE END: %lu\n", temp_timerange ? temp_timerange->range_end : 0); +#endif + + for(; temp_timerange != NULL; temp_timerange = temp_timerange->next) { + /* ranges with start/end of zero mean exclude this day */ + if(temp_timerange->range_start == 0 && temp_timerange->range_end == 0) + continue; + + day_range_start = (time_t)(midnight + temp_timerange->range_start); + day_range_end = (time_t)(midnight + temp_timerange->range_end); + +#ifdef TEST_TIMEPERIODS_B + printf(" RANGE START: %lu (%lu) = %s", temp_timerange->range_start, (unsigned long)day_range_start, ctime(&day_range_start)); + printf(" RANGE END: %lu (%lu) = %s", temp_timerange->range_end, (unsigned long)day_range_end, ctime(&day_range_end)); +#endif + + /* range is out of bounds */ + if(day_range_end < last_earliest_time) + continue; + + /* preferred time occurs before range start, so use range start time as earliest potential time */ + if(day_range_start >= last_earliest_time) + potential_time = day_range_start; + /* preferred time occurs between range start/end, so use preferred time as earliest potential time */ + else if(day_range_end >= last_earliest_time) + potential_time = last_earliest_time; + + /* is this the earliest time found thus far? */ + if(have_earliest_time == FALSE || potential_time < earliest_time) { + earliest_time = potential_time; +#ifdef TEST_TIMEPERIODS_B + printf(" EARLIEST TIME: %llu = %s", (unsigned long long)earliest_time, ctime(&earliest_time)); +#endif + } + have_earliest_time = TRUE; } - /* calculate start of this future weekday */ - day_start = (time_t)(midnight + (days_into_the_future * 3600 * 24)); - - /* we already found a time from a higher-precendence date range exception */ - if(day_start == earliest_day) - continue; - - /* check all time ranges for this day of the week */ - for(temp_timerange = tperiod->days[weekday]; temp_timerange != NULL; temp_timerange = temp_timerange->next) { - - /* calculate the time for the start of this time range */ - day_range_start = (time_t)(day_start + temp_timerange->range_start); - - if((have_earliest_time == FALSE || day_range_start < earliest_time) && day_range_start >= preferred_time) { - have_earliest_time = TRUE; - earliest_time = day_range_start; - earliest_day = day_start; + if (have_earliest_time == FALSE) { + earliest_time = midnight + 86400; + } else { + for(temp_timeperiodexclusion = tperiod->exclusions; temp_timeperiodexclusion != NULL; temp_timeperiodexclusion = temp_timeperiodexclusion->next) { + _get_next_invalid_time(earliest_time, &earliest_time, temp_timeperiodexclusion->timeperiod_ptr); +#ifdef TEST_TIMEPERIODS_B + printf(" FINAL EARLIEST TIME: %llu = %s", (unsigned long long)earliest_time, ctime(&earliest_time)); +#endif } } } - - /* if we couldn't find a time period there must be none defined */ - if(have_earliest_time == FALSE || earliest_time == (time_t)0) - *valid_time = (time_t)preferred_time; - - /* else use the calculated time */ + if (depth == max_depth) + *valid_time = pref_time; else *valid_time = earliest_time; - - return; } @@ -1544,7 +1354,9 @@ void get_next_valid_time(time_t pref_time, time_t *valid_time, timeperiod *tperi /* get time right now, preferred time must be now or in the future */ time(¤t_time); - _get_next_valid_time(pref_time, current_time, valid_time, tperiod); + pref_time = (pref_time < current_time) ? current_time : pref_time; + + _get_next_valid_time(pref_time, valid_time, tperiod); } @@ -1776,6 +1588,9 @@ time_t get_next_log_rotation_time(void) { /* trap signals so we can exit gracefully */ void setup_sighandler(void) { +#ifdef HAVE_SIGACTION + struct sigaction sig_action; +#endif /* reset the shutdown flag */ sigshutdown = FALSE; @@ -1786,12 +1601,28 @@ void setup_sighandler(void) { setbuf(stderr, (char *)NULL); /* initialize signal handling */ +#ifdef HAVE_SIGACTION + sig_action.sa_sigaction = NULL; + sig_action.sa_handler = SIG_IGN; + sigemptyset(&sig_action.sa_mask); + sig_action.sa_flags = 0; + sigaction(SIGPIPE, &sig_action, NULL); + sig_action.sa_handler = sighandler; + sigfillset(&sig_action.sa_mask); + sig_action.sa_flags = SA_NODEFER|SA_RESTART; + sigaction(SIGQUIT, &sig_action, NULL); + sigaction(SIGTERM, &sig_action, NULL); + sigaction(SIGHUP, &sig_action, NULL); + if(daemon_dumps_core == FALSE && daemon_mode == TRUE) + sigaction(SIGSEGV, &sig_action, NULL); +#else /* HAVE_SIGACTION */ signal(SIGPIPE, SIG_IGN); signal(SIGQUIT, sighandler); signal(SIGTERM, sighandler); signal(SIGHUP, sighandler); if(daemon_dumps_core == FALSE && daemon_mode == TRUE) signal(SIGSEGV, sighandler); +#endif /* HAVE_SIGACTION */ return; } @@ -1801,12 +1632,26 @@ void setup_sighandler(void) { void reset_sighandler(void) { /* set signal handling to default actions */ +#ifdef HAVE_SIGACTION + struct sigaction sig_action; + sig_action.sa_sigaction = NULL; + sig_action.sa_handler = SIG_DFL; + sigemptyset(&sig_action.sa_mask); + sig_action.sa_flags = 0; + sigaction(SIGQUIT, &sig_action, NULL); + sigaction(SIGTERM, &sig_action, NULL); + sigaction(SIGHUP, &sig_action, NULL); + sigaction(SIGSEGV, &sig_action, NULL); + sigaction(SIGPIPE, &sig_action, NULL); + sigaction(SIGXFSZ, &sig_action, NULL); +#else /* HAVE_SIGACTION */ signal(SIGQUIT, SIG_DFL); signal(SIGTERM, SIG_DFL); signal(SIGHUP, SIG_DFL); signal(SIGSEGV, SIG_DFL); signal(SIGPIPE, SIG_DFL); signal(SIGXFSZ, SIG_DFL); +#endif /* HAVE_SIGACTION */ return; } @@ -1814,6 +1659,7 @@ void reset_sighandler(void) { /* handle signals */ void sighandler(int sig) { + const char *sigs[35] = {"EXIT", "HUP", "INT", "QUIT", "ILL", "TRAP", "ABRT", "BUS", "FPE", "KILL", "USR1", "SEGV", "USR2", "PIPE", "ALRM", "TERM", "STKFLT", "CHLD", "CONT", "STOP", "TSTP", "TTIN", "TTOU", "URG", "XCPU", "XFSZ", "VTALRM", "PROF", "WINCH", "IO", "PWR", "UNUSED", "ZERR", "DEBUG", (char *)NULL}; int x = 0; /* if shutdown is already true, we're in a signal trap loop! */ @@ -1831,29 +1677,34 @@ void sighandler(int sig) { sig_id = sig; - /* log errors about segfaults now, as we might not get a chance to later */ - /* all other signals are logged at a later point in main() to prevent problems with NPTL */ - if(sig == SIGSEGV) - logit(NSLOG_PROCESS_INFO, TRUE, "Caught SIG%s, shutting down...\n", sigs[sig]); - /* we received a SIGHUP, so restart... */ if(sig == SIGHUP) sigrestart = TRUE; /* else begin shutting down... */ - else if(sig < 16) + else if(sig < 16) { + logit(NSLOG_PROCESS_INFO, TRUE, "Caught SIG%s, shutting down...\n", sigs[sig]); sigshutdown = TRUE; + } return; } +/* handle timeouts when executing commands via my_system_r() */ +void my_system_sighandler(int sig) { + + /* force the child process to exit... */ + _exit(STATE_CRITICAL); + } + + /* Handle the SIGXFSZ signal. A SIGXFSZ signal is received when a file exceeds - the maximum allowable size either as dictated by the fzise paramater in + the maximum allowable size either as dictated by the fzise parameter in /etc/security/limits.conf (ulimit -f) or by the maximum size allowed by the filesystem */ void handle_sigxfsz(int sig) { - static time_t lastlog_time = (time_t)0; /* Save the last log time so we + static time_t lastlog_time = (time_t)0; /* Save the last log time so we don't log too often. */ unsigned long log_interval = 300; /* How frequently to log messages about receiving the signal */ @@ -1862,12 +1713,12 @@ void handle_sigxfsz(int sig) { char *files[] = { log_file, debug_file, - xpddefault_host_perfdata_file, - xpddefault_service_perfdata_file, - xodtemplate_cache_file, - xodtemplate_precache_file, - xsddefault_status_log, - xrddefault_retention_file, + host_perfdata_file, + service_perfdata_file, + object_cache_file, + object_precache_file, + status_file, + retention_file, }; int x; char **filep; @@ -1885,14 +1736,14 @@ void handle_sigxfsz(int sig) { if(getrlimit(RLIMIT_FSIZE, &rlim) != 0) { /* Attempt to log the error, realizing that the logging may fail if it is the log file that is over the size limit. */ - logit(NSLOG_RUNTIME_ERROR, TRUE, - "Unable to determine current resoure limits: %s\n", + logit(NSLOG_RUNTIME_ERROR, TRUE, + "Unable to determine current resource limits: %s\n", strerror(errno)); } - /* Try to figure out which file caused the signal and react + /* Try to figure out which file caused the signal and react appropriately */ - for(x = 0, filep = files; x < (sizeof(files) / sizeof(files[0])); + for(x = 0, filep = files; x < (sizeof(files) / sizeof(files[0])); x++, filep++) { if((*filep != NULL) && strcmp(*filep, "/dev/null")) { if((size = check_file_size(*filep, 1024, rlim)) == -1) { @@ -1905,15 +1756,12 @@ void handle_sigxfsz(int sig) { } } } - /* TODO: Perhaps add check of the check results files in - check_results_path. This is likely not needed because these - files aren't very big */ if((max_size > 0) && (max_name != NULL)) { logit(NSLOG_RUNTIME_ERROR, TRUE, "SIGXFSZ received because a " "file's size may have exceeded the file size limits of " "the filesystem. The largest file checked, '%s', has a " "size of %lld bytes", max_name, max_size); - + } else { logit(NSLOG_RUNTIME_ERROR, TRUE, "SIGXFSZ received but unable to " @@ -1924,10 +1772,10 @@ void handle_sigxfsz(int sig) { } /* Checks a file to determine whether it exceeds resource limit imposed - limits. Returns the file size if file is OK, 0 if it's status could not - be determined, or -1 if not OK. fudge is the fudge factor (in bytes) for + limits. Returns the file size if file is OK, 0 if it's status could not + be determined, or -1 if not OK. fudge is the fudge factor (in bytes) for checking the file size */ -static long long check_file_size(char *path, unsigned long fudge, +static long long check_file_size(char *path, unsigned long fudge, struct rlimit rlim) { struct stat status; @@ -1941,14 +1789,14 @@ static long long check_file_size(char *path, unsigned long fudge, if(stat(path, &status) == 0) { /* Make sure it is a file */ if(S_ISREG(status.st_mode)) { - /* If the file size plus the fudge factor exceeds the + /* If the file size plus the fudge factor exceeds the current resource limit imposed size limit, log an error */ if(status.st_size + fudge > rlim.rlim_cur) { logit(NSLOG_RUNTIME_ERROR, TRUE, "Size of file '%s' (%llu) " "exceeds (or nearly exceeds) size imposed by resource " "limits (%llu). Consider increasing limits with " - "ulimit(1).\n", path, - (unsigned long long)status.st_size, + "ulimit(1).\n", path, + (unsigned long long)status.st_size, (unsigned long long)rlim.rlim_cur); return -1; } @@ -1962,102 +1810,13 @@ static long long check_file_size(char *path, unsigned long fudge, } else { /* If we could not determine the file status, log an error message */ - logit(NSLOG_RUNTIME_ERROR, TRUE, - "Unable to determine status of file %s: %s\n", + logit(NSLOG_RUNTIME_ERROR, TRUE, + "Unable to determine status of file %s: %s\n", log_file, strerror(errno)); return 0; } } -/* handle timeouts when executing service checks */ -/* 07/16/08 EG also called when parent process gets a TERM signal */ -void service_check_sighandler(int sig) { - struct timeval end_time; - - /* get the current time */ - gettimeofday(&end_time, NULL); - - check_result_info.return_code = service_check_timeout_state; - check_result_info.finish_time = end_time; - check_result_info.early_timeout = TRUE; - - /* write check result to file */ - if(check_result_info.output_file_fp) { - - fprintf(check_result_info.output_file_fp, "finish_time=%lu.%lu\n", check_result_info.finish_time.tv_sec, check_result_info.finish_time.tv_usec); - fprintf(check_result_info.output_file_fp, "early_timeout=%d\n", check_result_info.early_timeout); - fprintf(check_result_info.output_file_fp, "exited_ok=%d\n", check_result_info.exited_ok); - fprintf(check_result_info.output_file_fp, "return_code=%d\n", check_result_info.return_code); - fprintf(check_result_info.output_file_fp, "output=%s\n", "(Service Check Timed Out)"); - - /* close the temp file */ - fclose(check_result_info.output_file_fp); - - /* move check result to queue directory */ - move_check_result_to_queue(check_result_info.output_file); - } - - /* free check result memory */ - free_check_result(&check_result_info); - - /* try to kill the command that timed out by sending termination signal to our process group */ - /* we also kill ourselves while doing this... */ - kill((pid_t)0, SIGKILL); - - /* force the child process (service check) to exit... */ - _exit(STATE_CRITICAL); - } - - -/* handle timeouts when executing host checks */ -/* 07/16/08 EG also called when parent process gets a TERM signal */ -void host_check_sighandler(int sig) { - struct timeval end_time; - - /* get the current time */ - gettimeofday(&end_time, NULL); - - check_result_info.return_code = STATE_CRITICAL; - check_result_info.finish_time = end_time; - check_result_info.early_timeout = TRUE; - - /* write check result to file */ - if(check_result_info.output_file_fp) { - - fprintf(check_result_info.output_file_fp, "finish_time=%lu.%lu\n", check_result_info.finish_time.tv_sec, check_result_info.finish_time.tv_usec); - fprintf(check_result_info.output_file_fp, "early_timeout=%d\n", check_result_info.early_timeout); - fprintf(check_result_info.output_file_fp, "exited_ok=%d\n", check_result_info.exited_ok); - fprintf(check_result_info.output_file_fp, "return_code=%d\n", check_result_info.return_code); - fprintf(check_result_info.output_file_fp, "output=%s\n", "(Host Check Timed Out)"); - - /* close the temp file */ - fclose(check_result_info.output_file_fp); - - /* move check result to queue directory */ - move_check_result_to_queue(check_result_info.output_file); - } - - /* free check result memory */ - free_check_result(&check_result_info); - - /* try to kill the command that timed out by sending termination signal to our process group */ - /* we also kill ourselves while doing this... */ - kill((pid_t)0, SIGKILL); - - /* force the child process (service check) to exit... */ - _exit(STATE_CRITICAL); - } - - -/* handle timeouts when executing commands via my_system_r() */ -void my_system_sighandler(int sig) { - - /* force the child process to exit... */ - _exit(STATE_CRITICAL); - } - - - /******************************************************************/ /************************ DAEMON FUNCTIONS ************************/ @@ -2071,20 +1830,43 @@ int daemon_init(void) { char buf[256]; struct flock lock; char *homedir = NULL; + char *cp; #ifdef RLIMIT_CORE struct rlimit limit; #endif /* change working directory. scuttle home if we're dumping core */ - homedir = getenv("HOME"); - if(daemon_dumps_core == TRUE && homedir != NULL) - chdir(homedir); - else - chdir("/"); + if(daemon_dumps_core == TRUE) { + homedir = getenv("HOME"); + if (homedir && *homedir) + chdir(homedir); + else if (log_file && *log_file) { + homedir = strdup(log_file); + cp = strrchr(homedir, '/'); + if (cp) + *cp = '\0'; + else + strcpy(homedir, "/"); + chdir(homedir); + free(homedir); + } else + chdir("/"); + } umask(S_IWGRP | S_IWOTH); + /* close existing stdin, stdout, stderr */ + close(0); + close(1); + close(2); + + /* THIS HAS TO BE DONE TO AVOID PROBLEMS WITH STDERR BEING REDIRECTED TO SERVICE MESSAGE PIPE! */ + /* re-open stdin, stdout, stderr with known values */ + open("/dev/null", O_RDONLY); + open("/dev/null", O_WRONLY); + open("/dev/null", O_WRONLY); + lockfile = open(lock_file, O_RDWR | O_CREAT, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH); if(lockfile < 0) { @@ -2167,17 +1949,6 @@ int daemon_init(void) { val |= FD_CLOEXEC; fcntl(lockfile, F_SETFD, val); - /* close existing stdin, stdout, stderr */ - close(0); - close(1); - close(2); - - /* THIS HAS TO BE DONE TO AVOID PROBLEMS WITH STDERR BEING REDIRECTED TO SERVICE MESSAGE PIPE! */ - /* re-open stdin, stdout, stderr with known values */ - open("/dev/null", O_RDONLY); - open("/dev/null", O_WRONLY); - open("/dev/null", O_WRONLY); - #ifdef USE_EVENT_BROKER /* send program data to broker */ broker_program_state(NEBTYPE_PROCESS_DAEMONIZE, NEBFLAG_NONE, NEBATTR_NONE, NULL); @@ -2199,9 +1970,9 @@ int drop_privileges(char *user, char *group) { struct group *grp = NULL; struct passwd *pw = NULL; int result = OK; - - log_debug_info(DEBUGL_FUNCTIONS, 0, "drop_privileges() start\n"); - log_debug_info(DEBUGL_PROCESS, 0, "Original UID/GID: %d/%d\n", (int)getuid(), (int)getgid()); +#ifdef HAVE_SYS_RESOURCE_H + struct rlimit rl; +#endif /* only drop privileges if we're running as root, so we don't interfere with being debugged while running as some random user */ if(getuid() != 0) @@ -2222,18 +1993,8 @@ int drop_privileges(char *user, char *group) { /* else we were passed the GID */ else gid = (gid_t)atoi(group); - - /* set effective group ID if other than current EGID */ - if(gid != getegid()) { - - if(setgid(gid) == -1) { - logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Could not set effective GID=%d", (int)gid); - result = ERROR; - } - } } - /* set effective user ID */ if(user != NULL) { @@ -2249,32 +2010,53 @@ int drop_privileges(char *user, char *group) { /* else we were passed the UID */ else uid = (uid_t)atoi(user); + } -#ifdef HAVE_INITGROUPS + /* now that we know what to change to, we fix log file permissions */ + fix_log_file_owner(uid, gid); - if(uid != geteuid()) { - - /* initialize supplementary groups */ - if(initgroups(user, gid) == -1) { - if(errno == EPERM) - logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Unable to change supplementary groups using initgroups() -- I hope you know what you're doing"); - else { - logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Possibly root user failed dropping privileges with initgroups()"); - return ERROR; - } - } - } -#endif - /* Change the ownership on the debug log file */ - chown_debug_log(uid, gid); - - if(setuid(uid) == -1) { - logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Could not set effective UID=%d", (int)uid); + /* set effective group ID if other than current EGID */ + if(gid != getegid()) { + if(setgid(gid) == -1) { + logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Could not set effective GID=%d", (int)gid); result = ERROR; } } +#ifdef HAVE_INITGROUPS - log_debug_info(DEBUGL_PROCESS, 0, "New UID/GID: %d/%d\n", (int)getuid(), (int)getgid()); + if(uid != geteuid()) { + + /* initialize supplementary groups */ + if(initgroups(user, gid) == -1) { + if(errno == EPERM) + logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Unable to change supplementary groups using initgroups() -- I hope you know what you're doing"); + else { + logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Possibly root user failed dropping privileges with initgroups()"); + return ERROR; + } + } + } +#endif + +#ifdef HAVE_SYS_RESOURCE_H + if (result == OK && daemon_dumps_core == TRUE) { + rl.rlim_cur = RLIM_INFINITY; + rl.rlim_max = RLIM_INFINITY; + setrlimit(RLIMIT_CORE, &rl); + } +#endif + + if(setuid(uid) == -1) { + logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Could not set effective UID=%d", (int)uid); + result = ERROR; + } + +#ifdef HAVE_SYS_PRCTL_H + if (result == OK && daemon_dumps_core == TRUE) { + if (prctl(PR_SET_DUMPABLE, 1)) + logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Call to prctl(PR_SET_DUMPABLE, 1) failed with error %d", errno); + } +#endif return result; } @@ -2286,69 +2068,6 @@ int drop_privileges(char *user, char *group) { /************************* IPC FUNCTIONS **************************/ /******************************************************************/ -/* move check result to queue directory */ -int move_check_result_to_queue(char *checkresult_file) { - char *output_file = NULL; - char *temp_buffer = NULL; - int output_file_fd = -1; - mode_t new_umask = 077; - mode_t old_umask; - int result = 0; - - /* save the file creation mask */ - old_umask = umask(new_umask); - - /* create a safe temp file */ - asprintf(&output_file, "%s/cXXXXXX", check_result_path); - output_file_fd = mkstemp(output_file); - - /* file created okay */ - if(output_file_fd >= 0) { - - log_debug_info(DEBUGL_CHECKS, 2, "Moving temp check result file '%s' to queue file '%s'...\n", checkresult_file, output_file); - -#ifdef __CYGWIN__ - /* Cygwin cannot rename open files - gives Permission Denied */ - /* close the file */ - close(output_file_fd); -#endif - - /* move the original file */ - result = my_rename(checkresult_file, output_file); - -#ifndef __CYGWIN__ - /* close the file */ - close(output_file_fd); -#endif - - /* create an ok-to-go indicator file */ - asprintf(&temp_buffer, "%s.ok", output_file); - if((output_file_fd = open(temp_buffer, O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR)) >= 0) - close(output_file_fd); - my_free(temp_buffer); - - /* delete the original file if it couldn't be moved */ - if(result != 0) - unlink(checkresult_file); - } - else - result = -1; - - /* reset the file creation mask */ - umask(old_umask); - - /* log a warning on errors */ - if(result != 0) - logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Unable to move file '%s' to check results queue.\n", checkresult_file); - - /* free memory */ - my_free(output_file); - - return OK; - } - - - /* processes files in the check result queue directory */ int process_check_result_queue(char *dirname) { char file[MAX_FILENAME_LENGTH]; @@ -2358,7 +2077,8 @@ int process_check_result_queue(char *dirname) { struct stat stat_buf; struct stat ok_stat_buf; char *temp_buffer = NULL; - int result = OK; + int result = OK, check_result_files = 0; + time_t start; /* make sure we have what we need */ if(dirname == NULL) { @@ -2374,8 +2094,21 @@ int process_check_result_queue(char *dirname) { log_debug_info(DEBUGL_CHECKS, 1, "Starting to read check result queue '%s'...\n", dirname); + start = time(NULL); + /* process all files in the directory... */ while((dirfile = readdir(dirp)) != NULL) { + /* bail out if we encountered a signal */ + if (sigshutdown == TRUE || sigrestart == TRUE) { + log_debug_info(DEBUGL_CHECKS, 0, "Breaking out of check result reaper: signal encountered\n"); + break; + } + + /* break out if we've been here too long */ + if (start + max_check_reaper_time < time(NULL)) { + log_debug_info(DEBUGL_CHECKS, 0, "Breaking out of check result reaper: max time (%ds) exceeded\n", max_check_reaper_time); + break; + } /* create /path/to/file */ snprintf(file, sizeof(file), "%s/%s", dirname, dirfile->d_name); @@ -2390,22 +2123,18 @@ int process_check_result_queue(char *dirname) { continue; } - switch(stat_buf.st_mode & S_IFMT) { - - case S_IFREG: - /* don't process symlinked files */ - if(!S_ISREG(stat_buf.st_mode)) - continue; - break; - - default: - /* everything else we ignore */ - continue; - break; - } + /* we only care about real files */ + if (!S_ISREG(stat_buf.st_mode)) + continue; /* at this point we have a regular file... */ + /* if the file is too old, we delete it */ + if (stat_buf.st_mtime + max_check_result_file_age < time(NULL)) { + delete_check_result_file(dirfile->d_name); + continue; + } + /* can we find the associated ok-to-go file ? */ asprintf(&temp_buffer, "%s.ok", file); result = stat(temp_buffer, &ok_stat_buf); @@ -2414,166 +2143,85 @@ int process_check_result_queue(char *dirname) { continue; /* process the file */ - result = process_check_result_file(file, &check_result_list, - TRUE, TRUE); - - /* break out if we encountered an error */ - if(result == ERROR) - break; - } - } - - closedir(dirp); - - return result; - - } - - - - -/* Find checks that are currently executing. This function is intended to - be used on a Nagios restart to prevent currently executing checks from - being rescheduled. */ -int find_executing_checks(char *dirname) { - char file[MAX_FILENAME_LENGTH]; - DIR *dirp = NULL; - struct dirent *dirfile = NULL; - int x = 0; - struct stat stat_buf; - int result = OK; - check_result *crl = NULL; - check_result *cr = NULL; - service *svc = NULL; - host *host = NULL; - time_t current_time; - - log_debug_info(DEBUGL_FUNCTIONS, 0, "find_executing_checks() start\n"); - - /* make sure we have what we need */ - if(dirname == NULL) { - logit(NSLOG_CONFIG_ERROR, TRUE, "Error: No check directory specified.\n"); - return ERROR; - } - - /* open the directory for reading */ - if((dirp = opendir(dirname)) == NULL) { - logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not open check directory '%s' for reading.\n", dirname); - return ERROR; - } - - log_debug_info(DEBUGL_CHECKS, 1, "Starting to read check directory '%s'...\n", dirname); - - /* process all files in the directory... */ - while((dirfile = readdir(dirp)) != NULL) { - - /* create /path/to/file */ - snprintf(file, sizeof(file), "%s/%s", dirname, dirfile->d_name); - file[sizeof(file) - 1] = '\x0'; - - /* process this if it's a check result file... */ - x = strlen(dirfile->d_name); - if(x == 11 && !strncmp(dirfile->d_name, "check", 5)) { - - if(stat(file, &stat_buf) == -1) { - logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Could not stat() check status '%s'.\n", file); - continue; - } - - switch(stat_buf.st_mode & S_IFMT) { - - case S_IFREG: - /* don't process symlinked files */ - if(!S_ISREG(stat_buf.st_mode)) - continue; - break; - - default: - /* everything else we ignore */ - continue; - break; - } - - /* at this point we have a regular file... */ - log_debug_info(DEBUGL_CHECKS, 2, - "Looking for still-executing checks in %s.\n", file); - - /* process the file */ - result = process_check_result_file(file, &crl, FALSE, FALSE); + result = process_check_result_file(file); /* break out if we encountered an error */ if(result == ERROR) break; - time(¤t_time); - - /* examine the check results */ - while((cr = read_check_result(&crl)) != NULL) { - if(HOST_CHECK == cr->object_check_type) { - log_debug_info(DEBUGL_CHECKS, 2, - "Determining whether check for host '%s' is still executing.\n", - cr->host_name); - if((host = find_host(cr->host_name)) == NULL) { - logit(NSLOG_RUNTIME_WARNING, TRUE, - "Warning: Check status contained host '%s', " - "but the host could not be found! Ignoring " - "check.\n", cr->host_name); - } - else if(current_time - cr->start_time.tv_sec < - host_check_timeout) { - log_debug_info(DEBUGL_CHECKS, 1, - "Check for host %s is still executing.\n", - cr->host_name); - host->is_executing = TRUE; - } - } - else if(SERVICE_CHECK == cr->object_check_type) { - log_debug_info(DEBUGL_CHECKS, 2, - "Determining whether check for service '%s' on host '%s' is still executing.\n", - cr->host_name, cr->service_description); - if((svc = find_service(cr->host_name, - cr->service_description)) == NULL) { - logit(NSLOG_RUNTIME_WARNING, TRUE, - "Warning: Check status contained service '%s' " - "on host '%s', but the service could not be " - "found! Ignoring check.\n", - cr->service_description, cr->host_name); - } - else if(current_time - cr->start_time.tv_sec < - service_check_timeout) { - log_debug_info(DEBUGL_CHECKS, 1, - "Check for service %s:%s is still executing.\n", - cr->host_name, cr->service_description); - svc->is_executing = TRUE; - } - } - free_check_result_list(&crl); - } + check_result_files++; } } closedir(dirp); - return result; + return check_result_files; } +int process_check_result(check_result *cr) +{ + const char *source_name; + if (!cr) + return ERROR; + source_name = check_result_source(cr); + + if (cr->object_check_type == SERVICE_CHECK) { + service *svc; + svc = find_service(cr->host_name, cr->service_description); + if (!svc) { + logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Got check result for service '%s' on host '%s'. Unable to find service\n", + cr->service_description, cr->host_name); + return ERROR; + } + log_debug_info(DEBUGL_CHECKS, 2, "Processing check result for service '%s' on host '%s'\n", + svc->description, svc->host_name); + svc->check_source = source_name; + return handle_async_service_check_result(svc, cr); + } + if (cr->object_check_type == HOST_CHECK) { + host *hst; + hst = find_host(cr->host_name); + if (!hst) { + logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Got host checkresult for '%s', but no such host can be found\n", cr->host_name); + return ERROR; + } + log_debug_info(DEBUGL_CHECKS, 2, "Processing check result for host '%s'\n", hst->name); + hst->check_source = source_name; + return handle_async_host_check_result(hst, cr); + } + + /* We should never end up here */ + logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Unknown object check type for checkresult: %d; (host_name: %s; service_description: %s)\n", + cr->object_check_type, + cr->host_name ? cr->host_name : "(null)", + cr->service_description ? cr->service_description : "(null)"); + + return ERROR; + } + +/* Unescapes newlines in a string. Declared here for now as it's not used + * elsewhere. */ +/* static char *unescape_check_result_file_output(char*); */ /* reads check result(s) from a file */ -int process_check_result_file(char *fname, check_result **listp, int delete_file, int need_output) { +int process_check_result_file(char *fname) { mmapfile *thefile = NULL; char *input = NULL; char *var = NULL; char *val = NULL; char *v1 = NULL, *v2 = NULL; time_t current_time; - check_result *new_cr = NULL; + check_result cr; if(fname == NULL) return ERROR; + init_check_result(&cr); + cr.engine = &nagios_spool_check_engine; + time(¤t_time); log_debug_info(DEBUGL_CHECKS, 1, "Processing check result file: '%s'\n", fname); @@ -2582,7 +2230,8 @@ int process_check_result_file(char *fname, check_result **listp, int delete_file if((thefile = mmap_fopen(fname)) == NULL) { /* try removing the file - zero length files can't be mmap()'ed, so it might exist */ - unlink(fname); + log_debug_info(DEBUGL_CHECKS, 1, "Failed to open check result file for reading: '%s'\n", fname); + delete_check_result_file(fname); return ERROR; } @@ -2604,27 +2253,18 @@ int process_check_result_file(char *fname, check_result **listp, int delete_file /* empty line indicates end of record */ else if(input[0] == '\n') { - /* we have something... */ - if(new_cr) { + /* do we have the minimum amount of data? */ + if(cr.host_name != NULL && cr.output != NULL) { - /* do we have the minimum amount of data? */ - if(new_cr->host_name != NULL && - (!need_output || new_cr->output != NULL)) { + /* process the check result */ + process_check_result(&cr); - /* add check result to list in memory */ - add_check_result_to_list(listp, new_cr); - - /* reset pointer */ - new_cr = NULL; - } - - /* discard partial input */ - else { - free_check_result(new_cr); - init_check_result(new_cr); - new_cr->output_file = (char *)strdup(fname); - } } + + /* cleanse for next check result */ + free_check_result(&cr); + init_check_result(&cr); + cr.output_file = fname; } if((var = my_strtok(input, "=")) == NULL) @@ -2638,97 +2278,79 @@ int process_check_result_file(char *fname, check_result **listp, int delete_file /* file is too old - ignore check results it contains and delete it */ /* this will only work as intended if file_time comes before check results */ if(max_check_result_file_age > 0 && (current_time - (strtoul(val, NULL, 0)) > max_check_result_file_age)) { - delete_file = TRUE; break; } } /* else we have check result data */ else { - - /* allocate new check result if necessary */ - if(new_cr == NULL) { - - if((new_cr = (check_result *)malloc(sizeof(check_result))) == NULL) - continue; - - /* init values */ - init_check_result(new_cr); - new_cr->output_file = (char *)strdup(fname); - } - if(!strcmp(var, "host_name")) - new_cr->host_name = (char *)strdup(val); + cr.host_name = (char *)strdup(val); else if(!strcmp(var, "service_description")) { - new_cr->service_description = (char *)strdup(val); - new_cr->object_check_type = SERVICE_CHECK; + cr.service_description = (char *)strdup(val); + cr.object_check_type = SERVICE_CHECK; } else if(!strcmp(var, "check_type")) - new_cr->check_type = atoi(val); + cr.check_type = atoi(val); else if(!strcmp(var, "check_options")) - new_cr->check_options = atoi(val); + cr.check_options = atoi(val); else if(!strcmp(var, "scheduled_check")) - new_cr->scheduled_check = atoi(val); + cr.scheduled_check = atoi(val); else if(!strcmp(var, "reschedule_check")) - new_cr->reschedule_check = atoi(val); + cr.reschedule_check = atoi(val); else if(!strcmp(var, "latency")) - new_cr->latency = strtod(val, NULL); + cr.latency = strtod(val, NULL); else if(!strcmp(var, "start_time")) { if((v1 = strtok(val, ".")) == NULL) continue; if((v2 = strtok(NULL, "\n")) == NULL) continue; - new_cr->start_time.tv_sec = strtoul(v1, NULL, 0); - new_cr->start_time.tv_usec = strtoul(v2, NULL, 0); + cr.start_time.tv_sec = strtoul(v1, NULL, 0); + cr.start_time.tv_usec = strtoul(v2, NULL, 0); } else if(!strcmp(var, "finish_time")) { if((v1 = strtok(val, ".")) == NULL) continue; if((v2 = strtok(NULL, "\n")) == NULL) continue; - new_cr->finish_time.tv_sec = strtoul(v1, NULL, 0); - new_cr->finish_time.tv_usec = strtoul(v2, NULL, 0); + cr.finish_time.tv_sec = strtoul(v1, NULL, 0); + cr.finish_time.tv_usec = strtoul(v2, NULL, 0); } else if(!strcmp(var, "early_timeout")) - new_cr->early_timeout = atoi(val); + cr.early_timeout = atoi(val); else if(!strcmp(var, "exited_ok")) - new_cr->exited_ok = atoi(val); + cr.exited_ok = atoi(val); else if(!strcmp(var, "return_code")) - new_cr->return_code = atoi(val); + cr.return_code = atoi(val); else if(!strcmp(var, "output")) - new_cr->output = (char *)strdup(val); + /* Interpolate "\\\\" and "\\n" escape sequences to the literal + * characters they represent. This converts from the single line + * format used to store the output in a checkresult file, to the + * newline delimited format we use internally. By converting as + * soon as possible after reading from the file we don't have + * to worry about two different representations later. */ + cr.output = unescape_check_result_output(val); } } - /* we have something */ - if(new_cr) { + /* do we have the minimum amount of data? */ + if(cr.host_name != NULL && cr.output != NULL) { - /* do we have the minimum amount of data? */ - if(new_cr->host_name != NULL && - (!need_output || new_cr->output != NULL)) { - - /* add check result to list in memory */ - add_check_result_to_list(listp, new_cr); - - /* reset pointer */ - new_cr = NULL; - } - - /* discard partial input */ - /* free memory for current check result record */ - else { - free_check_result(new_cr); - my_free(new_cr); - } - } + /* process check result */ + process_check_result(&cr); + } + else { + /* log a debug message */ + log_debug_info(DEBUGL_CHECKS, 1, "Minimum amount of data not present; Skipped check result file: '%s'\n", fname); + } + free_check_result(&cr); /* free memory and close file */ my_free(input); mmap_fclose(thefile); - /* delete the file (as well its ok-to-go file) if they exist */ - if(TRUE == delete_file) - delete_check_result_file(fname); + /* delete the file (as well its ok-to-go file) */ + delete_check_result_file(fname); return OK; } @@ -2754,21 +2376,6 @@ int delete_check_result_file(char *fname) { -/* reads the first host/service check result from the list in memory */ -check_result *read_check_result(check_result **listp) { - check_result *first_cr = NULL; - - if(*listp == NULL) - return NULL; - - first_cr = *listp; - *listp = (*listp)->next; - - return first_cr; - } - - - /* initializes a host/service check result */ int init_check_result(check_result *info) { @@ -2779,12 +2386,11 @@ int init_check_result(check_result *info) { info->object_check_type = HOST_CHECK; info->host_name = NULL; info->service_description = NULL; - info->check_type = HOST_CHECK_ACTIVE; + info->check_type = CHECK_TYPE_ACTIVE; info->check_options = CHECK_OPTION_NONE; info->scheduled_check = FALSE; info->reschedule_check = FALSE; info->output_file_fp = NULL; - info->output_file_fd = -1; info->latency = 0.0; info->start_time.tv_sec = 0; info->start_time.tv_usec = 0; @@ -2794,73 +2400,14 @@ int init_check_result(check_result *info) { info->exited_ok = TRUE; info->return_code = 0; info->output = NULL; - info->next = NULL; + info->source = NULL; + info->engine = NULL; return OK; } - -/* adds a new host/service check result to the list in memory */ -int add_check_result_to_list(check_result **listp, check_result *new_cr) { - check_result *temp_cr = NULL; - check_result *last_cr = NULL; - - if(new_cr == NULL) - return ERROR; - - /* add to list, sorted by finish time (asc) */ - - /* find insertion point */ - last_cr = *listp; - for(temp_cr = *listp; temp_cr != NULL; temp_cr = temp_cr->next) { - if(temp_cr->finish_time.tv_sec >= new_cr->finish_time.tv_sec) { - if(temp_cr->finish_time.tv_sec > new_cr->finish_time.tv_sec) - break; - else if(temp_cr->finish_time.tv_usec > new_cr->finish_time.tv_usec) - break; - } - last_cr = temp_cr; - } - - /* item goes at head of list */ - if(*listp == NULL || temp_cr == *listp) { - new_cr->next = *listp; - *listp = new_cr; - } - - /* item goes in middle or at end of list */ - else { - new_cr->next = temp_cr; - last_cr->next = new_cr; - } - - return OK; - } - - - - -/* frees all memory associated with the check result list */ -int free_check_result_list(check_result **listp) { - check_result *this_cr = NULL; - check_result *next_cr = NULL; - - for(this_cr = *listp; this_cr != NULL; this_cr = next_cr) { - next_cr = this_cr->next; - free_check_result(this_cr); - my_free(this_cr); - } - - *listp = NULL; - - return OK; - } - - - - /* frees memory associated with a host/service check result */ int free_check_result(check_result *info) { @@ -2869,101 +2416,12 @@ int free_check_result(check_result *info) { my_free(info->host_name); my_free(info->service_description); - my_free(info->output_file); my_free(info->output); return OK; } -/* creates external command file as a named pipe (FIFO) and opens it for reading (non-blocked mode) */ -int open_command_file(void) { - struct stat st; - int result = 0; - - /* if we're not checking external commands, don't do anything */ - if(check_external_commands == FALSE) - return OK; - - /* the command file was already created */ - if(command_file_created == TRUE) - return OK; - - /* reset umask (group needs write permissions) */ - umask(S_IWOTH); - - /* use existing FIFO if possible */ - if(!(stat(command_file, &st) != -1 && (st.st_mode & S_IFIFO))) { - - /* create the external command file as a named pipe (FIFO) */ - if((result = mkfifo(command_file, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP)) != 0) { - - logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Could not create external command file '%s' as named pipe: (%d) -> %s. If this file already exists and you are sure that another copy of Nagios is not running, you should delete this file.\n", command_file, errno, strerror(errno)); - return ERROR; - } - } - - /* open the command file for reading (non-blocked) - O_TRUNC flag cannot be used due to errors on some systems */ - /* NOTE: file must be opened read-write for poll() to work */ - if((command_file_fd = open(command_file, O_RDWR | O_NONBLOCK)) < 0) { - - logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Could not open external command file for reading via open(): (%d) -> %s\n", errno, strerror(errno)); - - return ERROR; - } - - /* re-open the FIFO for use with fgets() */ - if((command_file_fp = (FILE *)fdopen(command_file_fd, "r")) == NULL) { - - logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Could not open external command file for reading via fdopen(): (%d) -> %s\n", errno, strerror(errno)); - - return ERROR; - } - - /* initialize worker thread */ - if(init_command_file_worker_thread() == ERROR) { - - logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Could not initialize command file worker thread.\n"); - - /* close the command file */ - fclose(command_file_fp); - - /* delete the named pipe */ - unlink(command_file); - - return ERROR; - } - - /* set a flag to remember we already created the file */ - command_file_created = TRUE; - - return OK; - } - - -/* closes the external command file FIFO and deletes it */ -int close_command_file(void) { - - /* if we're not checking external commands, don't do anything */ - if(check_external_commands == FALSE) - return OK; - - /* the command file wasn't created or was already cleaned up */ - if(command_file_created == FALSE) - return OK; - - /* reset our flag */ - command_file_created = FALSE; - - /* close the command file */ - fclose(command_file_fp); - - return OK; - } - - - - /******************************************************************/ /************************ STRING FUNCTIONS ************************/ /******************************************************************/ @@ -2971,7 +2429,7 @@ int close_command_file(void) { /* gets the next string from a buffer in memory - strings are terminated by newlines, which are removed */ char *get_next_string_from_buf(char *buf, int *start_index, int bufsize) { char *sptr = NULL; - char *nl = "\n"; + const char *nl = "\n"; int x; if(buf == NULL || start_index == NULL) @@ -3001,17 +2459,13 @@ char *get_next_string_from_buf(char *buf, int *start_index, int bufsize) { int contains_illegal_object_chars(char *name) { register int x = 0; register int y = 0; - register int ch = 0; - if(name == NULL) + if(name == NULL || illegal_object_chars == NULL) return FALSE; x = (int)strlen(name) - 1; for(; x >= 0; x--) { - - ch = (int)name[x]; - /* illegal user-specified characters */ if(illegal_object_chars != NULL) for(y = 0; illegal_object_chars[y]; y++) @@ -3023,28 +2477,39 @@ int contains_illegal_object_chars(char *name) { } -/* escapes newlines in a string */ +/* Escapes newlines in a string. */ char *escape_newlines(char *rawbuf) { char *newbuf = NULL; - register int x, y; + int x; + int y; - if(rawbuf == NULL) + if (rawbuf == NULL) return NULL; - /* allocate enough memory to escape all chars if necessary */ - if((newbuf = malloc((strlen(rawbuf) * 2) + 1)) == NULL) + /* Count the escapes we need to make. */ + for (x = 0, y = 0; rawbuf[x]; x++) { + if (rawbuf[x] == '\\' || rawbuf[x] == '\n') + y++; + } + + /* Just duplicate the string if we have nothing to escape. */ + if (y == 0) + return strdup(rawbuf); + + /* Allocate memory for the new string with escapes. */ + if ((newbuf = malloc(x + y + 1)) == NULL) return NULL; - for(x = 0, y = 0; rawbuf[x] != (char)'\x0'; x++) { + for (x = 0, y = 0; rawbuf[x]; x++) { - /* escape backslashes */ - if(rawbuf[x] == '\\') { + /* Escape backslashes. */ + if (rawbuf[x] == '\\') { newbuf[y++] = '\\'; newbuf[y++] = '\\'; } - /* escape newlines */ - else if(rawbuf[x] == '\n') { + /* Escape newlines. */ + else if (rawbuf[x] == '\n') { newbuf[y++] = '\\'; newbuf[y++] = 'n'; } @@ -3052,7 +2517,52 @@ char *escape_newlines(char *rawbuf) { else newbuf[y++] = rawbuf[x]; } - newbuf[y] = '\x0'; + newbuf[y] = '\0'; + + return newbuf; + } + +/* Unescapes newlines (and backslashes) in a string. */ +char *unescape_check_result_output(const char *rawbuf) { + char *newbuf = NULL; + int x; + int y; + + if (rawbuf == NULL) + return NULL; + + /* Count the replacements we need to make. */ + for (x = 0, y = 0; rawbuf[x]; x++) { + if (rawbuf[x] == '\\' && (rawbuf[x + 1] == '\\' || rawbuf[x + 1] == 'n')) + x++, y++; /* Consume one more char for each replacement. */ + } + + /* Just duplicate the string if we have nothing to replace. */ + if (y == 0) + return strdup(rawbuf); + + /* Allocate memory for the new string, with our escape sequences replaced. */ + if ((newbuf = malloc(x - y + 1)) == NULL) + return NULL; + + for (x = 0, y = 0; rawbuf[x]; x++) { + + /* Unescape backslashes. */ + if (rawbuf[x] == '\\' && rawbuf[x + 1] == '\\') { + x++; + newbuf[y++] = '\\'; + } + + /* Unescape newlines. */ + else if (rawbuf[x] == '\\' && rawbuf[x + 1] == 'n') { + x++; + newbuf[y++] = '\n'; + } + + else + newbuf[y++] = rawbuf[x]; + } + newbuf[y] = '\0'; return newbuf; } @@ -3118,7 +2628,7 @@ int my_rename(char *source, char *dest) { */ int my_fdcopy(char *source, char *dest, int dest_fd) { int source_fd, rd_result = 0, wr_result = 0; - unsigned long tot_written = 0, tot_read = 0, buf_size = 0; + int tot_written = 0, tot_read = 0, buf_size = 0; struct stat st; char *buf; @@ -3150,7 +2660,7 @@ int my_fdcopy(char *source, char *dest, int dest_fd) { buf_size = st.st_size > 128 << 10 ? 128 << 10 : st.st_size; buf = malloc(buf_size); if(!buf) { - logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Unable to malloc(%lu) bytes: %s\n", buf_size, strerror(errno)); + logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Unable to malloc(%d) bytes: %s\n", buf_size, strerror(errno)); close(source_fd); return ERROR; } @@ -3257,7 +2767,7 @@ int dbuf_free(dbuf *db) { /* dynamically expands a string */ -int dbuf_strcat(dbuf *db, char *buf) { +int dbuf_strcat(dbuf *db, const char *buf) { char *newbuf = NULL; unsigned long buflen = 0L; unsigned long new_size = 0L; @@ -3299,421 +2809,6 @@ int dbuf_strcat(dbuf *db, char *buf) { } - -/******************************************************************/ -/******************** EMBEDDED PERL FUNCTIONS *********************/ -/******************************************************************/ - -/* initializes embedded perl interpreter */ -int init_embedded_perl(char **env) { -#ifdef EMBEDDEDPERL - char **embedding; - int exitstatus = 0; - int argc = 2; - struct stat stat_buf; - - /* make sure the P1 file exists... */ - if(p1_file == NULL || stat(p1_file, &stat_buf) != 0) { - - use_embedded_perl = FALSE; - - logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: p1.pl file required for embedded Perl interpreter is missing!\n"); - } - - else { - - embedding = malloc(2 * sizeof(char *)); - if(embedding == NULL) - return ERROR; - *embedding = strdup(""); - *(embedding + 1) = strdup(p1_file); - - use_embedded_perl = TRUE; - - PERL_SYS_INIT3(&argc, &embedding, &env); - - if((my_perl = perl_alloc()) == NULL) { - use_embedded_perl = FALSE; - logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Could not allocate memory for embedded Perl interpreter!\n"); - } - } - - /* a fatal error occurred... */ - if(use_embedded_perl == FALSE) { - - logit(NSLOG_PROCESS_INFO | NSLOG_RUNTIME_ERROR, TRUE, "Bailing out due to errors encountered while initializing the embedded Perl interpreter. (PID=%d)\n", (int)getpid()); - - cleanup(); - exit(ERROR); - } - - perl_construct(my_perl); - exitstatus = perl_parse(my_perl, xs_init, 2, (char **)embedding, env); - if(!exitstatus) - exitstatus = perl_run(my_perl); - -#endif - return OK; - } - - -/* closes embedded perl interpreter */ -int deinit_embedded_perl(void) { -#ifdef EMBEDDEDPERL - - PL_perl_destruct_level = 0; - perl_destruct(my_perl); - perl_free(my_perl); - PERL_SYS_TERM(); - -#endif - return OK; - } - - -/* checks to see if we should run a script using the embedded Perl interpreter */ -int file_uses_embedded_perl(char *fname) { -#ifndef EMBEDDEDPERL - return FALSE; -#else - int line, use_epn = FALSE; - FILE *fp = NULL; - char buf[256] = ""; - - if(enable_embedded_perl != TRUE) - return FALSE; - - /* open the file, check if its a Perl script and see if we can use epn */ - fp = fopen(fname, "r"); - if(fp == NULL) - return FALSE; - - /* grab the first line - we should see Perl. go home if not */ - if(fgets(buf, 80, fp) == NULL || strstr(buf, "/bin/perl") == NULL) { - fclose(fp); - return FALSE; - } - - /* epn directives must be found in first ten lines of plugin */ - for(line = 1; line < 10; line++) { - if(fgets(buf, sizeof(buf) - 1, fp) == NULL) - break; - - buf[sizeof(buf) - 1] = '\0'; - - /* skip lines not containing nagios 'epn' directives */ - if(strstr(buf, "# nagios:")) { - char *p; - p = strstr(buf + 8, "epn"); - if(!p) - continue; - - /* - * we found it, so close the file and return - * whatever it shows. '+epn' means yes. everything - * else means no - */ - fclose(fp); - return *(p - 1) == '+' ? TRUE : FALSE; - } - } - - fclose(fp); - - return use_embedded_perl_implicitly; -#endif - } - - - - - -/******************************************************************/ -/************************ THREAD FUNCTIONS ************************/ -/******************************************************************/ - -/* initializes command file worker thread */ -int init_command_file_worker_thread(void) { - int result = 0; - sigset_t newmask; - - /* initialize circular buffer */ - external_command_buffer.head = 0; - external_command_buffer.tail = 0; - external_command_buffer.items = 0; - external_command_buffer.high = 0; - external_command_buffer.overflow = 0L; - external_command_buffer.buffer = (void **)malloc(external_command_buffer_slots * sizeof(char **)); - if(external_command_buffer.buffer == NULL) - return ERROR; - - /* initialize mutex (only on cold startup) */ - if(sigrestart == FALSE) - pthread_mutex_init(&external_command_buffer.buffer_lock, NULL); - - /* new thread should block all signals */ - sigfillset(&newmask); - pthread_sigmask(SIG_BLOCK, &newmask, NULL); - - /* create worker thread */ - result = pthread_create(&worker_threads[COMMAND_WORKER_THREAD], NULL, command_file_worker_thread, NULL); - - /* main thread should unblock all signals */ - pthread_sigmask(SIG_UNBLOCK, &newmask, NULL); - - if(result) - return ERROR; - - return OK; - } - - -/* shutdown command file worker thread */ -int shutdown_command_file_worker_thread(void) { - int result = 0; - - /* - * calling pthread_cancel(0) will cause segfaults with some - * thread libraries. It's possible that will happen if the - * user has a number of config files larger than the max - * open file descriptor limit (ulimit -n) and some retarded - * eventbroker module leaks filedescriptors, since we'll then - * enter the cleanup() routine from main() before we've - * spawned any threads. - */ - if(worker_threads[COMMAND_WORKER_THREAD]) { - /* tell the worker thread to exit */ - result = pthread_cancel(worker_threads[COMMAND_WORKER_THREAD]); - - /* wait for the worker thread to exit */ - if(result == 0) { - result = pthread_join(worker_threads[COMMAND_WORKER_THREAD], NULL); - } - - /* we're being called from a fork()'ed child process - can't cancel thread, so just cleanup memory */ - else { - cleanup_command_file_worker_thread(NULL); - } - } - - return OK; - } - - -/* clean up resources used by command file worker thread */ -void cleanup_command_file_worker_thread(void *arg) { - register int x = 0; - - /* release memory allocated to circular buffer */ - for(x = external_command_buffer.tail; x != external_command_buffer.head; x = (x + 1) % external_command_buffer_slots) { - my_free(((char **)external_command_buffer.buffer)[x]); - } - my_free(external_command_buffer.buffer); - - return; - } - - - -/* worker thread - artificially increases buffer of named pipe */ -void * command_file_worker_thread(void *arg) { - char input_buffer[MAX_EXTERNAL_COMMAND_LENGTH]; - struct pollfd pfd; - int pollval; - struct timeval tv; - int buffer_items = 0; - int result = 0; - - /* specify cleanup routine */ - pthread_cleanup_push(cleanup_command_file_worker_thread, NULL); - - /* set cancellation info */ - pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); - pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL); - - while(1) { - - /* should we shutdown? */ - pthread_testcancel(); - - /* wait for data to arrive */ - /* select seems to not work, so we have to use poll instead */ - /* 10-15-08 EG check into implementing William's patch @ http://blog.netways.de/2008/08/15/nagios-unter-mac-os-x-installieren/ */ - /* 10-15-08 EG poll() seems broken on OSX - see Jonathan's patch a few lines down */ - pfd.fd = command_file_fd; - pfd.events = POLLIN; - pollval = poll(&pfd, 1, 500); - - /* loop if no data */ - if(pollval == 0) - continue; - - /* check for errors */ - if(pollval == -1) { - - switch(errno) { - case EBADF: - write_to_log("command_file_worker_thread(): poll(): EBADF", logging_options, NULL); - break; - case ENOMEM: - write_to_log("command_file_worker_thread(): poll(): ENOMEM", logging_options, NULL); - break; - case EFAULT: - write_to_log("command_file_worker_thread(): poll(): EFAULT", logging_options, NULL); - break; - case EINTR: - /* this can happen when running under a debugger like gdb */ - /* - write_to_log("command_file_worker_thread(): poll(): EINTR (impossible)",logging_options,NULL); - */ - break; - default: - write_to_log("command_file_worker_thread(): poll(): Unknown errno value.", logging_options, NULL); - break; - } - - continue; - } - - /* should we shutdown? */ - pthread_testcancel(); - - /* get number of items in the buffer */ - pthread_mutex_lock(&external_command_buffer.buffer_lock); - buffer_items = external_command_buffer.items; - pthread_mutex_unlock(&external_command_buffer.buffer_lock); - -#ifdef DEBUG_CFWT - printf("(CFWT) BUFFER ITEMS: %d/%d\n", buffer_items, external_command_buffer_slots); -#endif - - /* 10-15-08 Fix for OS X by Jonathan Saggau - see http://www.jonathansaggau.com/blog/2008/09/using_shark_and_custom_dtrace.html */ - /* Not sure if this would have negative effects on other OSes... */ - if(buffer_items == 0) { - /* pause a bit so OS X doesn't go nuts with CPU overload */ - tv.tv_sec = 0; - tv.tv_usec = 500; - select(0, NULL, NULL, NULL, &tv); - } - - /* process all commands in the file (named pipe) if there's some space in the buffer */ - if(buffer_items < external_command_buffer_slots) { - - /* clear EOF condition from prior run (FreeBSD fix) */ - /* FIXME: use_poll_on_cmd_pipe: Still needed? */ - clearerr(command_file_fp); - - /* read and process the next command in the file */ - while(fgets(input_buffer, (int)(sizeof(input_buffer) - 1), command_file_fp) != NULL) { - -#ifdef DEBUG_CFWT - printf("(CFWT) READ: %s", input_buffer); -#endif - - /* submit the external command for processing (retry if buffer is full) */ - while((result = submit_external_command(input_buffer, &buffer_items)) == ERROR && buffer_items == external_command_buffer_slots) { - - /* wait a bit */ - tv.tv_sec = 0; - tv.tv_usec = 250000; - select(0, NULL, NULL, NULL, &tv); - - /* should we shutdown? */ - pthread_testcancel(); - } - -#ifdef DEBUG_CFWT - printf("(CFWT) RES: %d, BUFFER_ITEMS: %d/%d\n", result, buffer_items, external_comand_buffer_slots); -#endif - - /* bail if the circular buffer is full */ - if(buffer_items == external_command_buffer_slots) - break; - - /* should we shutdown? */ - pthread_testcancel(); - } - } - } - - /* removes cleanup handler - this should never be reached */ - pthread_cleanup_pop(0); - - return NULL; - } - - - -/* submits an external command for processing */ -int submit_external_command(char *cmd, int *buffer_items) { - int result = OK; - - if(cmd == NULL || external_command_buffer.buffer == NULL) { - if(buffer_items != NULL) - *buffer_items = -1; - return ERROR; - } - - /* obtain a lock for writing to the buffer */ - pthread_mutex_lock(&external_command_buffer.buffer_lock); - - if(external_command_buffer.items < external_command_buffer_slots) { - - /* save the line in the buffer */ - ((char **)external_command_buffer.buffer)[external_command_buffer.head] = (char *)strdup(cmd); - - /* increment the head counter and items */ - external_command_buffer.head = (external_command_buffer.head + 1) % external_command_buffer_slots; - external_command_buffer.items++; - if(external_command_buffer.items > external_command_buffer.high) - external_command_buffer.high = external_command_buffer.items; - } - - /* buffer was full */ - else - result = ERROR; - - /* return number of items now in buffer */ - if(buffer_items != NULL) - *buffer_items = external_command_buffer.items; - - /* release lock on buffer */ - pthread_mutex_unlock(&external_command_buffer.buffer_lock); - - return result; - } - - - -/* submits a raw external command (without timestamp) for processing */ -int submit_raw_external_command(char *cmd, time_t *ts, int *buffer_items) { - char *newcmd = NULL; - int result = OK; - time_t timestamp; - - if(cmd == NULL) - return ERROR; - - /* get the time */ - if(ts != NULL) - timestamp = *ts; - else - time(×tamp); - - /* create the command string */ - asprintf(&newcmd, "[%lu] %s", (unsigned long)timestamp, cmd); - - /* submit the command */ - result = submit_external_command(newcmd, buffer_items); - - /* free allocated memory */ - my_free(newcmd); - - return result; - } - - - /******************************************************************/ /********************** CHECK STATS FUNCTIONS *********************/ /******************************************************************/ @@ -3768,7 +2863,7 @@ int update_check_stats(int check_type, time_t check_time) { check_statistics[check_type].bucket[x] = 0; check_statistics[check_type].overflow_bucket = 0; #ifdef DEBUG_CHECK_STATS - printf("CLEARING ALL: TYPE[%d], CURRENT=%lu, LASTUPDATE=%lu\n", check_type, (unsigned long)current_time, (unsigned long)check_statistics[check_type].last_update); + printf("CLEARING ALL: TYPE[%d], CURRENT=%llu, LASTUPDATE=%llu\n", check_type, (unsigned long long)current_time, (unsigned long long)check_statistics[check_type].last_update); #endif } @@ -3835,9 +2930,6 @@ int generate_check_stats(void) { int check_type = 0; float this_bucket_weight = 0.0; float last_bucket_weight = 0.0; - int left_value = 0; - int right_value = 0; - time(¤t_time); @@ -3853,7 +2945,7 @@ int generate_check_stats(void) { check_statistics[check_type].bucket[x] = 0; check_statistics[check_type].overflow_bucket = 0; #ifdef DEBUG_CHECK_STATS - printf("GEN CLEARING ALL: TYPE[%d], CURRENT=%lu, LASTUPDATE=%lu\n", check_type, (unsigned long)current_time, (unsigned long)check_statistics[check_type].last_update); + printf("GEN CLEARING ALL: TYPE[%d], CURRENT=%llu, LASTUPDATE=%llu\n", check_type, (unsigned long long)current_time, (unsigned long long)check_statistics[check_type].last_update); #endif } @@ -3869,7 +2961,7 @@ int generate_check_stats(void) { break; #ifdef DEBUG_CHECK_STATS - printf("GEN CLEARING BUCKET %d, (NEW=%d, OLD=%d), CURRENT=%lu, LASTUPDATE=%lu\n", this_bucket, new_current_bucket, check_statistics[check_type].current_bucket, (unsigned long)current_time, (unsigned long)check_statistics[check_type].last_update); + printf("GEN CLEARING BUCKET %d, (NEW=%d, OLD=%d), CURRENT=%llu, LASTUPDATE=%llu\n", this_bucket, new_current_bucket, check_statistics[check_type].current_bucket, (unsigned long long)current_time, (unsigned long long)check_statistics[check_type].last_update); #endif /* clear old bucket value */ @@ -3883,7 +2975,7 @@ int generate_check_stats(void) { } #ifdef DEBUG_CHECK_STATS else - printf("GEN NO CLEARING NEEDED: TYPE[%d], CURRENT=%lu, LASTUPDATE=%lu\n", check_type, (unsigned long)current_time, (unsigned long)check_statistics[check_type].last_update); + printf("GEN NO CLEARING NEEDED: TYPE[%d], CURRENT=%llu, LASTUPDATE=%llu\n", check_type, (unsigned long long)current_time, (unsigned long long)check_statistics[check_type].last_update); #endif /* update last check time */ @@ -3921,14 +3013,10 @@ int generate_check_stats(void) { /* determine value by weighting this/last buckets... */ /* if this is the current bucket, use its full value + weighted % of last bucket */ if(x == 0) { - right_value = this_bucket_value; - left_value = (int)floor(last_bucket_value * last_bucket_weight); bucket_value = (int)(this_bucket_value + floor(last_bucket_value * last_bucket_weight)); } /* otherwise use weighted % of this and last bucket */ else { - right_value = (int)ceil(this_bucket_value * this_bucket_weight); - left_value = (int)floor(last_bucket_value * last_bucket_weight); bucket_value = (int)(ceil(this_bucket_value * this_bucket_weight) + floor(last_bucket_value * last_bucket_weight)); } @@ -3992,7 +3080,7 @@ int check_for_nagios_updates(int force, int reschedule) { if(update_uid == 0L) update_uid = current_time; - /* update chekcs are disabled */ + /* update checks are disabled */ if(check_for_updates == FALSE) do_check = FALSE; /* we checked for updates recently, so don't do it again */ @@ -4065,14 +3153,13 @@ int check_for_nagios_updates(int force, int reschedule) { /* checks for updates at api.nagios.org */ int query_update_api(void) { - char *api_server = "api.nagios.org"; - char *api_path = "/versioncheck/"; + const char *api_server = "api.nagios.org"; + const char *api_path = "/versioncheck/"; char *api_query = NULL; char *api_query_opts = NULL; char *buf = NULL; char recv_buf[1024]; int report_install = FALSE; - int result = OK; char *ptr = NULL; int current_line = 0; int buf_index = 0; @@ -4114,40 +3201,24 @@ int query_update_api(void) { "POST %s HTTP/1.0\r\nUser-Agent: Nagios/%s\r\n" "Connection: close\r\nHost: %s\r\n" "Content-Type: application/x-www-form-urlencoded\r\n" - "Content-Length: %zd\r\n\r\n%s", + "Content-Length: %lu\r\n\r\n%s", api_path, PROGRAM_VERSION, api_server, - strlen(api_query), api_query); + (unsigned long) strlen(api_query), api_query); - /* - printf("SENDING...\n"); - printf("==========\n"); - printf("%s",buf); - printf("\n"); - */ + if (buf == NULL) { + abort(); + } - - result = my_tcp_connect(api_server, 80, &sd, 2); - /*printf("CONN RESULT: %d, SD: %d\n",result,sd);*/ + my_tcp_connect(api_server, 80, &sd, 2); if(sd > 0) { - /* send request */ send_len = strlen(buf); - result = my_sendall(sd, buf, &send_len, 2); - /*printf("SEND RESULT: %d, SENT: %d\n",result,send_len);*/ + my_sendall(sd, buf, &send_len, 2); /* get response */ recv_len = sizeof(recv_buf); - result = my_recvall(sd, recv_buf, &recv_len, 2); + my_recvall(sd, recv_buf, &recv_len, 2); recv_buf[sizeof(recv_buf) - 1] = '\x0'; - /*printf("RECV RESULT: %d, RECEIVED: %d\n",result,recv_len);*/ - - /* - printf("\n"); - printf("RECEIVED...\n"); - printf("===========\n"); - printf("%s",recv_buf); - printf("\n"); - */ /* close connection */ close(sd); @@ -4168,7 +3239,6 @@ int query_update_api(void) { var = strtok(ptr, "="); val = strtok(NULL, "\n"); - /*printf("VAR: %s, VAL: %s\n",var,val);*/ if(!strcmp(var, "UPDATE_AVAILABLE")) { update_available = atoi(val); @@ -4243,6 +3313,7 @@ void cleanup(void) { /* free all allocated memory - including macros */ free_memory(get_global_macros()); + close_log_file(); return; } @@ -4250,8 +3321,7 @@ void cleanup(void) { /* free the memory allocated to the linked lists */ void free_memory(nagios_macros *mac) { - timed_event *this_event = NULL; - timed_event *next_event = NULL; + int i; /* free all allocated memory for the object definitions */ free_object_data(); @@ -4259,34 +3329,9 @@ void free_memory(nagios_macros *mac) { /* free memory allocated to comments */ free_comment_data(); - /* free check result list */ - free_check_result_list(&check_result_list); - - /* free memory for the high priority event list */ - this_event = event_list_high; - while(this_event != NULL) { - if(this_event->event_type == EVENT_SCHEDULED_DOWNTIME) - my_free(this_event->event_data); - next_event = this_event->next; - my_free(this_event); - this_event = next_event; - } - - /* reset the event pointer */ - event_list_high = NULL; - - /* free memory for the low priority event list */ - this_event = event_list_low; - while(this_event != NULL) { - if(this_event->event_type == EVENT_SCHEDULED_DOWNTIME) - my_free(this_event->event_data); - next_event = this_event->next; - my_free(this_event); - this_event = next_event; - } - - /* reset the event pointer */ - event_list_low = NULL; + /* free event queue data */ + squeue_destroy(nagios_squeue, SQUEUE_FREE_DATA); + nagios_squeue = NULL; /* free memory for global event handlers */ my_free(global_host_event_handler); @@ -4299,6 +3344,9 @@ void free_memory(nagios_macros *mac) { my_free(ocsp_command); my_free(ochp_command); + my_free(object_cache_file); + my_free(object_precache_file); + /* * free memory associated with macros. * It's ok to only free the volatile ones, as the non-volatile @@ -4324,17 +3372,29 @@ void free_memory(nagios_macros *mac) { my_free(new_program_version); /* free file/path variables */ - my_free(log_file); my_free(debug_file); + my_free(log_file); + mac->x[MACRO_LOGFILE] = NULL; /* assigned from 'log_file' */ my_free(temp_file); + mac->x[MACRO_TEMPFILE] = NULL; /* assigned from temp_file */ my_free(temp_path); + mac->x[MACRO_TEMPPATH] = NULL; /*assigned from temp_path */ my_free(check_result_path); my_free(command_file); - my_free(lock_file); - my_free(auth_file); - my_free(p1_file); + mac->x[MACRO_COMMANDFILE] = NULL; /* assigned from command_file */ my_free(log_archive_path); + for (i = 0; i < MAX_USER_MACROS; i++) { + my_free(macro_user[i]); + } + + /* these have no other reference */ + my_free(mac->x[MACRO_ADMINEMAIL]); + my_free(mac->x[MACRO_ADMINPAGER]); + my_free(mac->x[MACRO_RESOURCEFILE]); + my_free(mac->x[MACRO_OBJECTCACHEFILE]); + my_free(mac->x[MACRO_MAINCONFIGFILE]); + return; } @@ -4361,160 +3421,72 @@ void free_notification_list(void) { /* reset all system-wide variables, so when we've receive a SIGHUP we can restart cleanly */ int reset_variables(void) { + /* First free any variables previously set */ + my_free(log_file); + my_free(temp_file); + my_free(temp_path); + my_free(check_result_path); + my_free(command_file); + my_free(lock_file); + my_free(log_archive_path); + my_free(debug_file); + + my_free(object_cache_file); + my_free(object_precache_file); + + my_free(nagios_user); + my_free(nagios_group); + + my_free(global_host_event_handler); + my_free(global_service_event_handler); + + my_free(ocsp_command); + my_free(ochp_command); + + /* Next re-initialize configuration variables */ + init_main_cfg_vars(0); + init_shared_cfg_vars(0); + + /* Finally, set anything not set in the initialization routines */ log_file = (char *)strdup(DEFAULT_LOG_FILE); temp_file = (char *)strdup(DEFAULT_TEMP_FILE); temp_path = (char *)strdup(DEFAULT_TEMP_PATH); check_result_path = (char *)strdup(DEFAULT_CHECK_RESULT_PATH); command_file = (char *)strdup(DEFAULT_COMMAND_FILE); - lock_file = (char *)strdup(DEFAULT_LOCK_FILE); - auth_file = (char *)strdup(DEFAULT_AUTH_FILE); - p1_file = (char *)strdup(DEFAULT_P1_FILE); + lock_file = (char *)strdup(DEFAULT_LOCK_FILE); /* this is kept across restarts */ log_archive_path = (char *)strdup(DEFAULT_LOG_ARCHIVE_PATH); debug_file = (char *)strdup(DEFAULT_DEBUG_FILE); + /* init_main_cfg_vars(0) sets object_precache_file = strdup(DEFAULT_PRECACHED_OBJECT_FILE); */ + nagios_user = (char *)strdup(DEFAULT_NAGIOS_USER); nagios_group = (char *)strdup(DEFAULT_NAGIOS_GROUP); - use_regexp_matches = FALSE; - use_true_regexp_matching = FALSE; - - use_syslog = DEFAULT_USE_SYSLOG; - log_service_retries = DEFAULT_LOG_SERVICE_RETRIES; - log_host_retries = DEFAULT_LOG_HOST_RETRIES; - log_initial_states = DEFAULT_LOG_INITIAL_STATES; - - log_notifications = DEFAULT_NOTIFICATION_LOGGING; - log_event_handlers = DEFAULT_LOG_EVENT_HANDLERS; - log_external_commands = DEFAULT_LOG_EXTERNAL_COMMANDS; - log_passive_checks = DEFAULT_LOG_PASSIVE_CHECKS; - logging_options = NSLOG_RUNTIME_ERROR | NSLOG_RUNTIME_WARNING | NSLOG_VERIFICATION_ERROR | NSLOG_VERIFICATION_WARNING | NSLOG_CONFIG_ERROR | NSLOG_CONFIG_WARNING | NSLOG_PROCESS_INFO | NSLOG_HOST_NOTIFICATION | NSLOG_SERVICE_NOTIFICATION | NSLOG_EVENT_HANDLER | NSLOG_EXTERNAL_COMMAND | NSLOG_PASSIVE_CHECK | NSLOG_HOST_UP | NSLOG_HOST_DOWN | NSLOG_HOST_UNREACHABLE | NSLOG_SERVICE_OK | NSLOG_SERVICE_WARNING | NSLOG_SERVICE_UNKNOWN | NSLOG_SERVICE_CRITICAL | NSLOG_INFO_MESSAGE; syslog_options = NSLOG_RUNTIME_ERROR | NSLOG_RUNTIME_WARNING | NSLOG_VERIFICATION_ERROR | NSLOG_VERIFICATION_WARNING | NSLOG_CONFIG_ERROR | NSLOG_CONFIG_WARNING | NSLOG_PROCESS_INFO | NSLOG_HOST_NOTIFICATION | NSLOG_SERVICE_NOTIFICATION | NSLOG_EVENT_HANDLER | NSLOG_EXTERNAL_COMMAND | NSLOG_PASSIVE_CHECK | NSLOG_HOST_UP | NSLOG_HOST_DOWN | NSLOG_HOST_UNREACHABLE | NSLOG_SERVICE_OK | NSLOG_SERVICE_WARNING | NSLOG_SERVICE_UNKNOWN | NSLOG_SERVICE_CRITICAL | NSLOG_INFO_MESSAGE; - service_check_timeout = DEFAULT_SERVICE_CHECK_TIMEOUT; - host_check_timeout = DEFAULT_HOST_CHECK_TIMEOUT; - event_handler_timeout = DEFAULT_EVENT_HANDLER_TIMEOUT; - notification_timeout = DEFAULT_NOTIFICATION_TIMEOUT; - ocsp_timeout = DEFAULT_OCSP_TIMEOUT; - ochp_timeout = DEFAULT_OCHP_TIMEOUT; - - sleep_time = DEFAULT_SLEEP_TIME; - interval_length = DEFAULT_INTERVAL_LENGTH; - service_inter_check_delay_method = ICD_SMART; - host_inter_check_delay_method = ICD_SMART; - service_interleave_factor_method = ILF_SMART; - max_service_check_spread = DEFAULT_SERVICE_CHECK_SPREAD; - max_host_check_spread = DEFAULT_HOST_CHECK_SPREAD; - - use_aggressive_host_checking = DEFAULT_AGGRESSIVE_HOST_CHECKING; - cached_host_check_horizon = DEFAULT_CACHED_HOST_CHECK_HORIZON; - cached_service_check_horizon = DEFAULT_CACHED_SERVICE_CHECK_HORIZON; - enable_predictive_host_dependency_checks = DEFAULT_ENABLE_PREDICTIVE_HOST_DEPENDENCY_CHECKS; - enable_predictive_service_dependency_checks = DEFAULT_ENABLE_PREDICTIVE_SERVICE_DEPENDENCY_CHECKS; - - soft_state_dependencies = FALSE; - - retain_state_information = FALSE; - retention_update_interval = DEFAULT_RETENTION_UPDATE_INTERVAL; - use_retained_program_state = TRUE; - use_retained_scheduling_info = FALSE; - retention_scheduling_horizon = DEFAULT_RETENTION_SCHEDULING_HORIZON; modified_host_process_attributes = MODATTR_NONE; modified_service_process_attributes = MODATTR_NONE; - retained_host_attribute_mask = 0L; - retained_service_attribute_mask = 0L; - retained_process_host_attribute_mask = 0L; - retained_process_service_attribute_mask = 0L; - retained_contact_host_attribute_mask = 0L; - retained_contact_service_attribute_mask = 0L; - command_check_interval = DEFAULT_COMMAND_CHECK_INTERVAL; - check_reaper_interval = DEFAULT_CHECK_REAPER_INTERVAL; - max_check_reaper_time = DEFAULT_MAX_REAPER_TIME; - max_check_result_file_age = DEFAULT_MAX_CHECK_RESULT_AGE; - service_freshness_check_interval = DEFAULT_FRESHNESS_CHECK_INTERVAL; - host_freshness_check_interval = DEFAULT_FRESHNESS_CHECK_INTERVAL; - auto_rescheduling_interval = DEFAULT_AUTO_RESCHEDULING_INTERVAL; - auto_rescheduling_window = DEFAULT_AUTO_RESCHEDULING_WINDOW; - - check_external_commands = DEFAULT_CHECK_EXTERNAL_COMMANDS; - check_orphaned_services = DEFAULT_CHECK_ORPHANED_SERVICES; - check_orphaned_hosts = DEFAULT_CHECK_ORPHANED_HOSTS; - check_service_freshness = DEFAULT_CHECK_SERVICE_FRESHNESS; - check_host_freshness = DEFAULT_CHECK_HOST_FRESHNESS; - auto_reschedule_checks = DEFAULT_AUTO_RESCHEDULE_CHECKS; - - log_rotation_method = LOG_ROTATION_NONE; - - last_command_check = 0L; - last_command_status_update = 0L; last_log_rotation = 0L; - max_parallel_service_checks = DEFAULT_MAX_PARALLEL_SERVICE_CHECKS; currently_running_service_checks = 0; - enable_notifications = TRUE; - execute_service_checks = TRUE; - accept_passive_service_checks = TRUE; - execute_host_checks = TRUE; - accept_passive_service_checks = TRUE; - enable_event_handlers = TRUE; - obsess_over_services = FALSE; - obsess_over_hosts = FALSE; - enable_failure_prediction = TRUE; - next_comment_id = 0L; /* comment and downtime id get initialized to nonzero elsewhere */ next_downtime_id = 0L; next_event_id = 1; next_notification_id = 1; - aggregate_status_updates = TRUE; - status_update_interval = DEFAULT_STATUS_UPDATE_INTERVAL; - - event_broker_options = BROKER_NOTHING; - - time_change_threshold = DEFAULT_TIME_CHANGE_THRESHOLD; - - enable_flap_detection = DEFAULT_ENABLE_FLAP_DETECTION; - low_service_flap_threshold = DEFAULT_LOW_SERVICE_FLAP_THRESHOLD; - high_service_flap_threshold = DEFAULT_HIGH_SERVICE_FLAP_THRESHOLD; - low_host_flap_threshold = DEFAULT_LOW_HOST_FLAP_THRESHOLD; - high_host_flap_threshold = DEFAULT_HIGH_HOST_FLAP_THRESHOLD; - - process_performance_data = DEFAULT_PROCESS_PERFORMANCE_DATA; - - translate_passive_host_checks = DEFAULT_TRANSLATE_PASSIVE_HOST_CHECKS; - passive_host_checks_are_soft = DEFAULT_PASSIVE_HOST_CHECKS_SOFT; - - use_large_installation_tweaks = DEFAULT_USE_LARGE_INSTALLATION_TWEAKS; - enable_environment_macros = FALSE; free_child_process_memory = FALSE; child_processes_fork_twice = FALSE; - additional_freshness_latency = DEFAULT_ADDITIONAL_FRESHNESS_LATENCY; - - enable_embedded_perl = DEFAULT_ENABLE_EMBEDDED_PERL; - use_embedded_perl_implicitly = DEFAULT_USE_EMBEDDED_PERL_IMPLICITLY; - - external_command_buffer_slots = DEFAULT_EXTERNAL_COMMAND_BUFFER_SLOTS; - - debug_level = DEFAULT_DEBUG_LEVEL; - debug_verbosity = DEFAULT_DEBUG_VERBOSITY; - max_debug_file_size = DEFAULT_MAX_DEBUG_FILE_SIZE; - - date_format = DATE_FORMAT_US; - /* initialize macros */ init_macros(); - global_host_event_handler = NULL; - global_service_event_handler = NULL; global_host_event_handler_ptr = NULL; global_service_event_handler_ptr = NULL; - ocsp_command = NULL; - ochp_command = NULL; ocsp_command_ptr = NULL; ochp_command_ptr = NULL; @@ -4523,4 +3495,3 @@ int reset_variables(void) { return OK; } - diff --git a/base/workers.c b/base/workers.c new file mode 100644 index 0000000..1e78fd0 --- /dev/null +++ b/base/workers.c @@ -0,0 +1,1162 @@ +/* + * This file holds all nagios<->libnagios integration stuff, so that + * libnagios itself is usable as a standalone library for addon + * writers to use as they see fit. + * + * This means apis inside libnagios can be tested without compiling + * all of Nagios into it, and that they can remain general-purpose + * code that can be reused for other things later. + */ +#include "../include/config.h" +#include +#include "../include/nagios.h" +#include "../include/workers.h" + +/* perfect hash function for wproc response codes */ +#include "wpres-phash.h" + +struct wproc_worker; + +struct wproc_job { + unsigned int id; + unsigned int type; + unsigned int timeout; + char *command; + void *arg; + struct wproc_worker *wp; +}; + +struct wproc_list; + +struct wproc_worker { + char *name; /**< check-source name of this worker */ + int sd; /**< communication socket */ + pid_t pid; /**< pid */ + int max_jobs; /**< Max number of jobs the worker can handle */ + int jobs_running; /**< jobs running */ + int jobs_started; /**< jobs started */ + int job_index; /**< round-robin slot allocator (this wraps) */ + iocache *ioc; /**< iocache for reading from worker */ + fanout_table *jobs; /**< array of jobs */ + struct wproc_list *wp_list; +}; + +struct wproc_list { + unsigned int len; + unsigned int idx; + struct wproc_worker **wps; +}; + +static struct wproc_list workers = {0, 0, NULL}; + +static dkhash_table *specialized_workers; +static struct wproc_list *to_remove = NULL; + +typedef struct wproc_callback_job { + void *data; + void (*callback)(struct wproc_result *, void *, int); +} wproc_callback_job; + +typedef struct wproc_object_job { + char *contact_name; + char *host_name; + char *service_description; +} wproc_object_job; + +unsigned int wproc_num_workers_online = 0, wproc_num_workers_desired = 0; +unsigned int wproc_num_workers_spawned = 0; + +extern struct kvvec * macros_to_kvv(nagios_macros *); + +#define tv2float(tv) ((float)((tv)->tv_sec) + ((float)(tv)->tv_usec) / 1000000.0) + +static const char *wpjob_type_name(unsigned int type) +{ + switch (type) { + case WPJOB_CHECK: return "CHECK"; + case WPJOB_NOTIFY: return "NOTIFY"; + case WPJOB_OCSP: return "OCSP"; + case WPJOB_OCHP: return "OCHP"; + case WPJOB_GLOBAL_SVC_EVTHANDLER: return "GLOBAL SERVICE EVENTHANDLER"; + case WPJOB_SVC_EVTHANDLER: return "SERVICE EVENTHANDLER"; + case WPJOB_GLOBAL_HOST_EVTHANDLER: return "GLOBAL HOST EVENTHANDLER"; + case WPJOB_HOST_EVTHANDLER: return "HOST EVENTHANDLER"; + case WPJOB_CALLBACK: return "CALLBACK"; + case WPJOB_HOST_PERFDATA: return "HOST PERFDATA"; + case WPJOB_SVC_PERFDATA: return "SERVICE PERFDATA"; + } + return "UNKNOWN"; +} + +static void wproc_logdump_buffer(int level, int show, const char *prefix, char *buf) +{ + char *ptr, *eol; + unsigned int line = 1; + + if (!buf || !*buf) + return; + for (ptr = buf; ptr && *ptr; ptr = eol ? eol + 1 : NULL) { + if ((eol = strchr(ptr, '\n'))) + *eol = 0; + logit(level, show, "%s line %.02d: %s\n", prefix, line++, ptr); + if (eol) + *eol = '\n'; + else + break; + } +} + +/* Try to reap 'jobs' jobs for 'msecs' milliseconds. Return early on error. */ +void wproc_reap(int jobs, int msecs) +{ + struct timeval start; + gettimeofday(&start, NULL); + + while (jobs > 0 && msecs > 0) { + int inputs = iobroker_poll(nagios_iobs, msecs); + if (inputs < 0) return; + + jobs -= inputs; /* One input is roughly equivalent to one job. */ + + struct timeval now; + gettimeofday(&now, NULL); + msecs -= tv_delta_msec(&start, &now); + start = now; + } +} + +int wproc_can_spawn(struct load_control *lc) +{ + unsigned int old = 0; + time_t now; + + /* if no load control is enabled, we can safely run this job */ + if (!(lc->options & LOADCTL_ENABLED)) + return 1; + + now = time(NULL); + if (lc->last_check + lc->check_interval > now) { + lc->last_check = now; + + if (getloadavg(lc->load, 3) < 0) + return lc->jobs_limit > lc->jobs_running; + + if (lc->load[0] > lc->backoff_limit) { + old = lc->jobs_limit; + lc->jobs_limit -= lc->backoff_change; + } + else if (lc->load[0] < lc->rampup_limit) { + old = lc->jobs_limit; + lc->jobs_limit += lc->rampup_change; + } + + if (lc->jobs_limit > lc->jobs_max) { + lc->jobs_limit = lc->jobs_max; + } + else if (lc->jobs_limit < lc->jobs_min) { + logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Tried to set jobs_limit to %u, below jobs_min (%u)\n", + lc->jobs_limit, lc->jobs_min); + lc->jobs_limit = lc->jobs_min; + } + + if (old && old != lc->jobs_limit) { + if (lc->jobs_limit < old) { + logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: loadctl.jobs_limit changed from %u to %u\n", old, lc->jobs_limit); + } else { + logit(NSLOG_INFO_MESSAGE, FALSE, "wproc: loadctl.jobs_limit changed from %u to %u\n", old, lc->jobs_limit); + } + } + } + + return lc->jobs_limit > lc->jobs_running; +} + +static int get_job_id(struct wproc_worker *wp) +{ + return wp->job_index++; +} + +static struct wproc_job *get_job(struct wproc_worker *wp, int job_id) +{ + return fanout_remove(wp->jobs, job_id); +} + + +static struct wproc_list *get_wproc_list(const char *cmd) +{ + struct wproc_list *wp_list; + char *cmd_name = NULL, *slash = NULL, *space; + + if (!specialized_workers) + return &workers; + + /* first, look for a specialized worker for this command */ + if ((space = strchr(cmd, ' ')) != NULL) { + int namelen = (unsigned long)space - (unsigned long)cmd; + cmd_name = calloc(1, namelen + 1); + /* not exactly optimal, but what the hells */ + if (!cmd_name) + return &workers; + memcpy(cmd_name, cmd, namelen); + slash = strrchr(cmd_name, '/'); + } + + wp_list = dkhash_get(specialized_workers, cmd_name ? cmd_name : cmd, NULL); + if (!wp_list && slash) { + wp_list = dkhash_get(specialized_workers, ++slash, NULL); + } + if (wp_list != NULL) { + log_debug_info(DEBUGL_CHECKS, 1, "Found specialized worker(s) for '%s'", (slash && *slash != '/') ? slash : cmd_name); + } + if (cmd_name) + free(cmd_name); + + return wp_list ? wp_list : &workers; +} + +static struct wproc_worker *get_worker(const char *cmd) +{ + struct wproc_list *wp_list; + + if (!cmd) + return NULL; + + wp_list = get_wproc_list(cmd); + if (!wp_list || !wp_list->wps || !wp_list->len) + return NULL; + + return wp_list->wps[wp_list->idx++ % wp_list->len]; +} + +static struct wproc_job *create_job(int type, void *arg, time_t timeout, const char *cmd) +{ + struct wproc_job *job; + struct wproc_worker *wp; + + wp = get_worker(cmd); + if (!wp) + return NULL; + + job = calloc(1, sizeof(*job)); + if (!job) { + logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Failed to allocate memory for worker job: %s\n", strerror(errno)); + return NULL; + } + + job->wp = wp; + job->id = get_job_id(wp); + job->type = type; + job->arg = arg; + job->timeout = timeout; + if (fanout_add(wp->jobs, job->id, job) < 0 || !(job->command = strdup(cmd))) { + free(job); + return NULL; + } + + return job; +} + +static void run_job_callback(struct wproc_job *job, struct wproc_result *wpres, int val) +{ + wproc_callback_job *cj; + + if (!job || !job->arg) + return; + cj = (struct wproc_callback_job *)job->arg; + + if (!cj->callback) + return; + cj->callback(wpres, cj->data, val); + cj->callback = NULL; +} + +static void destroy_job(struct wproc_job *job) +{ + if (!job) + return; + + switch (job->type) { + case WPJOB_CHECK: + free_check_result(job->arg); + free(job->arg); + break; + case WPJOB_NOTIFY: + case WPJOB_OCSP: + case WPJOB_OCHP: + free(job->arg); + break; + + case WPJOB_GLOBAL_SVC_EVTHANDLER: + case WPJOB_SVC_EVTHANDLER: + case WPJOB_GLOBAL_HOST_EVTHANDLER: + case WPJOB_HOST_EVTHANDLER: + case WPJOB_HOST_PERFDATA: + case WPJOB_SVC_PERFDATA: + /* these require nothing special */ + break; + case WPJOB_CALLBACK: + /* call with NULL result to make callback clean things up */ + run_job_callback(job, NULL, 0); + break; + default: + logit(NSLOG_RUNTIME_WARNING, TRUE, "wproc: Unknown job type: %d\n", job->type); + break; + } + + my_free(job->command); + if (job->wp) { + fanout_remove(job->wp->jobs, job->id); + job->wp->jobs_running--; + } + loadctl.jobs_running--; + + free(job); +} + +static void fo_destroy_job(void *job) +{ + destroy_job((struct wproc_job *)job); +} + +static int wproc_is_alive(struct wproc_worker *wp) +{ + if (!wp || !wp->pid) + return 0; + if (kill(wp->pid, 0) == 0 && iobroker_is_registered(nagios_iobs, wp->sd)) + return 1; + return 0; +} + +static int wproc_destroy(struct wproc_worker *wp, int flags) +{ + int i = 0, force = 0, self; + + if (!wp) + return 0; + + force = !!(flags & WPROC_FORCE); + + self = getpid(); + + /* master retains workers through restarts */ + if (self == nagios_pid && !force) + return 0; + + /* free all memory when either forcing or a worker called us */ + iocache_destroy(wp->ioc); + wp->ioc = NULL; + my_free(wp->name); + fanout_destroy(wp->jobs, fo_destroy_job); + wp->jobs = NULL; + + /* workers must never control other workers, so they return early */ + if (self != nagios_pid) + return 0; + + /* kill(0, SIGKILL) equals suicide, so we avoid it */ + if (wp->pid) { + kill(wp->pid, SIGKILL); + } + + iobroker_close(nagios_iobs, wp->sd); + + /* reap our possibly lost children */ + while (waitpid(-1, &i, WNOHANG) > 0) + ; /* do nothing */ + + free(wp); + + return 0; +} + +/* remove the worker list pointed to by to_remove */ +static int remove_specialized(void *data) +{ + if (data == to_remove) { + return DKHASH_WALK_REMOVE; + } else if (to_remove == NULL) { + /* remove all specialised workers and their lists */ + struct wproc_list *h = data; + int i; + for (i=0;ilen;i++) { + /* not sure what WPROC_FORCE is actually for. + * Nagios does *not* retain workers across + * restarts, as stated in wproc_destroy? + */ + wproc_destroy(h->wps[i], WPROC_FORCE); + } + h->len = 0; + free(h->wps); + free(h); + return DKHASH_WALK_REMOVE; + } + return 0; +} + +/* remove worker from job assignment list */ +static void remove_worker(struct wproc_worker *worker) +{ + unsigned int i, j = 0; + struct wproc_list *wpl = worker->wp_list; + for (i = 0; i < wpl->len; i++) { + if (wpl->wps[i] == worker) + continue; + wpl->wps[j++] = wpl->wps[i]; + } + wpl->len = j; + + if (!specialized_workers || wpl->len) + return; + + to_remove = wpl; + dkhash_walk_data(specialized_workers, remove_specialized); +} + + +/* + * This gets called from both parent and worker process, so + * we must take care not to blindly shut down everything here + */ +void free_worker_memory(int flags) +{ + if (workers.wps) { + unsigned int i; + + for (i = 0; i < workers.len; i++) { + if (!workers.wps[i]) + continue; + + wproc_destroy(workers.wps[i], flags); + workers.wps[i] = NULL; + } + + my_free(workers.wps); + } + workers.len = 0; + workers.idx = 0; + + to_remove = NULL; + dkhash_walk_data(specialized_workers, remove_specialized); + dkhash_destroy(specialized_workers); + specialized_workers = NULL; /* Don't leave pointers to freed memory. */ +} + +static int str2timeval(char *str, struct timeval *tv) +{ + char *ptr, *ptr2; + + tv->tv_sec = strtoul(str, &ptr, 10); + if (ptr == str) { + tv->tv_sec = tv->tv_usec = 0; + return -1; + } + if (*ptr == '.' || *ptr == ',') { + ptr2 = ptr + 1; + tv->tv_usec = strtoul(ptr2, &ptr, 10); + } + return 0; +} + +static int handle_worker_check(wproc_result *wpres, struct wproc_worker *wp, struct wproc_job *job) +{ + int result = ERROR; + check_result *cr = (check_result *)job->arg; + + memcpy(&cr->rusage, &wpres->rusage, sizeof(wpres->rusage)); + cr->start_time.tv_sec = wpres->start.tv_sec; + cr->start_time.tv_usec = wpres->start.tv_usec; + cr->finish_time.tv_sec = wpres->stop.tv_sec; + cr->finish_time.tv_usec = wpres->stop.tv_usec; + if (WIFEXITED(wpres->wait_status)) { + cr->return_code = WEXITSTATUS(wpres->wait_status); + } else { + cr->return_code = STATE_UNKNOWN; + } + + if (wpres->outstd && *wpres->outstd) { + cr->output = strdup(wpres->outstd); + } else if (wpres->outerr) { + asprintf(&cr->output, "(No output on stdout) stderr: %s", wpres->outerr); + } else { + cr->output = NULL; + } + + cr->early_timeout = wpres->early_timeout; + cr->exited_ok = wpres->exited_ok; + cr->engine = NULL; + cr->source = wp->name; + + process_check_result(cr); + free_check_result(cr); + + return result; +} + +/* + * parses a worker result. We do no strdup()'s here, so when + * kvv is destroyed, all references to strings will become + * invalid + */ +static int parse_worker_result(wproc_result *wpres, struct kvvec *kvv) +{ + int i; + + for (i = 0; i < kvv->kv_pairs; i++) { + struct wpres_key *k; + char *key, *value; + key = kvv->kv[i].key; + value = kvv->kv[i].value; + + k = wpres_get_key(key, kvv->kv[i].key_len); + if (!k) { + logit(NSLOG_RUNTIME_WARNING, TRUE, "wproc: Unrecognized result variable: (i=%d) %s=%s\n", i, key, value); + continue; + } + switch (k->code) { + case WPRES_job_id: + wpres->job_id = atoi(value); + break; + case WPRES_type: + wpres->type = atoi(value); + break; + case WPRES_command: + wpres->command = value; + break; + case WPRES_timeout: + wpres->timeout = atoi(value); + break; + case WPRES_wait_status: + wpres->wait_status = atoi(value); + break; + case WPRES_start: + str2timeval(value, &wpres->start); + break; + case WPRES_stop: + str2timeval(value, &wpres->stop); + break; + case WPRES_outstd: + wpres->outstd = value; + break; + case WPRES_outerr: + wpres->outerr = value; + break; + case WPRES_exited_ok: + wpres->exited_ok = atoi(value); + break; + case WPRES_error_msg: + wpres->exited_ok = FALSE; + wpres->error_msg = value; + break; + case WPRES_error_code: + wpres->exited_ok = FALSE; + wpres->error_code = atoi(value); + break; + case WPRES_runtime: + /* ignored */ + break; + case WPRES_ru_utime: + str2timeval(value, &wpres->rusage.ru_utime); + break; + case WPRES_ru_stime: + str2timeval(value, &wpres->rusage.ru_stime); + break; + case WPRES_ru_minflt: + wpres->rusage.ru_minflt = atoi(value); + break; + case WPRES_ru_majflt: + wpres->rusage.ru_majflt = atoi(value); + break; + case WPRES_ru_nswap: + wpres->rusage.ru_nswap = atoi(value); + break; + case WPRES_ru_inblock: + wpres->rusage.ru_inblock = atoi(value); + break; + case WPRES_ru_oublock: + wpres->rusage.ru_oublock = atoi(value); + break; + case WPRES_ru_msgsnd: + wpres->rusage.ru_msgsnd = atoi(value); + break; + case WPRES_ru_msgrcv: + wpres->rusage.ru_msgrcv = atoi(value); + break; + case WPRES_ru_nsignals: + wpres->rusage.ru_nsignals = atoi(value); + break; + case WPRES_ru_nvcsw: + wpres->rusage.ru_nsignals = atoi(value); + break; + case WPRES_ru_nivcsw: + wpres->rusage.ru_nsignals = atoi(value); + break; + + default: + logit(NSLOG_RUNTIME_WARNING, TRUE, "wproc: Recognized but unhandled result variable: %s=%s\n", key, value); + break; + } + } + return 0; +} + +static int wproc_run_job(struct wproc_job *job, nagios_macros *mac); +static void fo_reassign_wproc_job(void *job_) +{ + struct wproc_job *job = (struct wproc_job *)job_; + job->wp = get_worker(job->command); + job->id = get_job_id(job->wp); + /* macros aren't used right now anyways */ + wproc_run_job(job, NULL); +} + +static int handle_worker_result(int sd, int events, void *arg) +{ + wproc_object_job *oj = NULL; + char *buf, *error_reason = NULL; + unsigned long size; + int ret; + static struct kvvec kvv = KVVEC_INITIALIZER; + struct wproc_worker *wp = (struct wproc_worker *)arg; + + if(iocache_capacity(wp->ioc) == 0) { + logit(NSLOG_RUNTIME_WARNING, TRUE, "wproc: iocache_capacity() is 0 for worker %s.\n", wp->name); + } + + ret = iocache_read(wp->ioc, wp->sd); + + if (ret < 0) { + logit(NSLOG_RUNTIME_WARNING, TRUE, "wproc: iocache_read() from %s returned %d: %s\n", + wp->name, ret, strerror(errno)); + return 0; + } else if (ret == 0) { + logit(NSLOG_INFO_MESSAGE, TRUE, "wproc: Socket to worker %s broken, removing", wp->name); + wproc_num_workers_online--; + iobroker_unregister(nagios_iobs, sd); + if (workers.len <= 0) { + /* there aren't global workers left, we can't run any more checks + * we should try respawning a few of the standard ones + */ + logit(NSLOG_RUNTIME_ERROR, TRUE, "wproc: All our workers are dead, we can't do anything!"); + } + remove_worker(wp); + fanout_destroy(wp->jobs, fo_reassign_wproc_job); + wp->jobs = NULL; + wproc_destroy(wp, 0); + return 0; + } + while ((buf = worker_ioc2msg(wp->ioc, &size, 0))) { + struct wproc_job *job; + wproc_result wpres; + + /* log messages are handled first */ + if (size > 5 && !memcmp(buf, "log=", 4)) { + logit(NSLOG_INFO_MESSAGE, TRUE, "wproc: %s: %s\n", wp->name, buf + 4); + continue; + } + + /* for everything else we need to actually parse */ + if (buf2kvvec_prealloc(&kvv, buf, size, '=', '\0', KVVEC_ASSIGN) <= 0) { + logit(NSLOG_RUNTIME_ERROR, TRUE, + "wproc: Failed to parse key/value vector from worker response with len %lu. First kv=%s", + size, buf ? buf : "(NULL)"); + continue; + } + + memset(&wpres, 0, sizeof(wpres)); + wpres.job_id = -1; + wpres.type = -1; + wpres.response = &kvv; + parse_worker_result(&wpres, &kvv); + + job = get_job(wp, wpres.job_id); + if (!job) { + logit(NSLOG_RUNTIME_WARNING, TRUE, "wproc: Job with id '%d' doesn't exist on %s.\n", + wpres.job_id, wp->name); + continue; + } + if (wpres.type != job->type) { + logit(NSLOG_RUNTIME_WARNING, TRUE, "wproc: %s claims job %d is type %d, but we think it's type %d\n", + wp->name, job->id, wpres.type, job->type); + break; + } + oj = (wproc_object_job *)job->arg; + + /* + * ETIME ("Timer expired") doesn't really happen + * on any modern systems, so we reuse it to mean + * "program timed out" + */ + if (wpres.error_code == ETIME) { + wpres.early_timeout = TRUE; + } + if (wpres.early_timeout) { + asprintf(&error_reason, "timed out after %.2fs", tv_delta_f(&wpres.start, &wpres.stop)); + } + else if (WIFSIGNALED(wpres.wait_status)) { + asprintf(&error_reason, "died by signal %d%s after %.2f seconds", + WTERMSIG(wpres.wait_status), + WCOREDUMP(wpres.wait_status) ? " (core dumped)" : "", + tv_delta_f(&wpres.start, &wpres.stop)); + } + else if (job->type != WPJOB_CHECK && WEXITSTATUS(wpres.wait_status) != 0) { + asprintf(&error_reason, "is a non-check helper but exited with return code %d", + WEXITSTATUS(wpres.wait_status)); + } + if (error_reason) { + logit(NSLOG_RUNTIME_ERROR, TRUE, "wproc: %s job %d from worker %s %s", + wpjob_type_name(job->type), job->id, wp->name, error_reason); +#ifdef DEBUG + /* The log below could leak sensitive information, such as + passwords, so only enable it if you really need it */ + logit(NSLOG_RUNTIME_ERROR, TRUE, "wproc: command: %s\n", job->command); +#endif + if (job->type != WPJOB_CHECK && oj) { + logit(NSLOG_RUNTIME_ERROR, TRUE, "wproc: host=%s; service=%s; contact=%s\n", + oj->host_name ? oj->host_name : "(none)", + oj->service_description ? oj->service_description : "(none)", + oj->contact_name ? oj->contact_name : "(none)"); + } else if (oj) { + struct check_result *cr = (struct check_result *)job->arg; + logit(NSLOG_RUNTIME_ERROR, TRUE, "wproc: host=%s; service=%s;\n", + cr->host_name, cr->service_description); + } + logit(NSLOG_RUNTIME_ERROR, TRUE, "wproc: early_timeout=%d; exited_ok=%d; wait_status=%d; error_code=%d;\n", + wpres.early_timeout, wpres.exited_ok, wpres.wait_status, wpres.error_code); + wproc_logdump_buffer(NSLOG_RUNTIME_ERROR, TRUE, "wproc: stderr", wpres.outerr); + wproc_logdump_buffer(NSLOG_RUNTIME_ERROR, TRUE, "wproc: stdout", wpres.outstd); + } + my_free(error_reason); + + switch (job->type) { + case WPJOB_CHECK: + ret = handle_worker_check(&wpres, wp, job); + break; + case WPJOB_NOTIFY: + if (wpres.early_timeout) { + if (oj->service_description) { + logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Notifying contact '%s' of service '%s' on host '%s' by command '%s' timed out after %.2f seconds\n", + oj->contact_name, oj->service_description, + oj->host_name, job->command, + tv2float(&wpres.runtime)); + } else { + logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Notifying contact '%s' of host '%s' by command '%s' timed out after %.2f seconds\n", + oj->contact_name, oj->host_name, + job->command, tv2float(&wpres.runtime)); + } + } + break; + case WPJOB_OCSP: + if (wpres.early_timeout) { + logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: OCSP command '%s' for service '%s' on host '%s' timed out after %.2f seconds\n", + job->command, oj->service_description, oj->host_name, + tv2float(&wpres.runtime)); + } + break; + case WPJOB_OCHP: + if (wpres.early_timeout) { + logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: OCHP command '%s' for host '%s' timed out after %.2f seconds\n", + job->command, oj->host_name, tv2float(&wpres.runtime)); + } + break; + case WPJOB_GLOBAL_SVC_EVTHANDLER: + if (wpres.early_timeout) { + logit(NSLOG_EVENT_HANDLER | NSLOG_RUNTIME_WARNING, TRUE, + "Warning: Global service event handler command '%s' timed out after %.2f seconds\n", + job->command, tv2float(&wpres.runtime)); + } + break; + case WPJOB_SVC_EVTHANDLER: + if (wpres.early_timeout) { + logit(NSLOG_EVENT_HANDLER | NSLOG_RUNTIME_WARNING, TRUE, + "Warning: Service event handler command '%s' timed out after %.2f seconds\n", + job->command, tv2float(&wpres.runtime)); + } + break; + case WPJOB_GLOBAL_HOST_EVTHANDLER: + if (wpres.early_timeout) { + logit(NSLOG_EVENT_HANDLER | NSLOG_RUNTIME_WARNING, TRUE, + "Warning: Global host event handler command '%s' timed out after %.2f seconds\n", + job->command, tv2float(&wpres.runtime)); + } + break; + case WPJOB_HOST_EVTHANDLER: + if (wpres.early_timeout) { + logit(NSLOG_EVENT_HANDLER | NSLOG_RUNTIME_WARNING, TRUE, + "Warning: Host event handler command '%s' timed out after %.2f seconds\n", + job->command, tv2float(&wpres.runtime)); + } + break; + + case WPJOB_CALLBACK: + run_job_callback(job, &wpres, 0); + break; + + case WPJOB_HOST_PERFDATA: + case WPJOB_SVC_PERFDATA: + /* these require nothing special */ + break; + + default: + logit(NSLOG_RUNTIME_WARNING, TRUE, "Worker %ld: Unknown jobtype: %d\n", (long)wp->pid, job->type); + break; + } + destroy_job(job); + } + + return 0; +} + +int workers_alive(void) +{ + unsigned int i; + int alive = 0; + + for (i = 0; i < workers.len; i++) { + if (wproc_is_alive(workers.wps[i])) + alive++; + } + + return alive; +} + +/* a service for registering workers */ +static int register_worker(int sd, char *buf, unsigned int len) +{ + int i, is_global = 1; + struct kvvec *info; + struct wproc_worker *worker; + + logit(NSLOG_INFO_MESSAGE, TRUE, "wproc: Registry request: %s\n", buf); + if (!(worker = calloc(1, sizeof(*worker)))) { + logit(NSLOG_RUNTIME_ERROR, TRUE, "wproc: Failed to allocate worker: %s\n", strerror(errno)); + return 500; + } + + info = buf2kvvec(buf, len, '=', ';', 0); + if (info == NULL) { + free(worker); + logit(NSLOG_RUNTIME_ERROR, TRUE, "wproc: Failed to parse registration request\n"); + return 500; + } + + worker->sd = sd; + worker->ioc = iocache_create(1 * 1024 * 1024); + + iobroker_unregister(nagios_iobs, sd); + iobroker_register(nagios_iobs, sd, worker, handle_worker_result); + + for(i = 0; i < info->kv_pairs; i++) { + struct key_value *kv = &info->kv[i]; + if (!strcmp(kv->key, "name")) { + worker->name = strdup(kv->value); + } + else if (!strcmp(kv->key, "pid")) { + worker->pid = atoi(kv->value); + } + else if (!strcmp(kv->key, "max_jobs")) { + worker->max_jobs = atoi(kv->value); + } + else if (!strcmp(kv->key, "plugin")) { + struct wproc_list *command_handlers; + is_global = 0; + if (!(command_handlers = dkhash_get(specialized_workers, kv->value, NULL))) { + command_handlers = calloc(1, sizeof(struct wproc_list)); + command_handlers->wps = calloc(1, sizeof(struct wproc_worker**)); + command_handlers->len = 1; + command_handlers->wps[0] = worker; + dkhash_insert(specialized_workers, strdup(kv->value), NULL, command_handlers); + } + else { + command_handlers->len++; + command_handlers->wps = realloc(command_handlers->wps, command_handlers->len * sizeof(struct wproc_worker**)); + command_handlers->wps[command_handlers->len - 1] = worker; + } + worker->wp_list = command_handlers; + } + } + + if (!worker->max_jobs) { + /* + * each worker uses two filedescriptors per job, one to + * connect to the master and about 13 to handle libraries + * and memory allocation, so this guesstimate shouldn't + * be too far off (for local workers, at least). + */ + worker->max_jobs = (iobroker_max_usable_fds() / 2) - 50; + } + worker->jobs = fanout_create(worker->max_jobs); + + if (is_global) { + workers.len++; + workers.wps = realloc(workers.wps, workers.len * sizeof(struct wproc_worker *)); + workers.wps[workers.len - 1] = worker; + worker->wp_list = &workers; + } + wproc_num_workers_online++; + kvvec_destroy(info, 0); + nsock_printf_nul(sd, "OK"); + + /* signal query handler to release its iocache for this one */ + return QH_TAKEOVER; +} + +static int wproc_query_handler(int sd, char *buf, unsigned int len) +{ + char *space, *rbuf = NULL; + + if (!*buf || !strcmp(buf, "help")) { + nsock_printf_nul(sd, "Control worker processes.\n" + "Valid commands:\n" + " wpstats Print general job information\n" + " register Register a new worker\n" + " can be name, pid, max_jobs and/or plugin.\n" + " There can be many plugin args."); + return 0; + } + + if ((space = memchr(buf, ' ', len)) != NULL) + *space = 0; + + rbuf = space ? space + 1 : buf; + len -= (unsigned long)rbuf - (unsigned long)buf; + + if (!strcmp(buf, "register")) + return register_worker(sd, rbuf, len); + if (!strcmp(buf, "wpstats")) { + unsigned int i; + + for (i = 0; i < workers.len; i++) { + struct wproc_worker *wp = workers.wps[i]; + nsock_printf(sd, "name=%s;pid=%ld;jobs_running=%u;jobs_started=%u\n", + wp->name, (long)wp->pid, + wp->jobs_running, wp->jobs_started); + } + return 0; + } + + return 400; +} + +static int spawn_core_worker(void) +{ + char *argvec[] = {nagios_binary_path, "--worker", qh_socket_path ? qh_socket_path : DEFAULT_QUERY_SOCKET, NULL}; + int ret; + + if ((ret = spawn_helper(argvec)) < 0) + logit(NSLOG_RUNTIME_ERROR, TRUE, "wproc: Failed to launch core worker: %s\n", strerror(errno)); + else + wproc_num_workers_spawned++; + + return ret; +} + + +int init_workers(int desired_workers) +{ + specialized_workers = dkhash_create(512); + if (!specialized_workers) { + logit(NSLOG_RUNTIME_ERROR, TRUE, "wproc: Failed to allocate specialized worker table.\n"); + return -1; + } + + /* Register our query handler before launching workers, so other workers + * can join us whenever they're ready. */ + if (!qh_register_handler("wproc", "Worker process management and info", 0, wproc_query_handler)) + logit(NSLOG_INFO_MESSAGE, TRUE, "wproc: Successfully registered manager as @wproc with query handler\n"); + else + logit(NSLOG_RUNTIME_ERROR, TRUE, "wproc: Failed to register manager with query handler\n"); + + if (desired_workers <= 0) { + int cpus = online_cpus(); /* Always at least 1 CPU. */ + + if (desired_workers < 0) { + /* @note This is an undocumented case of questionable utility, and + * should be removed. Users reading this note have been warned. */ + desired_workers = cpus - desired_workers; + /* desired_workers is now > 0. */ + } else { + desired_workers = cpus * 1.5; + + if (desired_workers < 4) { + /* Use at least 4 workers when autocalculating so we have some + * level of parallelism. */ + desired_workers = 4; + } else if (desired_workers > 48) { + /* Limit the autocalculated workers so we don't spawn too many + * on systems with many schedulable cores (>32). */ + desired_workers = 48; + } + } + } + wproc_num_workers_desired = desired_workers; + + if (workers_alive() == desired_workers) + return 0; + + /* can't shrink the number of workers (yet) */ + if (desired_workers < (int)workers.len) + return -1; + + while (desired_workers-- > 0) + spawn_core_worker(); + + return 0; +} + +/* + * Handles adding the command and macros to the kvvec, + * as well as shipping the command off to a designated + * worker + */ +static int wproc_run_job(struct wproc_job *job, nagios_macros *mac) +{ + static struct kvvec kvv = KVVEC_INITIALIZER; + struct kvvec_buf *kvvb; + struct kvvec *env_kvvp = NULL; + struct kvvec_buf *env_kvvb = NULL; + struct wproc_worker *wp; + int ret, result = OK; + ssize_t written = 0; + + if (!job || !job->wp) + return ERROR; + + wp = job->wp; + + if (!kvvec_init(&kvv, 4)) /* job_id, type, command and timeout */ + return ERROR; + + kvvec_addkv(&kvv, "job_id", (char *)mkstr("%d", job->id)); + kvvec_addkv(&kvv, "type", (char *)mkstr("%d", job->type)); + kvvec_addkv(&kvv, "command", job->command); + kvvec_addkv(&kvv, "timeout", (char *)mkstr("%u", job->timeout)); + + /* Add the macro environment variables */ + if(mac) { + env_kvvp = macros_to_kvv(mac); + if(NULL != env_kvvp) { + env_kvvb = kvvec2buf(env_kvvp, '=', '\n', 0); + if(NULL == env_kvvb) { + kvvec_destroy(env_kvvp, KVVEC_FREE_KEYS); + } + else { + kvvec_addkv_wlen(&kvv, "env", strlen("env"), env_kvvb->buf, + env_kvvb->buflen); + } + } + } + kvvb = build_kvvec_buf(&kvv); + /* ret = write(wp->sd, kvvb->buf, kvvb->bufsize); */ + ret = nwrite(wp->sd, kvvb->buf, kvvb->bufsize, &written); + if (ret != (int)kvvb->bufsize) { + logit(NSLOG_RUNTIME_ERROR, TRUE, "wproc: '%s' seems to be choked. ret = %d; bufsize = %lu: written = %lu; errno = %d (%s)\n", + wp->name, ret, kvvb->bufsize, written, errno, strerror(errno)); + destroy_job(job); + result = ERROR; + } else { + wp->jobs_running++; + wp->jobs_started++; + loadctl.jobs_running++; + } + if(NULL != env_kvvp) kvvec_destroy(env_kvvp, KVVEC_FREE_KEYS); + if(NULL != env_kvvb) { + free(env_kvvb->buf); + free(env_kvvb); + } + free(kvvb->buf); + free(kvvb); + + return result; +} + +static wproc_object_job *create_object_job(char *cname, char *hname, char *sdesc) +{ + wproc_object_job *oj; + + oj = calloc(1, sizeof(*oj)); + if (oj) { + oj->host_name = hname; + if (cname) + oj->contact_name = cname; + if (sdesc) + oj->service_description = sdesc; + } + + return oj; +} + +int wproc_notify(char *cname, char *hname, char *sdesc, char *cmd, nagios_macros *mac) +{ + struct wproc_job *job; + wproc_object_job *oj; + + if (!(oj = create_object_job(cname, hname, sdesc))) + return ERROR; + + job = create_job(WPJOB_NOTIFY, oj, notification_timeout, cmd); + + return wproc_run_job(job, mac); +} + +int wproc_run_service_job(int jtype, int timeout, service *svc, char *cmd, nagios_macros *mac) +{ + struct wproc_job *job; + wproc_object_job *oj; + + if (!(oj = create_object_job(NULL, svc->host_name, svc->description))) + return ERROR; + + job = create_job(jtype, oj, timeout, cmd); + + return wproc_run_job(job, mac); +} + +int wproc_run_host_job(int jtype, int timeout, host *hst, char *cmd, nagios_macros *mac) +{ + struct wproc_job *job; + wproc_object_job *oj; + + if (!(oj = create_object_job(NULL, hst->name, NULL))) + return ERROR; + + job = create_job(jtype, oj, timeout, cmd); + + return wproc_run_job(job, mac); +} + +int wproc_run_check(check_result *cr, char *cmd, nagios_macros *mac) +{ + struct wproc_job *job; + int timeout; + + if (cr->service_description) + timeout = service_check_timeout; + else + timeout = host_check_timeout; + + job = create_job(WPJOB_CHECK, cr, timeout, cmd); + return wproc_run_job(job, mac); +} + +int wproc_run(int jtype, char *cmd, int timeout, nagios_macros *mac) +{ + struct wproc_job *job; + + job = create_job(jtype, NULL, timeout, cmd); + return wproc_run_job(job, mac); +} + +int wproc_run_callback(char *cmd, int timeout, + void (*cb)(struct wproc_result *, void *, int), void *data, + nagios_macros *mac) +{ + struct wproc_job *job; + struct wproc_callback_job *cj; + if (!(cj = calloc(1, sizeof(*cj)))) + return ERROR; + cj->callback = cb; + cj->data = data; + + job = create_job(WPJOB_CALLBACK, cj, timeout, cmd); + return wproc_run_job(job, mac); +} diff --git a/base/wp-phash.c b/base/wp-phash.c new file mode 100644 index 0000000..e38e6b6 --- /dev/null +++ b/base/wp-phash.c @@ -0,0 +1,98 @@ +#define WPRES_type 4 +#define WPRES_outerr 6 +#define WPRES_timeout 7 +#define WPRES_ru_nswap 8 +#define WPRES_error_msg 9 +#define WPRES_error_code 10 +#define WPRES_ru_nsignals 11 +#define WPRES_command 12 +#define WPRES_ru_majflt 14 +#define WPRES_start 15 +#define WPRES_outstd 16 +#define WPRES_ru_stime 18 +#define WPRES_exited_ok 19 +#define WPRES_ru_inblock 20 +#define WPRES_job_id 21 +#define WPRES_ru_minflt 24 +#define WPRES_ru_oublock 25 +#define WPRES_wait_status 26 +#define WPRES_runtime 27 +#define WPRES_stop 29 +#define WPRES_ru_utime 33 + +/* C code produced by gperf version 3.0.4 */ +/* Command-line: gperf -H wp_phash wproc-strings */ +/* Computed positions: -k'4-5' */ + +#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ + && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \ + && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \ + && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \ + && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \ + && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \ + && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \ + && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \ + && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \ + && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \ + && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \ + && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \ + && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \ + && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \ + && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \ + && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \ + && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \ + && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \ + && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \ + && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \ + && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \ + && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \ + && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126)) +/* The character set is not based on ISO-646. */ +error "gperf generated tables don't work with this execution character set. Please report a bug to ." +#endif + +static inline unsigned int +wp_phash(register const char *str, register unsigned int len) +{ + /* the last 136 entries have been cut, as we don't need them */ + static unsigned char asso_values[256] = + { + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 5, 34, 0, 34, 34, + 34, 0, 34, 34, 34, 10, 34, 34, 34, 5, + 0, 0, 25, 34, 0, 0, 10, 15, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, + 34, 34, 34, 34, 34, 34, + }; + register int hval = len; + + switch (hval) { + default: + hval += asso_values[(unsigned char)str[4]]; + /*FALLTHROUGH*/ + case 4: + hval += asso_values[(unsigned char)str[3]]; + break; + } + return hval; +} diff --git a/base/wpres-phash.h b/base/wpres-phash.h new file mode 100644 index 0000000..51fde5d --- /dev/null +++ b/base/wpres-phash.h @@ -0,0 +1,320 @@ +/* C code produced by gperf version 3.0.3 */ +/* Command-line: gperf -S 1 -t -H wpres_key_phash -N wpres_get_key wpres.gperf */ +/* Computed positions: -k'4-5,7' */ + +#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ + && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \ + && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \ + && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \ + && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \ + && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \ + && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \ + && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \ + && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \ + && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \ + && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \ + && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \ + && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \ + && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \ + && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \ + && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \ + && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \ + && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \ + && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \ + && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \ + && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \ + && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \ + && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126)) +/* The character set is not based on ISO-646. */ +error "gperf generated tables don't work with this execution character set. Please report a bug to ." +#endif + +#line 1 "wpres.gperf" + +enum { + WPRES_job_id, + WPRES_type, + WPRES_command, + WPRES_timeout, + WPRES_wait_status, + WPRES_start, + WPRES_stop, + WPRES_outstd, + WPRES_outerr, + WPRES_exited_ok, + WPRES_error_msg, + WPRES_error_code, + WPRES_runtime, + WPRES_ru_utime, + WPRES_ru_stime, + WPRES_ru_maxrss, + WPRES_ru_ixrss, + WPRES_ru_idrss, + WPRES_ru_isrss, + WPRES_ru_minflt, + WPRES_ru_majflt, + WPRES_ru_nswap, + WPRES_ru_inblock, + WPRES_ru_oublock, + WPRES_ru_msgsnd, + WPRES_ru_msgrcv, + WPRES_ru_nsignals, + WPRES_ru_nvcsw, + WPRES_ru_nivcsw, +}; +#include /* for strcmp() */ +#line 35 "wpres.gperf" +struct wpres_key { + const char *name; + int code; +}; + +#define TOTAL_KEYWORDS 29 +#define MIN_WORD_LENGTH 4 +#define MAX_WORD_LENGTH 11 +#define MIN_HASH_VALUE 4 +#define MAX_HASH_VALUE 64 +/* maximum key range = 61, duplicates = 0 */ + +#ifdef __GNUC__ +__inline +#else +#ifdef __cplusplus +inline +#endif +#endif +static unsigned int +wpres_key_phash (str, len) + register const char *str; + register unsigned int len; +{ + static unsigned char asso_values[] = + { + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 15, 65, 25, 65, 3, + 10, 0, 30, 0, 65, 0, 65, 65, 0, 0, + 0, 20, 5, 65, 0, 5, 0, 0, 30, 65, + 15, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65 + }; + register int hval = len; + + switch (hval) + { + default: + hval += asso_values[(unsigned char)str[6]]; + /*FALLTHROUGH*/ + case 6: + case 5: + hval += asso_values[(unsigned char)str[4]]; + /*FALLTHROUGH*/ + case 4: + hval += asso_values[(unsigned char)str[3]]; + break; + } + return hval; +} + +#ifdef __GNUC__ +__inline +#ifdef __GNUC_STDC_INLINE__ +__attribute__ ((__gnu_inline__)) +#endif +#endif +struct wpres_key * +wpres_get_key (str, len) + register const char *str; + register unsigned int len; +{ + static struct wpres_key wordlist[] = + { +#line 41 "wpres.gperf" + {"type", WPRES_type}, +#line 45 "wpres.gperf" + {"start", WPRES_start}, +#line 48 "wpres.gperf" + {"outerr", WPRES_outerr}, +#line 52 "wpres.gperf" + {"runtime", WPRES_runtime}, +#line 53 "wpres.gperf" + {"ru_utime", WPRES_ru_utime}, +#line 46 "wpres.gperf" + {"stop", WPRES_stop}, +#line 62 "wpres.gperf" + {"ru_inblock", WPRES_ru_inblock}, +#line 47 "wpres.gperf" + {"outstd", WPRES_outstd}, +#line 68 "wpres.gperf" + {"ru_nivcsw", WPRES_ru_nivcsw}, +#line 54 "wpres.gperf" + {"ru_stime", WPRES_ru_stime}, +#line 65 "wpres.gperf" + {"ru_msgrcv", WPRES_ru_msgrcv}, +#line 66 "wpres.gperf" + {"ru_nsignals", WPRES_ru_nsignals}, +#line 58 "wpres.gperf" + {"ru_isrss", WPRES_ru_isrss}, +#line 64 "wpres.gperf" + {"ru_msgsnd", WPRES_ru_msgsnd}, +#line 40 "wpres.gperf" + {"job_id", WPRES_job_id}, +#line 57 "wpres.gperf" + {"ru_idrss", WPRES_ru_idrss}, +#line 49 "wpres.gperf" + {"exited_ok", WPRES_exited_ok}, +#line 44 "wpres.gperf" + {"wait_status", WPRES_wait_status}, +#line 43 "wpres.gperf" + {"timeout", WPRES_timeout}, +#line 56 "wpres.gperf" + {"ru_ixrss", WPRES_ru_ixrss}, +#line 50 "wpres.gperf" + {"error_msg", WPRES_error_msg}, +#line 63 "wpres.gperf" + {"ru_oublock", WPRES_ru_oublock}, +#line 51 "wpres.gperf" + {"error_code", WPRES_error_code}, +#line 55 "wpres.gperf" + {"ru_maxrss", WPRES_ru_maxrss}, +#line 61 "wpres.gperf" + {"ru_nswap", WPRES_ru_nswap}, +#line 59 "wpres.gperf" + {"ru_minflt", WPRES_ru_minflt}, +#line 42 "wpres.gperf" + {"command", WPRES_command}, +#line 67 "wpres.gperf" + {"ru_nvcsw", WPRES_ru_nvcsw}, +#line 60 "wpres.gperf" + {"ru_majflt", WPRES_ru_majflt} + }; + + if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) + { + register int key = wpres_key_phash (str, len); + + if (key <= MAX_HASH_VALUE && key >= MIN_HASH_VALUE) + { + register struct wpres_key *resword; + + switch (key - 4) + { + case 0: + resword = &wordlist[0]; + goto compare; + case 1: + resword = &wordlist[1]; + goto compare; + case 2: + resword = &wordlist[2]; + goto compare; + case 3: + resword = &wordlist[3]; + goto compare; + case 4: + resword = &wordlist[4]; + goto compare; + case 5: + resword = &wordlist[5]; + goto compare; + case 6: + resword = &wordlist[6]; + goto compare; + case 7: + resword = &wordlist[7]; + goto compare; + case 8: + resword = &wordlist[8]; + goto compare; + case 9: + resword = &wordlist[9]; + goto compare; + case 10: + resword = &wordlist[10]; + goto compare; + case 12: + resword = &wordlist[11]; + goto compare; + case 14: + resword = &wordlist[12]; + goto compare; + case 15: + resword = &wordlist[13]; + goto compare; + case 17: + resword = &wordlist[14]; + goto compare; + case 19: + resword = &wordlist[15]; + goto compare; + case 20: + resword = &wordlist[16]; + goto compare; + case 22: + resword = &wordlist[17]; + goto compare; + case 23: + resword = &wordlist[18]; + goto compare; + case 24: + resword = &wordlist[19]; + goto compare; + case 25: + resword = &wordlist[20]; + goto compare; + case 26: + resword = &wordlist[21]; + goto compare; + case 29: + resword = &wordlist[22]; + goto compare; + case 30: + resword = &wordlist[23]; + goto compare; + case 34: + resword = &wordlist[24]; + goto compare; + case 35: + resword = &wordlist[25]; + goto compare; + case 38: + resword = &wordlist[26]; + goto compare; + case 39: + resword = &wordlist[27]; + goto compare; + case 60: + resword = &wordlist[28]; + goto compare; + } + return 0; + compare: + { + register const char *s = resword->name; + + if (*str == *s && !strcmp (str + 1, s + 1)) + return resword; + } + } + } + return 0; +} diff --git a/base/wpres.gperf b/base/wpres.gperf new file mode 100644 index 0000000..b6e5769 --- /dev/null +++ b/base/wpres.gperf @@ -0,0 +1,68 @@ +%{ +enum { + WPRES_job_id, + WPRES_type, + WPRES_command, + WPRES_timeout, + WPRES_wait_status, + WPRES_start, + WPRES_stop, + WPRES_outstd, + WPRES_outerr, + WPRES_exited_ok, + WPRES_error_msg, + WPRES_error_code, + WPRES_runtime, + WPRES_ru_utime, + WPRES_ru_stime, + WPRES_ru_maxrss, + WPRES_ru_ixrss, + WPRES_ru_idrss, + WPRES_ru_isrss, + WPRES_ru_minflt, + WPRES_ru_majflt, + WPRES_ru_nswap, + WPRES_ru_inblock, + WPRES_ru_oublock, + WPRES_ru_msgsnd, + WPRES_ru_msgrcv, + WPRES_ru_nsignals, + WPRES_ru_nvcsw, + WPRES_ru_nivcsw, +}; +#include /* for strcmp() */ +%} +struct wpres_key { + const char *name; + int code; +}; +%% +job_id, WPRES_job_id +type, WPRES_type +command, WPRES_command +timeout, WPRES_timeout +wait_status, WPRES_wait_status +start, WPRES_start +stop, WPRES_stop +outstd, WPRES_outstd +outerr, WPRES_outerr +exited_ok, WPRES_exited_ok +error_msg, WPRES_error_msg +error_code, WPRES_error_code +runtime, WPRES_runtime +ru_utime, WPRES_ru_utime +ru_stime, WPRES_ru_stime +ru_maxrss, WPRES_ru_maxrss +ru_ixrss, WPRES_ru_ixrss +ru_idrss, WPRES_ru_idrss +ru_isrss, WPRES_ru_isrss +ru_minflt, WPRES_ru_minflt +ru_majflt, WPRES_ru_majflt +ru_nswap, WPRES_ru_nswap +ru_inblock, WPRES_ru_inblock +ru_oublock, WPRES_ru_oublock +ru_msgsnd, WPRES_ru_msgsnd +ru_msgrcv, WPRES_ru_msgrcv +ru_nsignals, WPRES_ru_nsignals +ru_nvcsw, WPRES_ru_nvcsw +ru_nivcsw, WPRES_ru_nivcsw diff --git a/cgi/Makefile.in b/cgi/Makefile.in index e45b126..24e314d 100644 --- a/cgi/Makefile.in +++ b/cgi/Makefile.in @@ -1,7 +1,6 @@ ############################### # Makefile for Nagios CGIs # -# Last Modified: 10-30-2008 ############################### @@ -9,6 +8,7 @@ SRC_COMMON=../common SRC_INCLUDE=../include SRC_XDATA=../xdata +SRC_LIB=../lib prefix=@prefix@ exec_prefix=@exec_prefix@ @@ -26,7 +26,8 @@ CGIEXTRAS=@CGIEXTRAS@ CP=@CP@ CC=@CC@ -CFLAGS=-Wall @CFLAGS@ @DEFS@ -DNSCGI +CFLAGS=-Wall -I.. @CFLAGS@ @DEFS@ -DNSCGI +JSONFLAGS=-DJSON_NAGIOS_4X # Compiler flags for optimization (overrides default) #CFLAGS=-O3 -Wall -Wshadow -Wpointer-arith -Wcast-qual -Wcast-align -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs -DHAVE_CONFIG_H -DNSCGI @@ -39,20 +40,7 @@ CFLAGS=-Wall @CFLAGS@ @DEFS@ -DNSCGI LDFLAGS=@LDFLAGS@ LIBS=@LIBS@ -CGIS=avail.cgi cmd.cgi config.cgi extinfo.cgi history.cgi notifications.cgi outages.cgi showlog.cgi status.cgi statuswml.cgi summary.cgi tac.cgi $(CGIEXTRAS) - -# External data I/O code and headers -XSDC=@XSDC@ -XSDH=@XSDH@ -XCDC=@XCDC@ -XCDH=@XCDH@ -XODC=@XODC@ -XODH=@XODH@ -XDDC=@XDDC@ -XDDH=@XDDH@ - -# Generated automatically from configure script -SNPRINTF_O=@SNPRINTF_O@ +CGIS=archivejson.cgi avail.cgi cmd.cgi config.cgi extinfo.cgi history.cgi notifications.cgi objectjson.cgi outages.cgi showlog.cgi status.cgi statusjson.cgi statuswml.cgi summary.cgi tac.cgi $(CGIEXTRAS) # Object functions ODATALIBS=objects-cgi.o xobjects-cgi.o @@ -75,9 +63,9 @@ DDATAHDRS= DDATADEPS=$(DDATALIBS) # Common CGI functions (includes object and status functions) -CGILIBS=$(SRC_COMMON)/shared.o getcgi.o cgiutils.o cgiauth.o macros-cgi.o skiplist.o $(SNPRINTF_O) $(ODATALIBS) $(SDATALIBS) +CGILIBS=$(SRC_COMMON)/shared.o getcgi.o cgiutils.o cgiauth.o macros-cgi.o $(SNPRINTF_O) $(ODATALIBS) $(SDATALIBS) $(SRC_LIB)/libnagios.a CGIHDRS=$(SRC_INCLUDE)/config.h $(SRC_INCLUDE)/common.h $(SRC_INCLUDE)/locations.h -CGIDEPS=$(CGILIBS) $(ODATADEPS) $(SDATADEPS) +CGIDEPS=$(CGILIBS) $(ODATADEPS) $(SDATADEPS) $(SRC_LIB)/libnagios.a MATHLIBS=-lm @@ -91,8 +79,8 @@ $(CGILIBS): $(CGIHDRS) ######## REQUIRED LIBRARIES ########## -skiplist.o: $(SRC_COMMON)/skiplist.c $(SRC_INCLUDE)/skiplist.h - $(CC) $(CFLAGS) -c -o $@ $(SRC_COMMON)/skiplist.c +$(SRC_LIB)/libnagios.a: + $(MAKE) -C $(SRC_LIB) macros-cgi.o: $(SRC_COMMON)/macros.c $(SRC_INCLUDE)/macros.h $(CC) $(CFLAGS) -c -o $@ $(SRC_COMMON)/macros.c @@ -100,27 +88,21 @@ macros-cgi.o: $(SRC_COMMON)/macros.c $(SRC_INCLUDE)/macros.h objects-cgi.o: $(SRC_COMMON)/objects.c $(SRC_INCLUDE)/objects.h $(CC) $(CFLAGS) -c -o $@ $(SRC_COMMON)/objects.c -xobjects-cgi.o: $(SRC_XDATA)/$(XODC) $(SRC_XDATA)/$(XODH) - $(CC) $(CFLAGS) -c -o $@ $(SRC_XDATA)/$(XODC) +xobjects-cgi.o: $(SRC_XDATA)/xodtemplate.c $(SRC_XDATA)/xodtemplate.h + $(CC) $(CFLAGS) -c -o $@ $(SRC_XDATA)/xodtemplate.c statusdata-cgi.o: $(SRC_COMMON)/statusdata.c $(SRC_INCLUDE)/statusdata.h $(CC) $(CFLAGS) -c -o $@ $(SRC_COMMON)/statusdata.c -xstatusdata-cgi.o: $(SRC_XDATA)/$(XSDC) $(SRC_XDATA)/$(XSDH) - $(CC) $(CFLAGS) -c -o $@ $(SRC_XDATA)/$(XSDC) +xstatusdata-cgi.o: $(SRC_XDATA)/xsddefault.c $(SRC_XDATA)/xsddefault.h + $(CC) $(CFLAGS) -c -o $@ $(SRC_XDATA)/xsddefault.c comments-cgi.o: $(SRC_COMMON)/comments.c $(SRC_INCLUDE)/comments.h $(CC) $(CFLAGS) -c -o $@ $(SRC_COMMON)/comments.c -xcomments-cgi.o: $(SRC_XDATA)/$(XCDC) $(SRC_XDATA)/$(XCDH) - $(CC) $(CFLAGS) -c -o $@ $(SRC_XDATA)/$(XCDC) - downtime-cgi.o: $(SRC_COMMON)/downtime.c $(SRC_INCLUDE)/downtime.h $(CC) $(CFLAGS) -c -o $@ $(SRC_COMMON)/downtime.c -xdowntime-cgi.o: $(SRC_XDATA)/$(XDDC) $(SRC_XDATA)/$(XDDH) - $(CC) $(CFLAGS) -c -o $@ $(SRC_XDATA)/$(XDDC) - $(SRC_COMMON)/shared.o: $(SRC_COMMON)/shared.c $(CC) $(CFLAGS) -c -o $@ $< @@ -183,6 +165,24 @@ trends.cgi: trends.c $(CGIDEPS) histogram.cgi: histogram.c $(CGIDEPS) $(CC) $(CFLAGS) $(LDFLAGS) -o $@ histogram.c $(CGILIBS) $(GDLIBS) $(LIBS) +########## JSON CGIS ########## + +jsonutils.o: jsonutils.c $(SRC_INCLUDE)/jsonutils.h + $(CC) $(CFLAGS) $(JSONFLAGS) -c -o $@ jsonutils.c + +archiveutils.o: archiveutils.c $(SRC_INCLUDE)/archiveutils.h + $(CC) $(CFLAGS) $(JSONFLAGS) -c -o $@ archiveutils.c + +archivejson.cgi: archivejson.c $(CGIDEPS) archiveutils.o jsonutils.o $(SRC_INCLUDE)/archivejson.h + $(CC) $(CFLAGS) $(JSONFLAGS) $(LDFLAGS) -o $@ archivejson.c $(CGILIBS) archiveutils.o jsonutils.o $(LIBS) + +objectjson.cgi: objectjson.c $(CGIDEPS) jsonutils.o $(SRC_INCLUDE)/objectjson.h + $(CC) $(CFLAGS) $(JSONFLAGS) $(LDFLAGS) -o $@ objectjson.c $(CGILIBS) jsonutils.o $(LIBS) + +statusjson.cgi: statusjson.c $(CGIDEPS) jsonutils.o $(SRC_INCLUDE)/statusjson.h + $(CC) $(CFLAGS) $(JSONFLAGS) $(LDFLAGS) -o $@ statusjson.c $(CGILIBS) jsonutils.o $(LIBS) + + clean: rm -f $(CGIS) rm -f *.o core gmon.out @@ -212,3 +212,4 @@ strip-post-install: done +.PHONY: libnagios diff --git a/cgi/archivejson.c b/cgi/archivejson.c new file mode 100644 index 0000000..ccf486c --- /dev/null +++ b/cgi/archivejson.c @@ -0,0 +1,4622 @@ +/************************************************************************** + * + * ARCHIVEJSON.C - Nagios CGI for returning JSON-formatted archive data + * + * Copyright (c) 2013 Nagios Enterprises, LLC + * Last Modified: 04-13-2013 + * + * License: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + *************************************************************************/ + +#include "../include/config.h" +#include "../include/common.h" +#include "../include/objects.h" +#include "../include/statusdata.h" + +#include "../include/cgiutils.h" +#include "../include/getcgi.h" +#include "../include/cgiauth.h" +#include "../include/jsonutils.h" +#include "../include/archiveutils.h" +#include "../include/archivejson.h" + +#define THISCGI "archivejson.cgi" + +#define min(a,b) ((a) < (b) ? (a) : (b)) +#define max(a,b) ((a) > (b) ? (a) : (b)) + +extern char main_config_file[MAX_FILENAME_LENGTH]; +extern int log_rotation_method; +extern char *status_file; + +extern host *host_list; +extern hostgroup *hostgroup_list; +extern service *service_list; +extern servicegroup *servicegroup_list; +#if 0 +extern contact *contact_list; +extern contactgroup *contactgroup_list; +extern timeperiod *timeperiod_list; +extern command *command_list; +extern servicedependency *servicedependency_list; +extern serviceescalation *serviceescalation_list; +extern hostdependency *hostdependency_list; +extern hostescalation *hostescalation_list; +#endif + +void document_header(); +void document_footer(void); +void init_cgi_data(archive_json_cgi_data *); +int process_cgivars(json_object *, archive_json_cgi_data *, time_t); +void free_cgi_data(archive_json_cgi_data *); +int validate_arguments(json_object *, archive_json_cgi_data *, time_t); + +authdata current_authdata; + +const string_value_mapping valid_queries[] = { + { "help", ARCHIVE_QUERY_HELP, + "Display help for this CGI" }, + { "alertcount", ARCHIVE_QUERY_ALERTCOUNT, + "Return the number of alerts" }, + { "alertlist", ARCHIVE_QUERY_ALERTLIST, + "Return a list of alerts" }, + { "notificationcount", ARCHIVE_QUERY_NOTIFICATIONCOUNT, + "Return the number of notifications" }, + { "notificationlist", ARCHIVE_QUERY_NOTIFICATIONLIST, + "Return a list of notifications" }, + { "statechangelist", ARCHIVE_QUERY_STATECHANGELIST, + "Return a list of state changes" }, + { "availability", ARCHIVE_QUERY_AVAILABILITY, + "Return an availability report" }, + { NULL, -1, NULL }, + }; + +static const int query_status[][2] = { + { ARCHIVE_QUERY_HELP, QUERY_STATUS_RELEASED }, + { ARCHIVE_QUERY_ALERTCOUNT, QUERY_STATUS_RELEASED }, + { ARCHIVE_QUERY_ALERTLIST, QUERY_STATUS_RELEASED }, + { ARCHIVE_QUERY_NOTIFICATIONCOUNT, QUERY_STATUS_RELEASED }, + { ARCHIVE_QUERY_NOTIFICATIONLIST, QUERY_STATUS_RELEASED }, + { ARCHIVE_QUERY_STATECHANGELIST, QUERY_STATUS_RELEASED }, + { ARCHIVE_QUERY_AVAILABILITY, QUERY_STATUS_RELEASED }, + { -1, -1 }, + }; + +const string_value_mapping valid_object_types[] = { + { "host", AU_OBJTYPE_HOST, "Host" }, + { "service", AU_OBJTYPE_SERVICE, "Service" }, + { NULL, -1, NULL }, + }; + +const string_value_mapping valid_availability_object_types[] = { + { "hosts", AU_OBJTYPE_HOST, "Hosts" }, + { "hostgroups", AU_OBJTYPE_HOSTGROUP, "Hostgroups" }, + { "services", AU_OBJTYPE_SERVICE, "Services" }, + { "servicegroups", AU_OBJTYPE_SERVICEGROUP, "Servicegroups" }, + { NULL, -1, NULL }, + }; + +const string_value_mapping valid_state_types[] = { + { "hard", AU_STATETYPE_HARD, "Hard" }, + { "soft", AU_STATETYPE_SOFT, "Soft" }, + { NULL, -1, NULL }, + }; + +const string_value_mapping valid_states[] = { + { "no_data", AU_STATE_NO_DATA, "No Data" }, + { "host_up", AU_STATE_HOST_UP, "Host Up" }, + { "host_down", AU_STATE_HOST_DOWN, "Host Down" }, + { "host_unreachable", AU_STATE_HOST_UNREACHABLE, "Host Unreachable" }, + { "service_ok", AU_STATE_SERVICE_OK, "Service OK" }, + { "service_warning", AU_STATE_SERVICE_WARNING, "Service Warning" }, + { "service_critical", AU_STATE_SERVICE_CRITICAL, "Service Critical" }, + { "service_unknown", AU_STATE_SERVICE_UNKNOWN, "Service Unknown" }, + { "program_start", AU_STATE_PROGRAM_START, "Program Start" }, + { "program_end", AU_STATE_PROGRAM_END, "Program End" }, + { "downtime_start", AU_STATE_DOWNTIME_START, "Downtime Start" }, + { "downtime_end", AU_STATE_DOWNTIME_END, "Downtime End" }, +}; + +const string_value_mapping valid_host_states[] = { + { "up", AU_STATE_HOST_UP, "Up" }, + { "down", AU_STATE_HOST_DOWN, "Down" }, + { "unreachable", AU_STATE_HOST_UNREACHABLE, "Unreachable" }, + { NULL, -1, NULL }, + }; + +const string_value_mapping valid_initial_host_states[] = { + { "up", AU_STATE_HOST_UP, "Up" }, + { "down", AU_STATE_HOST_DOWN, "Down" }, + { "unreachable", AU_STATE_HOST_UNREACHABLE, "Unreachable" }, + { "current", AU_STATE_CURRENT_STATE, "Current State" }, + { NULL, -1, NULL }, + }; + +const string_value_mapping valid_service_states[] = { + { "ok", AU_STATE_SERVICE_OK, "Ok" }, + { "warning", AU_STATE_SERVICE_WARNING, "Warning" }, + { "critical", AU_STATE_SERVICE_CRITICAL, "Critical" }, + { "unknown", AU_STATE_SERVICE_UNKNOWN, "Unknown" }, + { NULL, -1, NULL }, + }; + +const string_value_mapping valid_initial_service_states[] = { + { "ok", AU_STATE_SERVICE_OK, "Ok" }, + { "warning", AU_STATE_SERVICE_WARNING, "Warning" }, + { "critical", AU_STATE_SERVICE_CRITICAL, "Critical" }, + { "unknown", AU_STATE_SERVICE_UNKNOWN, "Unknown" }, + { "current", AU_STATE_CURRENT_STATE, "Current State" }, + { NULL, -1, NULL }, + }; + +const string_value_mapping valid_host_notification_types[] = { + { "nodata", AU_NOTIFICATION_NO_DATA, + "No Data" }, + { "down", AU_NOTIFICATION_HOST_DOWN, + "Host Down" }, + { "unreachable", AU_NOTIFICATION_HOST_UNREACHABLE, + "Host Unreachable" }, + { "recovery", AU_NOTIFICATION_HOST_RECOVERY, + "Host Recovery" }, + { "hostcustom", AU_NOTIFICATION_HOST_CUSTOM, + "Host Custom" }, + { "hostack", AU_NOTIFICATION_HOST_ACK, + "Host Acknowledgement" }, + { "hostflapstart", AU_NOTIFICATION_HOST_FLAPPING_START, + "Host Flapping Start" }, + { "hostflapstop", AU_NOTIFICATION_HOST_FLAPPING_STOP, + "Host Flapping Stop" }, + { NULL, -1, NULL }, + }; + +const string_value_mapping valid_service_notification_types[] = { + { "nodata", AU_NOTIFICATION_NO_DATA, + "No Data" }, + { "critical", AU_NOTIFICATION_SERVICE_CRITICAL, + "Service Critical" }, + { "warning", AU_NOTIFICATION_SERVICE_WARNING, + "Service Warning" }, + { "recovery", AU_NOTIFICATION_SERVICE_RECOVERY, + "Service Recovery" }, + { "custom", AU_NOTIFICATION_SERVICE_CUSTOM, + "Service Custom" }, + { "serviceack", AU_NOTIFICATION_SERVICE_ACK, + "Service Acknowledgement" }, + { "serviceflapstart", AU_NOTIFICATION_SERVICE_FLAPPING_START, + "Service Flapping Start" }, + { "serviceflapstop", AU_NOTIFICATION_SERVICE_FLAPPING_STOP, + "Service Flapping Stop" }, + { "unknown", AU_NOTIFICATION_SERVICE_UNKNOWN, + "Service Unknown" }, + { NULL, -1, NULL }, + }; + +option_help archive_json_help[] = { + { + "query", + "Query", + "enumeration", + { "all", NULL }, + { NULL }, + NULL, + "Specifies the type of query to be executed.", + valid_queries + }, + { + "formatoptions", + "Format Options", + "list", + { NULL }, + { "all", NULL }, + NULL, + "Specifies the formatting options to be used when displaying the results. Multiple options are allowed and are separated by a plus (+) sign..", + svm_format_options + }, + { + "start", + "Start", + "integer", + { NULL }, + { "alertlist", "notificationlist", "statechangelist", NULL }, + NULL, + "Specifies the index (zero-based) of the first object in the list to be returned.", + NULL + }, + { + "count", + "Count", + "integer", + { NULL }, + { "alertlist", "notificationlist", "statechangelist", NULL }, + NULL, + "Specifies the number of objects in the list to be returned.", + NULL + }, + { + "dateformat", + "Date Format", + "string", + { NULL }, + { "all", NULL }, + NULL, + "strftime format string for values of type time_t. In the absence of a format, the Javascript default format of the number of milliseconds since the beginning of the Unix epoch is used. Because of URL encoding, percent signs must be encoded as %25 and a space must be encoded as a plus (+) sign.", + NULL + }, + { + "objecttypes", + "Object Types", + "list", + { NULL }, + { "alertcount", "alertlist", "notificationcount", "notificationlist", + NULL }, + NULL, + "Type(s) of object to be included in query results.", + valid_object_types + }, + { + "objecttype", + "Object Type", + "enumeration", + { "statechangelist", NULL }, + { NULL }, + NULL, + "Type of object to be included in query results.", + valid_object_types + }, + { + "availabilityobjecttype", + "Availability Object Type", + "enumeration", + { "availability", NULL }, + { NULL }, + NULL, + "Type of object to be included in query results.", + valid_availability_object_types + }, + { + "statetypes", + "State Types", + "list", + { NULL }, + { "alertcount", "alertlist", "statechangelist", "availability", NULL }, + NULL, + "Type(s) of states to be included in query results.", + valid_state_types + }, + { + "hoststates", + "Host States", + "list", + { NULL }, + { "alertcount", "alertlist", NULL }, + NULL, + "Host states to be included in query results.", + valid_host_states + }, + { + "servicestates", + "Service States", + "list", + { NULL }, + { "alertcount", "alertlist", NULL }, + NULL, + "Service states to be included in query results.", + valid_service_states + }, + { + "hostnotificationtypes", + "Host Notification Types", + "list", + { NULL }, + { "notificationcount", "notificationlist", NULL }, + NULL, + "Host notification types to be included in query results.", + valid_host_notification_types + }, + { + "servicenotificationtypes", + "Service Notification Types", + "list", + { NULL }, + { "notificationcount", "notificationlist", NULL }, + NULL, + "Service notification types to be included in query results.", + valid_service_notification_types + }, + { + "parenthost", + "Parent Host", + "nagios:objectjson/hostlist", + { NULL }, + { "alertcount", "alertlist", "notificationcount", "notificationlist", + NULL }, + NULL, + "Limits the hosts or services returned to those whose host parent is specified. A value of 'none' returns all hosts or services reachable directly by the Nagios core host.", + parent_host_extras + }, + { + "childhost", + "Child Host", + "nagios:objectjson/hostlist", + { NULL }, + { "alertcount", "alertlist", "notificationcount", "notificationlist", + NULL }, + NULL, + "Limits the hosts or services returned to those whose having the host specified as a child host. A value of 'none' returns all hosts or services with no child hosts.", + child_host_extras + }, + { + "hostname", + "Host Name", + "nagios:objectjson/hostlist", + { "statechangelist", NULL }, + { "alertcount", "alertlist", "notificationcount", "notificationlist", + "availability", NULL }, + NULL, + "Name for the host requested. For availability reports if the " + "availability object type is hosts and the hostname is not " + "specified, the report will be generated for all hosts. Likewise, " + "if the availability object type is services and the hostname is not " + "specified, the report will be generated for all services or all " + "services with the same description, depending on the value for " + "service description.", + NULL + }, + { + "hostgroup", + "Host Group", + "nagios:objectjson/hostgrouplist", + { NULL }, + { "alertcount", "alertlist", "notificationcount", "notificationlist", + "availability", NULL }, + NULL, + "Returns information applicable to the hosts in the hostgroup.", + NULL + }, + { + "servicegroup", + "Service Group", + "nagios:objectjson/servicegrouplist", + { NULL }, + { "alertcount", "alertlist", "notificationcount", "notificationlist", + "availability", NULL }, + NULL, + "Returns information applicable to the services in the servicegroup.", + NULL + }, + { + "servicedescription", + "Service Description", + "nagios:objectjson/servicelist", + { NULL }, + { "alertcount", "alertlist", "notificationcount", "notificationlist", + "statechangelist", "availability", NULL }, + "hostname", + "Description for the service requested. For availability reports, " + "if the availability object type is services and the " + "servicedescription is not specified, the report will be generated " + "either for all services or for all services on the specified host, " + "depending on the value specified for hostname", + NULL + }, + { + "contactname", + "Contact Name", + "nagios:objectjson/contactlist", + { NULL }, + { "alertcount", "alertlist", "notificationcount", "notificationlist", + NULL }, + NULL, + "Name for the contact requested.", + NULL + }, + { + "contactgroup", + "Contact Group", + "nagios:objectjson/contactgrouplist", + { NULL }, + { "alertcount", "alertlist", "notificationcount", "notificationlist", + NULL }, + NULL, + "Returns information applicable to the contacts in the contactgroup.", + NULL + }, + { + "notificationmethod", + "Notification Method", + "nagios:objectjson/commandlist", + { NULL }, + { "notificationcount", "notificationlist", NULL }, + NULL, + "Returns objects that match the notification method.", + NULL + }, + { + "timeperiod", + "Report Time Period", + "nagios:objectjson/timeperiodlist", + { NULL }, + { "availability", NULL }, + NULL, + "Timeperiod to use for the report.", + NULL + }, + { + "assumeinitialstate", + "Assume Initial State", + "boolean", + { NULL }, + { "availability", NULL }, + NULL, + "Assume the initial state for the host(s) or service(s). Note that if true, assuming the initial state will be done only if the initial state could not be discovered by looking through the backtracked logs.", + NULL + }, + { + "assumestateretention", + "Assume State Retention", + "boolean", + { NULL }, + { "availability", NULL }, + NULL, + "Assume states are retained.", + NULL + }, + { + "assumestatesduringnagiosdowntime", + "Assume States During Nagios Downtime", + "boolean", + { NULL }, + { "availability", NULL }, + NULL, + "Assume states are retained during Nagios downtime.", + NULL + }, + { + "assumedinitialhoststate", + "Assumed Initial Host State", + "enumeration", + { NULL }, + { "availability", NULL }, + NULL, + "Host state assumed when it is not possible to determine the initial host state.", + valid_initial_host_states + }, + { + "assumedinitialservicestate", + "Assumed Initial Service State", + "enumeration", + { NULL }, + { "availability", NULL }, + NULL, + "Service state assumed when it is not possible to determine the initial service state.", + valid_initial_service_states + }, + { + "backtrackedarchives", + "Backtracked Archives", + "integer", + { NULL }, + { "alertcount", "alertlist", "notificationcount", "notificationlist", + "statechangelist", "availability", NULL }, + NULL, + "Number of backtracked archives to read in an attempt to find initial states.", + NULL, + }, + { + "starttime", + "Start Time", + "integer", + { "alertcount", "alertlist", "notificationcount", "notificationlist", + "statechangelist", "availability", NULL }, + { NULL }, + NULL, + "Starting time to use. Supplying a plus or minus sign means times relative to the query time.", + NULL, + }, + { + "endtime", + "End Time", + "integer", + { "alertcount", "alertlist", "notificationcount", "notificationlist", + "statechangelist", "availability", NULL }, + { NULL }, + NULL, + "Ending time to use. Specifying plus or minus sign means times relative to the query time.", + NULL, + }, + { /* The last entry must contain all NULL entries */ + NULL, + NULL, + NULL, + { NULL }, + { NULL }, + NULL, + NULL, + NULL + }, + }; + +extern const json_escape percent_escapes; + +int json_archive_alert_passes_selection(time_t, time_t, time_t, int, int, + au_host *, char *, au_service *, char *, int, host *, int, host *, + hostgroup *, servicegroup *, contact *, contactgroup *, unsigned, + unsigned, unsigned, unsigned, unsigned); +json_object *json_archive_alert_selectors(unsigned, int, int, time_t, time_t, + int, char *, char *, int, host *, int, host *, hostgroup *, + servicegroup *, contact *, contactgroup *, unsigned, unsigned, + unsigned); + +int json_archive_notification_passes_selection(time_t, time_t, time_t, int, + int, au_host *, char *, au_service *, char *, int, host *, int, host *, + hostgroup *, servicegroup *, au_contact *, char *, contactgroup *, + unsigned, unsigned, unsigned, char *, char *); +json_object *json_archive_notification_selectors(unsigned, int, int, time_t, + time_t, int, char *, char *, int, host *, int, host *, hostgroup *, + servicegroup *, char *, contactgroup *, unsigned, unsigned, char *); + +int json_archive_statechange_passes_selection(time_t, time_t, int, int, + au_host *, char *, au_service *, char *, unsigned, unsigned); +json_object *json_archive_statechange_selectors(unsigned, int, int, time_t, + time_t, int, char *, char *, unsigned); + +int get_initial_nagios_state(au_linked_list *, time_t, time_t); +int get_initial_downtime_state(au_linked_list *, time_t, time_t); +int get_initial_subject_state(au_linked_list *, time_t, time_t); +int get_log_entry_state(au_log_entry *); +int have_data(au_linked_list *, int); +void compute_window_availability(time_t, time_t, int, int, int, timeperiod *, + au_availability *, int, int, int); +static void compute_availability(au_linked_list *, time_t, time_t, time_t, + timeperiod *, au_availability *, int, int, int, int); +void compute_host_availability(time_t, time_t, time_t, au_log *, au_host *, + timeperiod *, int, int, int, int); +void compute_service_availability(time_t, time_t, time_t, au_log *, + au_service *, timeperiod *, int, int, int, int); +json_object *json_archive_single_host_availability(unsigned, time_t, time_t, + time_t, char *, timeperiod *, int, int, int, int, unsigned, au_log *); +json_object *json_archive_single_service_availability(unsigned, time_t, time_t, + time_t, char *, char *, timeperiod *, int, int, int, int, unsigned, + au_log *); +json_object *json_archive_host_availability(unsigned, char *, + au_availability *); +json_object *json_archive_service_availability(unsigned, char *, char *, + au_availability *); + +int main(void) { + int result = OK; + time_t query_time; + archive_json_cgi_data cgi_data; + json_object *json_root; + au_log *log; + time_t last_archive_data_update = (time_t)0; + json_object_member *romp = NULL; + + /* The official time of the query */ + time(&query_time); + + json_root = json_new_object(); + if(NULL == json_root) { + printf( "Failed to create new json object\n"); + exit( 1); + } + json_object_append_integer(json_root, "format_version", + OUTPUT_FORMAT_VERSION); + + /* Initialize shared configuration variables */ + init_shared_cfg_vars(1); + + init_cgi_data(&cgi_data); + + document_header(); + + /* get the arguments passed in the URL */ + result = process_cgivars(json_root, &cgi_data, query_time); + if(result != RESULT_SUCCESS) { + json_object_append_object(json_root, "data", + json_help(archive_json_help)); + json_object_print(json_root, 0, 1, cgi_data.strftime_format, + cgi_data.format_options); + document_footer(); + return result; + } + + /* reset internal variables */ + reset_cgi_vars(); + + /* read the CGI configuration file */ + result = read_cgi_config_file(get_cgi_config_location()); + if(result == ERROR) { + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + (time_t)-1, NULL, RESULT_FILE_OPEN_READ_ERROR, + "Error: Could not open CGI configuration file '%s' for reading!", + get_cgi_config_location())); + json_object_append_object(json_root, "data", + json_help(archive_json_help)); + json_object_print(json_root, 0, 1, cgi_data.strftime_format, + cgi_data.format_options); + document_footer(); + return ERROR; + } + + /* read the main configuration file */ + result = read_main_config_file(main_config_file); + if(result == ERROR) { + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + (time_t)-1, NULL, RESULT_FILE_OPEN_READ_ERROR, + "Error: Could not open main configuration file '%s' for reading!", + main_config_file)); + json_object_append_object(json_root, "data", + json_help(archive_json_help)); + document_footer(); + return ERROR; + } + + /* Set the number of backtracked archives if it wasn't specified by the + user */ + if(0 == cgi_data.backtracked_archives) { + switch(log_rotation_method) { + case LOG_ROTATION_MONTHLY: + cgi_data.backtracked_archives = 1; + break; + case LOG_ROTATION_WEEKLY: + cgi_data.backtracked_archives = 2; + break; + case LOG_ROTATION_DAILY: + cgi_data.backtracked_archives = 4; + break; + case LOG_ROTATION_HOURLY: + cgi_data.backtracked_archives = 8; + break; + default: + cgi_data.backtracked_archives = 2; + break; + } + } + + /* read all object configuration data */ + result = read_all_object_configuration_data(main_config_file, + READ_ALL_OBJECT_DATA); + if(result == ERROR) { + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + (time_t)-1, NULL, RESULT_FILE_OPEN_READ_ERROR, + "Error: Could not read some or all object configuration data!")); + json_object_append_object(json_root, "data", + json_help(archive_json_help)); + document_footer(); + return ERROR; + } + + /* read all status data */ + result = read_all_status_data(status_file, READ_ALL_STATUS_DATA); + if(result == ERROR) { + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + (time_t)-1, NULL, RESULT_FILE_OPEN_READ_ERROR, + "Error: Could not read host and service status information!")); + json_object_append_object(json_root, "data", + json_help(archive_json_help)); + + document_footer(); + return ERROR; + } + + /* validate arguments in URL */ + result = validate_arguments(json_root, &cgi_data, query_time); + if((result != RESULT_SUCCESS) && (result != RESULT_OPTION_IGNORED)) { + json_object_append_object(json_root, "data", + json_help(archive_json_help)); + json_object_print(json_root, 0, 1, cgi_data.strftime_format, + cgi_data.format_options); + document_footer(); + return ERROR; + } + + /* get authentication information */ + get_authentication_information(¤t_authdata); + + /* Allocate the structure for the logs */ + if((log = au_init_log()) == NULL) { + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + (time_t)-1, ¤t_authdata, RESULT_MEMORY_ALLOCATION_ERROR, + "Unable to allocate memory for log data.")); + json_object_append_object(json_root, "data", + json_help(archive_json_help)); + + document_footer(); + return ERROR; + } + + /* Return something to the user */ + switch( cgi_data.query) { + case ARCHIVE_QUERY_HELP: + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + compile_time(__DATE__, __TIME__), ¤t_authdata, + RESULT_SUCCESS, "")); + json_object_append_object(json_root, "data", + json_help(archive_json_help)); + break; + case ARCHIVE_QUERY_ALERTCOUNT: + read_archived_data(cgi_data.start_time, cgi_data.end_time, + cgi_data.backtracked_archives, AU_OBJTYPE_ALL, + AU_STATETYPE_ALL, AU_LOGTYPE_ALERT | AU_LOGTYPE_STATE, log, + &last_archive_data_update); + if(result != RESULT_OPTION_IGNORED) { + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + last_archive_data_update, ¤t_authdata, + RESULT_SUCCESS, "")); + } + else { + romp = json_get_object_member(json_root, "result"); + json_object_append_time_t(romp->value.object, "last_data_update", + last_archive_data_update); + } + json_object_append_object(json_root, "data", + json_archive_alertcount(cgi_data.format_options, + cgi_data.start_time, cgi_data.end_time, cgi_data.object_types, + cgi_data.host_name, cgi_data.service_description, + cgi_data.use_parent_host, cgi_data.parent_host, + cgi_data.use_child_host, cgi_data.child_host, + cgi_data.hostgroup, cgi_data.servicegroup, cgi_data.contact, + cgi_data.contactgroup, cgi_data.state_types, + cgi_data.host_states, cgi_data.service_states, log)); + break; + case ARCHIVE_QUERY_ALERTLIST: + read_archived_data(cgi_data.start_time, cgi_data.end_time, + cgi_data.backtracked_archives, AU_OBJTYPE_ALL, + AU_STATETYPE_ALL, AU_LOGTYPE_ALERT | AU_LOGTYPE_STATE, log, + &last_archive_data_update); + if(result != RESULT_OPTION_IGNORED) { + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + last_archive_data_update, ¤t_authdata, + RESULT_SUCCESS, "")); + } + else { + romp = json_get_object_member(json_root, "result"); + json_object_append_time_t(romp->value.object, "last_data_update", + last_archive_data_update); + } + json_object_append_object(json_root, "data", + json_archive_alertlist(cgi_data.format_options, cgi_data.start, + cgi_data.count, cgi_data.start_time, cgi_data.end_time, + cgi_data.object_types, cgi_data.host_name, + cgi_data.service_description, cgi_data.use_parent_host, + cgi_data.parent_host, cgi_data.use_child_host, + cgi_data.child_host, cgi_data.hostgroup, cgi_data.servicegroup, + cgi_data.contact, cgi_data.contactgroup, cgi_data.state_types, + cgi_data.host_states, cgi_data.service_states, log)); + break; + case ARCHIVE_QUERY_NOTIFICATIONCOUNT: + read_archived_data(cgi_data.start_time, cgi_data.end_time, + cgi_data.backtracked_archives, AU_OBJTYPE_ALL, + AU_STATETYPE_ALL, AU_LOGTYPE_NOTIFICATION, log, + &last_archive_data_update); + if(result != RESULT_OPTION_IGNORED) { + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + last_archive_data_update, ¤t_authdata, + RESULT_SUCCESS, "")); + } + else { + romp = json_get_object_member(json_root, "result"); + json_object_append_time_t(romp->value.object, "last_data_update", + last_archive_data_update); + } + json_object_append_object(json_root, "data", + json_archive_notificationcount(cgi_data.format_options, + cgi_data.start_time, cgi_data.end_time, cgi_data.object_types, + cgi_data.host_name, cgi_data.service_description, + cgi_data.use_parent_host, cgi_data.parent_host, + cgi_data.use_child_host, cgi_data.child_host, + cgi_data.hostgroup, cgi_data.servicegroup, + cgi_data.contact_name, cgi_data.contactgroup, + cgi_data.host_notification_types, + cgi_data.service_notification_types, + cgi_data.notification_method, log)); + break; + case ARCHIVE_QUERY_NOTIFICATIONLIST: + read_archived_data(cgi_data.start_time, cgi_data.end_time, + cgi_data.backtracked_archives, AU_OBJTYPE_ALL, + AU_STATETYPE_ALL, AU_LOGTYPE_NOTIFICATION, log, + &last_archive_data_update); + if(result != RESULT_OPTION_IGNORED) { + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + last_archive_data_update, ¤t_authdata, + RESULT_SUCCESS, "")); + } + else { + romp = json_get_object_member(json_root, "result"); + json_object_append_time_t(romp->value.object, "last_data_update", + last_archive_data_update); + } + json_object_append_object(json_root, "data", + json_archive_notificationlist(cgi_data.format_options, + cgi_data.start, cgi_data.count, cgi_data.start_time, + cgi_data.end_time, cgi_data.object_types, cgi_data.host_name, + cgi_data.service_description, cgi_data.use_parent_host, + cgi_data.parent_host, cgi_data.use_child_host, + cgi_data.child_host, cgi_data.hostgroup, cgi_data.servicegroup, + cgi_data.contact_name, cgi_data.contactgroup, + cgi_data.host_notification_types, + cgi_data.service_notification_types, + cgi_data.notification_method, log)); + break; + case ARCHIVE_QUERY_STATECHANGELIST: + read_archived_data(cgi_data.start_time, cgi_data.end_time, + cgi_data.backtracked_archives, cgi_data.object_type, + AU_STATETYPE_ALL, (AU_LOGTYPE_ALERT | AU_LOGTYPE_STATE), log, + &last_archive_data_update); + if(result != RESULT_OPTION_IGNORED) { + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + last_archive_data_update, ¤t_authdata, + RESULT_SUCCESS, "")); + } + else { + romp = json_get_object_member(json_root, "result"); + json_object_append_time_t(romp->value.object, "last_data_update", + last_archive_data_update); + } + json_object_append_object(json_root, "data", + json_archive_statechangelist(cgi_data.format_options, + cgi_data.start, cgi_data.count, cgi_data.start_time, + cgi_data.end_time, cgi_data.object_type, cgi_data.host_name, + cgi_data.service_description, + cgi_data.assumed_initial_host_state, + cgi_data.assumed_initial_service_state, cgi_data.state_types, + log)); + break; + case ARCHIVE_QUERY_AVAILABILITY: + switch(cgi_data.object_type) { + case AU_OBJTYPE_HOST: + case AU_OBJTYPE_HOSTGROUP: + read_archived_data(cgi_data.start_time, cgi_data.end_time, + cgi_data.backtracked_archives, AU_OBJTYPE_HOST, + cgi_data.state_types, (AU_LOGTYPE_NAGIOS | AU_LOGTYPE_ALERT + | AU_LOGTYPE_STATE | AU_LOGTYPE_DOWNTIME), log, + &last_archive_data_update); + break; + case AU_OBJTYPE_SERVICE: + case AU_OBJTYPE_SERVICEGROUP: + read_archived_data(cgi_data.start_time, cgi_data.end_time, + cgi_data.backtracked_archives, AU_OBJTYPE_SERVICE, + cgi_data.state_types, (AU_LOGTYPE_NAGIOS | AU_LOGTYPE_ALERT + | AU_LOGTYPE_STATE | AU_LOGTYPE_DOWNTIME), log, + &last_archive_data_update); + break; + } + if(result != RESULT_OPTION_IGNORED) { + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + last_archive_data_update, ¤t_authdata, + RESULT_SUCCESS, "")); + } + else { + romp = json_get_object_member(json_root, "result"); + json_object_append_time_t(romp->value.object, "last_data_update", + last_archive_data_update); + } + json_object_append_object(json_root, "data", + json_archive_availability(cgi_data.format_options, query_time, + cgi_data.start_time, cgi_data.end_time, + cgi_data.object_type, cgi_data.host_name, + cgi_data.service_description, cgi_data.hostgroup, + cgi_data.servicegroup, cgi_data.timeperiod, + cgi_data.assume_initial_state, cgi_data.assume_state_retention, + cgi_data.assume_states_during_nagios_downtime, + cgi_data.assumed_initial_host_state, + cgi_data.assumed_initial_service_state, cgi_data.state_types, + log)); + break; + default: + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + (time_t)-1, ¤t_authdata, RESULT_OPTION_MISSING, + "Error: Object Type not specified. See data for help.")); + json_object_append_object(json_root, "data", + json_help(archive_json_help)); + break; + } + + json_object_print(json_root, 0, 1, cgi_data.strftime_format, + cgi_data.format_options); + document_footer(); + + /* free all allocated memory */ + free_cgi_data( &cgi_data); + json_free_object(json_root, 1); + au_free_log(log); + free_memory(); + + return OK; + } + +void document_header() { + char date_time[MAX_DATETIME_LENGTH]; + time_t expire_time; + time_t current_time; + + time(¤t_time); + + printf("Cache-Control: no-store\r\n"); + printf("Pragma: no-cache\r\n"); + + get_time_string(¤t_time, date_time, (int)sizeof(date_time), HTTP_DATE_TIME); + printf("Last-Modified: %s\r\n", date_time); + + expire_time = (time_t)0L; + get_time_string(&expire_time, date_time, (int)sizeof(date_time), HTTP_DATE_TIME); + printf("Expires: %s\r\n", date_time); + + printf("Content-type: application/json; charset=utf-8\r\n\r\n"); + + return; + } + + +void document_footer(void) { + + printf( "\n"); + + return; + } + + +void init_cgi_data(archive_json_cgi_data *cgi_data) { + cgi_data->format_options = 0; + cgi_data->query = ARCHIVE_QUERY_INVALID; + cgi_data->start = 0; + cgi_data->count = 0; + cgi_data->object_types = AU_OBJTYPE_ALL; + cgi_data->object_type = 0; + cgi_data->state_types = AU_STATETYPE_ALL; + cgi_data->host_states = AU_STATE_HOST_ALL; + cgi_data->service_states = AU_STATE_SERVICE_ALL; + cgi_data->host_notification_types = AU_NOTIFICATION_HOST_ALL; + cgi_data->service_notification_types = AU_NOTIFICATION_SERVICE_ALL; +#if 0 + cgi_data->details = 0; +#endif + cgi_data->strftime_format = NULL; + cgi_data->start_time = (time_t)0; + cgi_data->end_time = (time_t)0; + cgi_data->parent_host_name = NULL; + cgi_data->use_parent_host = 0; + cgi_data->parent_host = NULL; + cgi_data->child_host_name = NULL; + cgi_data->use_child_host = 0; + cgi_data->child_host = NULL; + cgi_data->host_name = NULL; + cgi_data->host = NULL; + cgi_data->hostgroup_name = NULL; + cgi_data->hostgroup = NULL; + cgi_data->servicegroup_name = NULL; + cgi_data->servicegroup = NULL; + cgi_data->service_description = NULL; + cgi_data->service = NULL; + cgi_data->contact_name = NULL; + cgi_data->contact = NULL; + cgi_data->contactgroup_name = NULL; + cgi_data->contactgroup = NULL; + cgi_data->notification_method = NULL; + cgi_data->timeperiod_name = NULL; + cgi_data->timeperiod = NULL; + cgi_data->assumed_initial_host_state = AU_STATE_NO_DATA; + cgi_data->assumed_initial_service_state = AU_STATE_NO_DATA; + cgi_data->assume_initial_state = 1; + cgi_data->assume_state_retention = 1; + cgi_data->assume_states_during_nagios_downtime = 1; + cgi_data->backtracked_archives = 0; +} + +void free_cgi_data(archive_json_cgi_data *cgi_data) { + if(NULL != cgi_data->strftime_format) free( cgi_data->strftime_format); + if(NULL != cgi_data->parent_host_name) free( cgi_data->parent_host_name); + if(NULL != cgi_data->child_host_name) free( cgi_data->child_host_name); + if(NULL != cgi_data->host_name) free( cgi_data->host_name); + if(NULL != cgi_data->hostgroup_name) free( cgi_data->hostgroup_name); + if(NULL != cgi_data->servicegroup_name) free(cgi_data->servicegroup_name); + if(NULL != cgi_data->service_description) free(cgi_data->service_description); + if(NULL != cgi_data->contact_name) free(cgi_data->contact_name); + if(NULL != cgi_data->contactgroup_name) free(cgi_data->contactgroup_name); + if(NULL != cgi_data->notification_method) free(cgi_data->notification_method); + if(NULL != cgi_data->timeperiod_name) free(cgi_data->timeperiod_name); + } + + +int process_cgivars(json_object *json_root, archive_json_cgi_data *cgi_data, + time_t query_time) { + char **variables; + int result = RESULT_SUCCESS; + int x; + authdata *authinfo = NULL; /* Currently always NULL because + get_authentication_information() hasn't + been called yet, but in case we want to + use it in the future... */ + + variables = getcgivars(); + + for(x = 0; variables[x] != NULL; x++) { + /* We set these each iteration because they could change with each + iteration */ + + if(!strcmp(variables[x], "query")) { + if((result = parse_enumeration_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], valid_queries, &(cgi_data->query))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "formatoptions")) { + cgi_data->format_options = 0; + if((result = parse_bitmask_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], svm_format_options, + &(cgi_data->format_options))) != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "backtrackedarchives")) { + if((result = parse_int_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->backtracked_archives))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "start")) { + if((result = parse_int_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->start))) != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "count")) { + if((result = parse_int_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->count))) != RESULT_SUCCESS) { + break; + } + + if(cgi_data->count == 0) { + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, + valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, RESULT_OPTION_VALUE_INVALID, + "The count option value is invalid. " + "It must be an integer greater than zero")); + result = RESULT_OPTION_VALUE_INVALID; + break; + } + x++; + } + + else if(!strcmp(variables[x], "objecttype")) { + if((result = parse_enumeration_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], valid_object_types, + &(cgi_data->object_type))) != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "objecttypes")) { + cgi_data->object_types = 0; + if((result = parse_bitmask_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], valid_object_types, + &(cgi_data->object_types))) != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "availabilityobjecttype")) { + if((result = parse_enumeration_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], valid_availability_object_types, + &(cgi_data->object_type))) != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "statetypes")) { + cgi_data->state_types = 0; + if((result = parse_bitmask_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], valid_state_types, + &(cgi_data->state_types))) != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "hoststates")) { + cgi_data->host_states = 0; + if((result = parse_bitmask_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], valid_host_states, + &(cgi_data->host_states))) != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "servicestates")) { + cgi_data->service_states = 0; + if((result = parse_bitmask_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], valid_service_states, + &(cgi_data->service_states))) != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "hostnotificationtypes")) { + cgi_data->host_notification_types = 0; + if((result = parse_bitmask_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], valid_host_notification_types, + &(cgi_data->host_notification_types))) != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "servicenotificationtypes")) { + cgi_data->service_notification_types = 0; + if((result = parse_bitmask_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], valid_service_notification_types, + &(cgi_data->service_notification_types))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "parenthost")) { + if((result = parse_string_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->parent_host_name))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "childhost")) { + if((result = parse_string_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->child_host_name))) + != RESULT_SUCCESS) { + } + x++; + } + + else if(!strcmp(variables[x], "hostname")) { + if((result = parse_string_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->host_name))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "hostgroup")) { + if((result = parse_string_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->hostgroup_name))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "servicegroup")) { + if((result = parse_string_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->servicegroup_name))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "servicedescription")) { + if((result = parse_string_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->service_description))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "contactname")) { + if((result = parse_string_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->contact_name))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "contactgroup")) { + if((result = parse_string_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->contactgroup_name))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "notificationmethod")) { + if((result = parse_string_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->notification_method))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "timeperiod")) { + if((result = parse_string_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->timeperiod_name))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "assumeinitialstate")) { + if((result = parse_boolean_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->assume_initial_state))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "assumestateretention")) { + if((result = parse_boolean_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->assume_state_retention))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "assumestatesduringnagiosdowntime")) { + if((result = parse_boolean_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], + &(cgi_data->assume_states_during_nagios_downtime))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "assumedinitialhoststate")) { + if((result = parse_enumeration_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], valid_initial_host_states, + &(cgi_data->assumed_initial_host_state))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "assumedinitialservicestate")) { + if((result = parse_enumeration_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], valid_initial_service_states, + &(cgi_data->assumed_initial_service_state))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "dateformat")) { + if((result = parse_string_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->strftime_format))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "starttime")) { + if((result = parse_time_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->start_time))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "endtime")) { + if((result = parse_time_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->end_time))) != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "NagFormId")) + ++x; + + else if(!strcmp(variables[x], "")); + + else { + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, RESULT_OPTION_INVALID, + "Invalid option: '%s'.", variables[x])); + result = RESULT_OPTION_INVALID; + break; + } + } + + /* free memory allocated to the CGI variables */ + free_cgivars(variables); + + return result; + } + +int validate_arguments(json_object *json_root, archive_json_cgi_data *cgi_data, + time_t query_time) { + + int result = RESULT_SUCCESS; + host *temp_host = NULL; + hostgroup *temp_hostgroup = NULL; + servicegroup *temp_servicegroup = NULL; + contactgroup *temp_contactgroup = NULL; + timeperiod *temp_timeperiod = NULL; +#if 0 + service *temp_service = NULL; + contact *temp_contact = NULL; + command *temp_command = NULL; +#endif + authdata *authinfo = NULL; /* Currently always NULL because + get_authentication_information() hasn't + been called yet, but in case we want to + use it in the future... */ + + /* Validate that required parameters were supplied */ + switch(cgi_data->query) { + case ARCHIVE_QUERY_HELP: + break; + case ARCHIVE_QUERY_ALERTCOUNT: + case ARCHIVE_QUERY_ALERTLIST: + if((0 == cgi_data->start_time) && (0 == cgi_data->end_time)) { + result = RESULT_OPTION_MISSING; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "Start and/or end time must be supplied.")); + } + + if(!(cgi_data->object_types & (AU_OBJTYPE_HOST | AU_OBJTYPE_SERVICE))) { + result = RESULT_OPTION_MISSING; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "At least one object type must be supplied.")); + } + break; + case ARCHIVE_QUERY_NOTIFICATIONCOUNT: + case ARCHIVE_QUERY_NOTIFICATIONLIST: + if((0 == cgi_data->start_time) && (0 == cgi_data->end_time)) { + result = RESULT_OPTION_MISSING; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "Start and/or end time must be supplied.")); + } + + if(!(cgi_data->object_types & (AU_OBJTYPE_HOST | AU_OBJTYPE_SERVICE))) { + result = RESULT_OPTION_MISSING; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "At least one object type must be supplied.")); + } + break; + case ARCHIVE_QUERY_STATECHANGELIST: + if((0 == cgi_data->start_time) && (0 == cgi_data->end_time)) { + result = RESULT_OPTION_MISSING; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "Start and/or end time must be supplied.")); + } + + if(0 == cgi_data->object_type) { + result = RESULT_OPTION_MISSING; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "Object type must be supplied.")); + } + + if(NULL == cgi_data->host_name) { + result = RESULT_OPTION_MISSING; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "Host name must be supplied.")); + } + + if((AU_OBJTYPE_SERVICE == cgi_data->object_type) && + (NULL == cgi_data->service_description)) { + result = RESULT_OPTION_MISSING; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "Service description must be supplied.")); + } + + break; + case ARCHIVE_QUERY_AVAILABILITY: + if((0 == cgi_data->start_time) && (0 == cgi_data->end_time)) { + result = RESULT_OPTION_MISSING; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "Start and/or end time must be supplied.")); + } + + if(0 == cgi_data->object_type) { + result = RESULT_OPTION_MISSING; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "Availability object type must be supplied.")); + } + + break; + default: + result = RESULT_OPTION_MISSING; + json_object_append_object(json_root, "result", json_result(query_time, + THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "Missing validation for object type %u.", cgi_data->query)); + break; + } + + /* Attempt to find the host object associated with host_name. Because + we're looking at historical data, the host may no longer + exist. */ + if(NULL != cgi_data->host_name) { + cgi_data->host = find_host(cgi_data->host_name); + } + + /* Attempt to find the service object associated with host_name and + service_description. Because we're looking at historical data, + the service may no longer exist. */ + if((NULL != cgi_data->host_name) && + (NULL != cgi_data->service_description)) { + cgi_data->service = find_service(cgi_data->host_name, + cgi_data->service_description); + } + + /* Validate the requested parent host */ + if( NULL != cgi_data->parent_host_name) { + if(strcmp(cgi_data->parent_host_name, "none")) { + temp_host = find_host(cgi_data->parent_host_name); + if( NULL == temp_host) { + result = RESULT_OPTION_VALUE_INVALID; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, + valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "The parenthost '%s' could not be found.", + cgi_data->parent_host_name)); + } + else { + cgi_data->use_parent_host = 1; + cgi_data->parent_host = temp_host; + } + } + else { + cgi_data->use_parent_host = 1; + cgi_data->parent_host = NULL; + } + } + + /* Validate the requested child host */ + if( NULL != cgi_data->child_host_name) { + if(strcmp(cgi_data->child_host_name, "none")) { + temp_host = find_host(cgi_data->child_host_name); + if( NULL == temp_host) { + result = RESULT_OPTION_VALUE_INVALID; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, + valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "The childhost '%s' could not be found.", + cgi_data->child_host_name)); + } + else { + cgi_data->use_child_host = 1; + cgi_data->child_host = temp_host; + } + } + else { + cgi_data->use_child_host = 1; + cgi_data->child_host = NULL; + } + } + + /* Validate the requested hostgroup */ + if( NULL != cgi_data->hostgroup_name) { + temp_hostgroup = find_hostgroup(cgi_data->hostgroup_name); + if( NULL == temp_hostgroup) { + result = RESULT_OPTION_VALUE_INVALID; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "The hostgroup '%s' could not be found.", + cgi_data->hostgroup_name)); + } + else { + cgi_data->hostgroup = temp_hostgroup; + } + } + + /* Validate the requested servicegroup */ + if( NULL != cgi_data->servicegroup_name) { + temp_servicegroup = find_servicegroup(cgi_data->servicegroup_name); + if( NULL == temp_servicegroup) { + result = RESULT_OPTION_VALUE_INVALID; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "The servicegroup '%s' could not be found.", + cgi_data->servicegroup_name)); + } + else { + cgi_data->servicegroup = temp_servicegroup; + } + } + + /* Attempt to find the contact object associated with contact_name. + Because we're looking at historical data, the contact may + no longer exist. */ + if(NULL != cgi_data->contact_name) { + cgi_data->contact = find_contact(cgi_data->contact_name); + } + + /* Validate the requested contactgroup */ + if( NULL != cgi_data->contactgroup_name) { + temp_contactgroup = find_contactgroup(cgi_data->contactgroup_name); + if( NULL == temp_contactgroup) { + result = RESULT_OPTION_VALUE_INVALID; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "The contactgroup '%s' could not be found.", + cgi_data->contactgroup_name)); + } + else { + cgi_data->contactgroup = temp_contactgroup; + } + } + + /* Validate the requested timeperiod */ + if( NULL != cgi_data->timeperiod_name) { + temp_timeperiod = find_timeperiod(cgi_data->timeperiod_name); + if( NULL == temp_timeperiod) { + result = RESULT_OPTION_VALUE_INVALID; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "The timeperiod '%s' could not be found.", + cgi_data->timeperiod_name)); + } + else { + cgi_data->timeperiod = temp_timeperiod; + } + } + + /* Validate the requested start time is before the requested end time */ + if((cgi_data->start_time > 0) && (cgi_data->end_time > 0) && ( + cgi_data->start_time >= cgi_data->end_time)) { + result = RESULT_OPTION_VALUE_INVALID; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "The requested start time must be before the end time.")); + } + + /* If one or more host states were selected, but host objects were not, + notify the user, but continue */ + if((cgi_data->host_states != AU_STATE_HOST_ALL) && + (!(cgi_data->object_types & AU_OBJTYPE_HOST))) { + result = RESULT_OPTION_IGNORED; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, "The requested host states " + "were ignored because host objects were not selected.")); + } + /* If one or more service states were selected, but service objects + were not, notify the user but continue */ + else if((cgi_data->service_states != AU_STATE_SERVICE_ALL) && + (!(cgi_data->object_types & AU_OBJTYPE_SERVICE))) { + result = RESULT_OPTION_IGNORED; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, "The requested service states " + "were ignored because service objects were not selected.")); + } + + /* If one or more host notification types were selected, but host + objects were not, notify the user, but continue */ + if((cgi_data->host_notification_types != AU_NOTIFICATION_HOST_ALL) && + (!(cgi_data->object_types & AU_OBJTYPE_HOST))) { + result = RESULT_OPTION_IGNORED; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "The requested host notification types were ignored because host objects were not selected.")); + } + /* If one or more service notification types were selected, but + service objects were not, notify the user but continue */ + else if((cgi_data->service_notification_types != + AU_NOTIFICATION_SERVICE_ALL) && + (!(cgi_data->object_types & AU_OBJTYPE_SERVICE))) { + result = RESULT_OPTION_IGNORED; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "The requested service notification types were ignored because service objects were not selected.")); + } + + return result; + } + +int json_archive_alert_passes_selection(time_t timestamp, time_t start_time, + time_t end_time, int current_object_type, int match_object_types, + au_host *current_host, char *match_host, au_service *current_service, + char *match_service, int use_parent_host, host *parent_host, + int use_child_host, host *child_host, hostgroup *match_hostgroup, + servicegroup *match_servicegroup, contact *match_contact, + contactgroup *match_contactgroup, unsigned current_state_type, + unsigned match_state_types, unsigned current_state, + unsigned match_host_states, unsigned match_service_states) { + + host *temp_host; + host *temp_host2; + service *temp_service; + contactgroupsmember *temp_contact_groupsmember; + int found; + + if((start_time > 0) && (timestamp < start_time)) { + return 0; + } + + if((end_time > 0) && (timestamp > end_time)) { + return 0; + } + + /* Skip if we're not interested in the current state type */ + if(!(current_state_type & match_state_types)) { + return 0; + } + + switch(current_object_type) { + case AU_OBJTYPE_HOST: + /* Skip if we're not interested in hosts */ + if(!(match_object_types & AU_OBJTYPE_HOST)) { + return 0; + } + + /* Skip if user is not authorized for this host */ + if((NULL != current_host->hostp) && (FALSE == + is_authorized_for_host(current_host->hostp, + ¤t_authdata))) { + return 0; + } + + /* Skip if we're not interested in the current host state */ + if(!(current_state & match_host_states)) { + return 0; + } + + /* If a specific host name was specified, skip this host if it's + name does not match the one specified */ + if((NULL != match_host) && strcmp(current_host->name, match_host)) { + return 0; + } + + /* If a host parent was specified, skip this host if it's parent is + not the parent host specified */ + if((1 == use_parent_host) && (NULL != current_host->hostp) && + FALSE == is_host_immediate_child_of_host(parent_host, + current_host->hostp)) { + return 0; + } + + /* If a hostgroup was specified, skip this host if it is not a member + of the hostgroup specified */ + if((NULL != match_hostgroup) && (NULL != current_host->hostp) && + ( FALSE == is_host_member_of_hostgroup(match_hostgroup, + current_host->hostp))) { + return 0; + } + + /* If the contact was specified, skip this host if it does not have + the contact specified */ + if((NULL != match_contact) && (NULL != current_host->hostp) && + (FALSE == is_contact_for_host(current_host->hostp, + match_contact))) { + return 0; + } + + /* If the contact group was specified, skip this host if it does not + have the contact group specified */ + if((NULL != match_contactgroup) && (NULL != current_host->hostp)) { + found = 0; + for(temp_contact_groupsmember = + current_host->hostp->contact_groups; + temp_contact_groupsmember != NULL; + temp_contact_groupsmember = + temp_contact_groupsmember->next) { + if(!strcmp(temp_contact_groupsmember->group_name, + match_contactgroup->group_name)) { + found = 1; + break; + } + } + if(0 == found) return 0; + } + + /* If a child host was specified... */ + if((1 == use_child_host) && (NULL != current_host->hostp)) { + /* If the child host is "none", skip this host if it has children */ + if(NULL == child_host) { + for(temp_host2 = host_list; temp_host2 != NULL; + temp_host2 = temp_host2->next) { + if(TRUE == + is_host_immediate_child_of_host(current_host->hostp, + temp_host2)) { + return 0; + } + } + } + /* Otherwise, skip this host if it does not have the specified host + as a child */ + else if(FALSE == + is_host_immediate_child_of_host(current_host->hostp, + child_host)) { + return 0; + } + } + break; + case AU_OBJTYPE_SERVICE: + /* Skip if we're not interested in services */ + if(!(match_object_types & AU_OBJTYPE_SERVICE)) { + return 0; + } + + /* Skip if user is not authorized for this service */ + if((NULL != current_service->servicep) && (FALSE == + is_authorized_for_service(current_service->servicep, + ¤t_authdata))) { + return 0; + } + + /* Skip if we're not interested in the current service state */ + if(!(current_state & match_service_states)) { + return 0; + } + + /* If a specific host name was specified, skip this service if it's + host name does not match the one specified */ + if((NULL != match_host) && strcmp(current_service->host_name, + match_host)) { + return 0; + } + + /* If a specific service description was specified, skip this service + if it's description does not match the one specified */ + if((NULL != match_service) && strcmp(current_service->description, + match_service)) { + return 0; + } + + /* If a host parent was specified, skip this service if the parent + of the host associated with it is not the parent host specified */ + if((1 == use_parent_host) && (NULL != current_service->servicep)) { + temp_host = find_host(current_service->servicep->host_name); + if((NULL != temp_host) && (FALSE == + is_host_immediate_child_of_host(parent_host, temp_host))) { + return 0; + } + } + + /* If a hostgroup was specified, skip this service if it's host is not + a member of the hostgroup specified */ + if((NULL != match_hostgroup) && (NULL != current_service->servicep)) { + temp_host = find_host(current_service->servicep->host_name); + if((NULL != temp_host) && (FALSE == + is_host_member_of_hostgroup(match_hostgroup, temp_host))) { + return 0; + } + } + + /* If a servicegroup was specified, skip this service if it is not + a member of the servicegroup specified */ + if((NULL != match_servicegroup) && + (NULL != current_service->servicep)) { + temp_service = find_service(current_service->servicep->host_name, + current_service->description); + if((NULL != temp_service) && (FALSE == + is_service_member_of_servicegroup(match_servicegroup, + temp_service))) { + return 0; + } + } + + /* If the contact was specified, skip this service if it does not have + the contact specified */ + if((NULL != match_contact) && (NULL != current_service->servicep) && + (FALSE == is_contact_for_service(current_service->servicep, + match_contact))) { + return 0; + } + + /* If the contact group was specified, skip this service if it does not + have the contact group specified */ + if((NULL != match_contactgroup) && + (NULL != current_service->servicep)) { + found = 0; + for(temp_contact_groupsmember = + current_service->servicep->contact_groups; + temp_contact_groupsmember != NULL; + temp_contact_groupsmember = + temp_contact_groupsmember->next) { + if(!strcmp(temp_contact_groupsmember->group_name, + match_contactgroup->group_name)) { + found = 1; + break; + } + } + if(0 == found) return 0; + } + + /* If a child host was specified... */ + if((1 == use_child_host) && (NULL != current_service->servicep)) { + temp_host = find_host(current_service->servicep->host_name); + if(NULL != temp_host) { + /* If the child host is "none", skip this service if it's + host has children */ + if(NULL == child_host) { + for(temp_host2 = host_list; temp_host2 != NULL; + temp_host2 = temp_host2->next) { + if(TRUE == is_host_immediate_child_of_host(temp_host, + temp_host2)) { + return 0; + } + } + } + /* Otherwise, skip this service if it's host does not have the + specified host as a child */ + else if(FALSE == is_host_immediate_child_of_host(temp_host, + child_host)) { + return 0; + } + } + } + break; + } + + + return 1; + } + +json_object * json_archive_alert_selectors(unsigned format_options, int start, + int count, time_t start_time, time_t end_time, int object_types, + char *match_host, char *match_service, int use_parent_host, + host *parent_host, int use_child_host, host *child_host, + hostgroup *match_hostgroup, servicegroup *match_servicegroup, + contact *match_contact, contactgroup *match_contactgroup, + unsigned match_state_types, unsigned match_host_states, + unsigned match_service_states) { + + json_object *json_selectors; + + json_selectors = json_new_object(); + + if( start > 0) { + json_object_append_integer(json_selectors, "start", start); + } + + if( count > 0) { + json_object_append_integer(json_selectors, "count", count); + } + + if(start_time > 0) { + json_object_append_time_t(json_selectors, "starttime", start_time); + } + + if(end_time > 0) { + json_object_append_time_t(json_selectors, "endtime", end_time); + } + + if(object_types != AU_OBJTYPE_ALL) { + json_bitmask(json_selectors, format_options, "objecttypes", + object_types, valid_object_types); + } + + if(match_state_types != AU_STATETYPE_ALL) { + json_bitmask(json_selectors, format_options, "statetypes", + match_state_types, valid_state_types); + } + + if((object_types & AU_OBJTYPE_HOST) && + (match_host_states != AU_STATE_HOST_ALL)) { + json_bitmask(json_selectors, format_options, "hoststates", + match_host_states, valid_host_states); + } + + if((object_types & AU_OBJTYPE_SERVICE) && + (match_service_states != AU_STATE_SERVICE_ALL)) { + json_bitmask(json_selectors, format_options, "servicestates", + match_service_states, valid_service_states); + } + + if(NULL != match_host) { + json_object_append_string(json_selectors, "hostname", &percent_escapes, + match_host); + } + + if(NULL != match_service) { + json_object_append_string(json_selectors, "servicedescription", + &percent_escapes, match_service); + } + + if(1 == use_parent_host) { + json_object_append_string(json_selectors, "parenthost", + &percent_escapes, + ( NULL == parent_host ? "none" : parent_host->name)); + } + + if( 1 == use_child_host) { + json_object_append_string(json_selectors, "childhost", &percent_escapes, + ( NULL == child_host ? "none" : child_host->name)); + } + + if(NULL != match_hostgroup) { + json_object_append_string(json_selectors, "hostgroup", &percent_escapes, + match_hostgroup->group_name); + } + + if((object_types & AU_OBJTYPE_SERVICE) && (NULL != match_servicegroup)) { + json_object_append_string(json_selectors, "servicegroup", + &percent_escapes, match_servicegroup->group_name); + } + + if(NULL != match_contact) { + json_object_append_string(json_selectors, "contact", &percent_escapes, + match_contact->name); + } + + if(NULL != match_contactgroup) { + json_object_append_string(json_selectors, "contactgroup", + &percent_escapes, match_contactgroup->group_name); + } + + return json_selectors; + } + +json_object * json_archive_alertcount(unsigned format_options, + time_t start_time, time_t end_time, int object_types, + char *match_host, char *match_service, int use_parent_host, + host *parent_host, int use_child_host, host *child_host, + hostgroup *match_hostgroup, servicegroup *match_servicegroup, + contact *match_contact, contactgroup *match_contactgroup, + unsigned match_state_types, unsigned match_host_states, + unsigned match_service_states, au_log *log) { + + json_object *json_data; + au_node *temp_node; + au_log_entry *temp_entry; + au_log_alert *temp_alert_log; + au_host *temp_host = NULL; + au_service *temp_service = NULL; + int count = 0; + + json_data = json_new_object(); + json_object_append_object(json_data, "selectors", + json_archive_alert_selectors(format_options, 0, 0, start_time, + end_time, object_types, match_host, match_service, use_parent_host, + parent_host, use_child_host, child_host, match_hostgroup, + match_servicegroup, match_contact, match_contactgroup, + match_state_types, match_host_states, match_service_states)); + + for(temp_node = log->entry_list->head; temp_node != NULL; + temp_node = temp_node->next) { + + temp_entry = (au_log_entry *)temp_node->data; + + /* Skip all but alert type messages */ + if(AU_LOGTYPE_ALERT != temp_entry->entry_type) continue; + + /* Get the host/service object */ + temp_alert_log = (au_log_alert *)temp_entry->entry; + switch(temp_alert_log->obj_type) { + case AU_OBJTYPE_HOST: + temp_host = (au_host *)temp_alert_log->object; + temp_service = NULL; + break; + case AU_OBJTYPE_SERVICE: + temp_host = NULL; + temp_service = (au_service *)temp_alert_log->object; + break; + } + + /* Skip anything that does not pass the alert selection criteria */ + if(json_archive_alert_passes_selection(temp_entry->timestamp, + start_time, end_time, temp_alert_log->obj_type, + object_types, temp_host, match_host, temp_service, + match_service, use_parent_host, parent_host, use_child_host, + child_host, match_hostgroup, match_servicegroup, + match_contact, match_contactgroup, temp_alert_log->state_type, + match_state_types, temp_alert_log->state, match_host_states, + match_service_states) == 0) { + continue; + } + + count++; + } + json_object_append_integer(json_data, "count", count); + + return json_data; + } + +json_object * json_archive_alertlist(unsigned format_options, int start, + int count, time_t start_time, time_t end_time, int object_types, + char *match_host, char *match_service, int use_parent_host, + host *parent_host, int use_child_host, host *child_host, + hostgroup *match_hostgroup, servicegroup *match_servicegroup, + contact *match_contact, contactgroup *match_contactgroup, + unsigned match_state_types, unsigned match_host_states, + unsigned match_service_states, au_log *log) { + + json_object *json_data; + json_array *json_alertlist; + json_object *json_alert_details; + au_node *temp_node; + au_log_entry *temp_entry; + au_log_alert *temp_alert_log; + au_host *temp_host = NULL; + au_service *temp_service = NULL; + int current = 0; + int counted = 0; + + json_data = json_new_object(); + json_object_append_object(json_data, "selectors", + json_archive_alert_selectors(format_options, start, count, + start_time, end_time, object_types, match_host, match_service, + use_parent_host, parent_host, use_child_host, child_host, + match_hostgroup, match_servicegroup, match_contact, + match_contactgroup, match_state_types, match_host_states, + match_service_states)); + + json_alertlist = json_new_array(); + + for(temp_node = log->entry_list->head; temp_node != NULL; + temp_node = temp_node->next) { + + temp_entry = (au_log_entry *)temp_node->data; + + /* Skip all but alert type messages */ + if(AU_LOGTYPE_ALERT != temp_entry->entry_type) continue; + + /* Get the host/service object */ + temp_alert_log = (au_log_alert *)temp_entry->entry; + switch(temp_alert_log->obj_type) { + case AU_OBJTYPE_HOST: + temp_host = (au_host *)temp_alert_log->object; + temp_service = NULL; + break; + case AU_OBJTYPE_SERVICE: + temp_host = NULL; + temp_service = (au_service *)temp_alert_log->object; + break; + } + + /* Skip anything that does not pass the alert selection criteria */ + if(json_archive_alert_passes_selection(temp_entry->timestamp, + start_time, end_time, temp_alert_log->obj_type, + object_types, temp_host, match_host, temp_service, + match_service, use_parent_host, parent_host, use_child_host, + child_host, match_hostgroup, match_servicegroup, + match_contact, match_contactgroup, temp_alert_log->state_type, + match_state_types, temp_alert_log->state, match_host_states, + match_service_states) == 0) { + continue; + } + + /* If the current item passes the start and limit tests, display it */ + if( passes_start_and_count_limits(start, count, current, counted)) { + json_alert_details = json_new_object(); + json_archive_alert_details(json_alert_details, format_options, + temp_entry->timestamp, (au_log_alert *)temp_entry->entry); + json_array_append_object(json_alertlist, json_alert_details); + counted++; + } + current++; + } + + json_object_append_array(json_data, "alertlist", json_alertlist); + + return json_data; + } + +void json_archive_alert_details(json_object *json_details, + unsigned format_options, time_t timestamp, au_log_alert *temp_alert) { + + au_host *temp_host; + au_service *temp_service; + + json_object_append_time_t(json_details, "timestamp", timestamp); + + json_enumeration(json_details, format_options, "object_type", + temp_alert->obj_type, svm_au_object_types); + + switch(temp_alert->obj_type) { + case AU_OBJTYPE_HOST: + temp_host = (au_host *)temp_alert->object; + json_object_append_string(json_details, "name", &percent_escapes, + temp_host->name); + break; + case AU_OBJTYPE_SERVICE: + temp_service = (au_service *)temp_alert->object; + json_object_append_string(json_details, "host_name", &percent_escapes, + temp_service->host_name); + json_object_append_string(json_details, "description", &percent_escapes, + temp_service->description); + break; + } + + json_enumeration(json_details, format_options, "state_type", + temp_alert->state_type, svm_au_state_types); + json_enumeration(json_details, format_options, "state", temp_alert->state, + svm_au_states); + json_object_append_string(json_details, "plugin_output", &percent_escapes, + temp_alert->plugin_output); + } + +int json_archive_notification_passes_selection(time_t timestamp, + time_t start_time, time_t end_time, int current_object_type, + int match_object_types, au_host *current_host, char *match_host, + au_service *current_service, char *match_service, int use_parent_host, + host *parent_host, int use_child_host, host *child_host, + hostgroup *match_hostgroup, servicegroup *match_servicegroup, + au_contact *current_contact, char *match_contact, + contactgroup *match_contactgroup, + unsigned current_notification_type, + unsigned match_host_notification_types, + unsigned match_service_notification_types, + char *current_notification_method, char *match_notification_method) { + + host *temp_host; + host *temp_host2; + service *temp_service; + contactgroupsmember *temp_contact_groupsmember; + int found; + + if((start_time > 0) && (timestamp < start_time)) { + return 0; + } + + if((end_time > 0) && (timestamp > end_time)) { + return 0; + } + + /* If the contact was specified, skip this notification if it does not have + the contact specified */ + if((NULL != match_contact) && (NULL != current_contact) && + strcmp(current_contact->name, match_contact)) { + return 0; + } + + /* If the notification method was specified, skip this notification if + it does not have the method specified */ + if((NULL != match_notification_method) && + (NULL != current_notification_method) && + strcmp(current_notification_method, match_notification_method)) { + return 0; + } + + switch(current_object_type) { + case AU_OBJTYPE_HOST: + /* Skip if we're not interested in hosts */ + if(!(match_object_types & AU_OBJTYPE_HOST)) { + return 0; + } + + /* Skip if user is not authorized for this host */ + if((NULL != current_host->hostp) && (FALSE == + is_authorized_for_host(current_host->hostp, + ¤t_authdata))) { + return 0; + } + + /* Skip if we're not interested in the current host notification type */ + if(!(current_notification_type & match_host_notification_types)) { + return 0; + } + + /* If a specific host name was specified, skip this host if it's + name does not match the one specified */ + if((NULL != match_host) && strcmp(current_host->name, match_host)) { + return 0; + } + + /* If a host parent was specified, skip this host if it's parent is + not the parent host specified */ + if((1 == use_parent_host) && (NULL != current_host->hostp) && + FALSE == is_host_immediate_child_of_host(parent_host, + current_host->hostp)) { + return 0; + } + + /* If a hostgroup was specified, skip this host if it is not a member + of the hostgroup specified */ + if((NULL != match_hostgroup) && (NULL != current_host->hostp) && + ( FALSE == is_host_member_of_hostgroup(match_hostgroup, + current_host->hostp))) { + return 0; + } + + /* If the contact group was specified, skip this host if it does not + have the contact group specified */ + if((NULL != match_contactgroup) && (NULL != current_host->hostp)) { + found = 0; + for(temp_contact_groupsmember = + current_host->hostp->contact_groups; + temp_contact_groupsmember != NULL; + temp_contact_groupsmember = + temp_contact_groupsmember->next) { + if(!strcmp(temp_contact_groupsmember->group_name, + match_contactgroup->group_name)) { + found = 1; + break; + } + } + if(0 == found) return 0; + } + + /* If a child host was specified... */ + if((1 == use_child_host) && (NULL != current_host->hostp)) { + /* If the child host is "none", skip this host if it has children */ + if(NULL == child_host) { + for(temp_host2 = host_list; temp_host2 != NULL; + temp_host2 = temp_host2->next) { + if(TRUE == + is_host_immediate_child_of_host(current_host->hostp, + temp_host2)) { + return 0; + } + } + } + /* Otherwise, skip this host if it does not have the specified host + as a child */ + else if(FALSE == + is_host_immediate_child_of_host(current_host->hostp, + child_host)) { + return 0; + } + } + break; + case AU_OBJTYPE_SERVICE: + /* Skip if we're not interested in services */ + if(!(match_object_types & AU_OBJTYPE_SERVICE)) { + return 0; + } + + /* Skip if user is not authorized for this service */ + if((NULL != current_service->servicep) && (FALSE == + is_authorized_for_service(current_service->servicep, + ¤t_authdata))) { + return 0; + } + + /* Skip if we're not interested in the current service notification + type */ + if(!(current_notification_type & match_service_notification_types)) { + return 0; + } + + /* If a specific host name was specified, skip this service if it's + host name does not match the one specified */ + if((NULL != match_host) && strcmp(current_service->host_name, + match_host)) { + return 0; + } + + /* If a specific service description was specified, skip this service + if it's description does not match the one specified */ + if((NULL != match_service) && strcmp(current_service->description, + match_service)) { + return 0; + } + + /* If a host parent was specified, skip this service if the parent + of the host associated with it is not the parent host specified */ + if((1 == use_parent_host) && (NULL != current_service->servicep)) { + temp_host = find_host(current_service->servicep->host_name); + if((NULL != temp_host) && (FALSE == + is_host_immediate_child_of_host(parent_host, temp_host))) { + return 0; + } + } + + /* If a hostgroup was specified, skip this service if it's host is not + a member of the hostgroup specified */ + if((NULL != match_hostgroup) && (NULL != current_service->servicep)) { + temp_host = find_host(current_service->servicep->host_name); + if((NULL != temp_host) && (FALSE == + is_host_member_of_hostgroup(match_hostgroup, temp_host))) { + return 0; + } + } + + /* If a servicegroup was specified, skip this service if it is not + a member of the servicegroup specified */ + if((NULL != match_servicegroup) && + (NULL != current_service->servicep)) { + temp_service = find_service(current_service->servicep->host_name, + current_service->description); + if((NULL != temp_service) && (FALSE == + is_service_member_of_servicegroup(match_servicegroup, + temp_service))) { + return 0; + } + } + + /* If the contact group was specified, skip this service if it does not + have the contact group specified */ + if((NULL != match_contactgroup) && + (NULL != current_service->servicep)) { + found = 0; + for(temp_contact_groupsmember = + current_service->servicep->contact_groups; + temp_contact_groupsmember != NULL; + temp_contact_groupsmember = + temp_contact_groupsmember->next) { + if(!strcmp(temp_contact_groupsmember->group_name, + match_contactgroup->group_name)) { + found = 1; + break; + } + } + if(0 == found) return 0; + } + + /* If a child host was specified... */ + if((1 == use_child_host) && (NULL != current_service->servicep)) { + temp_host = find_host(current_service->servicep->host_name); + if(NULL != temp_host) { + /* If the child host is "none", skip this service if it's + host has children */ + if(NULL == child_host) { + for(temp_host2 = host_list; temp_host2 != NULL; + temp_host2 = temp_host2->next) { + if(TRUE == is_host_immediate_child_of_host(temp_host, + temp_host2)) { + return 0; + } + } + } + /* Otherwise, skip this service if it's host does not have the + specified host as a child */ + else if(FALSE == is_host_immediate_child_of_host(temp_host, + child_host)) { + return 0; + } + } + } + break; + } + + return 1; + } + +json_object * json_archive_notification_selectors(unsigned format_options, + int start, int count, time_t start_time, time_t end_time, + int match_object_types, char *match_host, char *match_service, + int use_parent_host, host *parent_host, int use_child_host, + host *child_host, hostgroup *match_hostgroup, + servicegroup *match_servicegroup, char *match_contact, + contactgroup *match_contactgroup, + unsigned match_host_notification_types, + unsigned match_service_notification_types, + char *match_notification_method) { + + json_object *json_selectors; + + json_selectors = json_new_object(); + + if( start > 0) { + json_object_append_integer(json_selectors, "start", start); + } + + if( count > 0) { + json_object_append_integer(json_selectors, "count", count); + } + + if(start_time > 0) { + json_object_append_time_t(json_selectors, "starttime", start_time); + } + + if(end_time > 0) { + json_object_append_time_t(json_selectors, "endtime", end_time); + } + + if(match_object_types != AU_OBJTYPE_ALL) { + json_bitmask(json_selectors, format_options, "objecttypes", + match_object_types, valid_object_types); + } + + if((match_object_types & AU_OBJTYPE_HOST) && + (match_host_notification_types != AU_NOTIFICATION_HOST_ALL)) { + json_bitmask(json_selectors, format_options, "hostnotificationtypes", + match_host_notification_types, + valid_host_notification_types); + } + + if((match_object_types & AU_OBJTYPE_SERVICE) && + (match_service_notification_types != AU_NOTIFICATION_SERVICE_ALL)) { + json_bitmask(json_selectors, format_options, "servicenotificationtypes", + match_service_notification_types, + valid_service_notification_types); + } + + if(NULL != match_host) { + json_object_append_string(json_selectors, "hostname", &percent_escapes, + match_host); + } + + if(NULL != match_service) { + json_object_append_string(json_selectors, "servicedescription", + &percent_escapes, match_service); + } + + if(1 == use_parent_host) { + json_object_append_string(json_selectors, "parenthost", + &percent_escapes, + ( NULL == parent_host ? "none" : parent_host->name)); + } + + if( 1 == use_child_host) { + json_object_append_string(json_selectors, "childhost", + &percent_escapes, + ( NULL == child_host ? "none" : child_host->name)); + } + + if(NULL != match_hostgroup) { + json_object_append_string(json_selectors, "hostgroup", &percent_escapes, + match_hostgroup->group_name); + } + + if((match_object_types & AU_OBJTYPE_SERVICE) && + (NULL != match_servicegroup)) { + json_object_append_string(json_selectors, "servicegroup", + &percent_escapes, match_servicegroup->group_name); + } + + if(NULL != match_contact) { + json_object_append_string(json_selectors, "contact", &percent_escapes, + match_contact); + } + + if(NULL != match_contactgroup) { + json_object_append_string(json_selectors, "contactgroup", + &percent_escapes, match_contactgroup->group_name); + } + + if(NULL != match_notification_method) { + json_object_append_string(json_selectors, "notificationmethod", + &percent_escapes, match_notification_method); + } + + return json_selectors; + } + +json_object * json_archive_notificationcount(unsigned format_options, + time_t start_time, time_t end_time, int match_object_types, + char *match_host, char *match_service, int use_parent_host, + host *parent_host, int use_child_host, host *child_host, + hostgroup *match_hostgroup, servicegroup *match_servicegroup, + char *match_contact, contactgroup *match_contactgroup, + unsigned match_host_notification_types, + unsigned match_service_notification_types, + char *match_notification_method, au_log *log) { + + json_object *json_data; + au_node *temp_node; + au_log_entry *temp_entry; + au_log_notification *temp_notification_log; + au_host *temp_host = NULL; + au_service *temp_service = NULL; + int count = 0; + + json_data = json_new_object(); + json_object_append_object(json_data, "selectors", + json_archive_notification_selectors(format_options, 0, 0, + start_time, end_time, match_object_types, match_host, + match_service, use_parent_host, parent_host, use_child_host, + child_host, match_hostgroup, match_servicegroup, match_contact, + match_contactgroup, match_host_notification_types, + match_service_notification_types, match_notification_method)); + + for(temp_node = log->entry_list->head; temp_node != NULL; + temp_node = temp_node->next) { + + temp_entry = (au_log_entry *)temp_node->data; + + /* Skip all but notification type messages */ + if(AU_LOGTYPE_NOTIFICATION != temp_entry->entry_type) continue; + + /* Get the host/service object */ + temp_notification_log = (au_log_notification *)temp_entry->entry; + switch(temp_notification_log->obj_type) { + case AU_OBJTYPE_HOST: + temp_host = (au_host *)temp_notification_log->object; + temp_service = NULL; + break; + case AU_OBJTYPE_SERVICE: + temp_host = NULL; + temp_service = (au_service *)temp_notification_log->object; + break; + } + + /* Skip anything that does not pass the notification selection + criteria */ + if(json_archive_notification_passes_selection(temp_entry->timestamp, + start_time, end_time, temp_notification_log->obj_type, + match_object_types, temp_host, match_host, temp_service, + match_service, use_parent_host, parent_host, use_child_host, + child_host, match_hostgroup, match_servicegroup, + temp_notification_log->contact, match_contact, + match_contactgroup, temp_notification_log->notification_type, + match_host_notification_types, + match_service_notification_types, temp_notification_log->method, match_notification_method) == 0) { + continue; + } + + count++; + } + json_object_append_integer(json_data, "count", count); + + return json_data; + } + +json_object * json_archive_notificationlist(unsigned format_options, int start, + int count, time_t start_time, time_t end_time, int match_object_types, + char *match_host, char *match_service, int use_parent_host, + host *parent_host, int use_child_host, host *child_host, + hostgroup *match_hostgroup, servicegroup *match_servicegroup, + char *match_contact, contactgroup *match_contactgroup, + unsigned match_host_notification_types, + unsigned match_service_notification_types, + char *match_notification_method, au_log *log) { + + json_object *json_data; + json_array *json_notificationlist; + json_object *json_notification_details; + au_node *temp_node; + au_log_entry *temp_entry; + au_log_notification *temp_notification_log; + au_host *temp_host = NULL; + au_service *temp_service = NULL; + int current = 0; + int counted = 0; + + json_data = json_new_object(); + json_object_append_object(json_data, "selectors", + json_archive_notification_selectors(format_options, start, count, + start_time, end_time, match_object_types, match_host, + match_service, use_parent_host, parent_host, use_child_host, + child_host, match_hostgroup, match_servicegroup, match_contact, + match_contactgroup, match_host_notification_types, + match_service_notification_types, match_notification_method)); + + json_notificationlist = json_new_array(); + + for(temp_node = log->entry_list->head; temp_node != NULL; + temp_node = temp_node->next) { + + temp_entry = (au_log_entry *)temp_node->data; + + /* Skip all but notification type messages */ + if(AU_LOGTYPE_NOTIFICATION != temp_entry->entry_type) continue; + + /* Get the host/service object */ + temp_notification_log = (au_log_notification *)temp_entry->entry; + switch(temp_notification_log->obj_type) { + case AU_OBJTYPE_HOST: + temp_host = (au_host *)temp_notification_log->object; + temp_service = NULL; + break; + case AU_OBJTYPE_SERVICE: + temp_host = NULL; + temp_service = (au_service *)temp_notification_log->object; + break; + } + + /* Skip anything that does not pass the notification selection + criteria */ + if(json_archive_notification_passes_selection(temp_entry->timestamp, + start_time, end_time, temp_notification_log->obj_type, + match_object_types, temp_host, match_host, temp_service, + match_service, use_parent_host, parent_host, use_child_host, + child_host, match_hostgroup, match_servicegroup, + temp_notification_log->contact, match_contact, + match_contactgroup, temp_notification_log->notification_type, + match_host_notification_types, + match_service_notification_types, temp_notification_log->method, + match_notification_method) == 0) { + continue; + } + + /* If the current item passes the start and limit tests, display it */ + if( passes_start_and_count_limits(start, count, current, counted)) { + json_notification_details = json_new_object(); + json_archive_notification_details(json_notification_details, + format_options, temp_entry->timestamp, + (au_log_notification *)temp_entry->entry); + json_array_append_object(json_notificationlist, + json_notification_details); + counted++; + } + current++; + } + + json_object_append_array(json_data, "notificationlist", + json_notificationlist); + + return json_data; + } + +void json_archive_notification_details(json_object *json_details, + unsigned format_options, time_t timestamp, + au_log_notification *temp_notification) { + + au_host *temp_host; + au_service *temp_service; + + json_object_append_time_t(json_details, "timestamp", timestamp); + + json_enumeration(json_details, format_options, "object_type", + temp_notification->obj_type, + svm_au_object_types); + + switch(temp_notification->obj_type) { + case AU_OBJTYPE_HOST: + temp_host = (au_host *)temp_notification->object; + json_object_append_string(json_details, "name", &percent_escapes, + temp_host->name); + break; + case AU_OBJTYPE_SERVICE: + temp_service = (au_service *)temp_notification->object; + json_object_append_string(json_details, "host_name", &percent_escapes, + temp_service->host_name); + json_object_append_string(json_details, "description", &percent_escapes, + temp_service->description); + break; + } + + json_object_append_string(json_details, "contact", &percent_escapes, + temp_notification->contact->name); + json_enumeration(json_details, format_options, "notification_type", + temp_notification->notification_type, svm_au_notification_types); + json_object_append_string(json_details, "method", &percent_escapes, + temp_notification->method); + json_object_append_string(json_details, "message", &percent_escapes, + temp_notification->message); + } + +int json_archive_statechange_passes_selection(time_t timestamp, + time_t end_time, int current_object_type, + int match_object_type, au_host *current_host, char *match_host, + au_service *current_service, char *match_service, + unsigned current_state_type, unsigned match_state_types) { + + if((end_time > 0) && (timestamp > end_time)) { + return 0; + } + + /* Skip if we're not interested in the current state type */ + if(!(current_state_type & match_state_types)) { + return 0; + } + + switch(current_object_type) { + case AU_OBJTYPE_HOST: + /* Skip if we're not interested in hosts */ + if(match_object_type != AU_OBJTYPE_HOST) { + return 0; + } + + /* Skip if user is not authorized for this host */ + if((NULL != current_host->hostp) && (FALSE == + is_authorized_for_host(current_host->hostp, + ¤t_authdata))) { + return 0; + } + + /* If a specific host name was specified, skip this host if it's + name does not match the one specified */ + if((NULL != match_host) && (NULL != current_host) && + strcmp(current_host->name, match_host)) { + return 0; + } + + break; + + case AU_OBJTYPE_SERVICE: + /* Skip if we're not interested in services */ + if(match_object_type != AU_OBJTYPE_SERVICE) { + return 0; + } + + /* Skip if user is not authorized for this service */ + if((NULL != current_service->servicep) && (FALSE == + is_authorized_for_service(current_service->servicep, + ¤t_authdata))) { + return 0; + } + + /* If a specific service was specified, skip this service if it's + host name and service description do not match the one specified */ + if((NULL != match_host) && (NULL != match_service) && + (NULL != current_service) && + ( strcmp(current_service->host_name, match_host) || + strcmp(current_service->description, match_service))) { + return 0; + } + + break; + } + + return 1; + } + +json_object *json_archive_statechange_selectors(unsigned format_options, + int start, int count, time_t start_time, time_t end_time, + int object_type, char *host_name, char *service_description, + unsigned state_types) { + + json_object *json_selectors; + + json_selectors = json_new_object(); + + if( start > 0) { + json_object_append_integer(json_selectors, "start", start); + } + + if( count > 0) { + json_object_append_integer(json_selectors, "count", count); + } + + if(start_time > 0) { + json_object_append_time_t(json_selectors, "starttime", start_time); + } + + if(end_time > 0) { + json_object_append_time_t(json_selectors, "endtime", end_time); + } + + if(NULL != host_name) { + json_object_append_string(json_selectors, "hostname", &percent_escapes, + host_name); + } + + if(NULL != service_description) { + json_object_append_string(json_selectors, "servicedescription", + &percent_escapes, service_description); + } + + if(state_types != AU_STATETYPE_ALL) { + json_bitmask(json_selectors, format_options, "statetypes", state_types, + valid_state_types); + } + + return json_selectors; + } + +json_object *json_archive_statechangelist(unsigned format_options, + int start, int count, time_t start_time, time_t end_time, + int object_type, char *host_name, char *service_description, + int assumed_initial_host_state, int assumed_initial_service_state, + unsigned state_types, au_log *log) { + + json_object *json_data; + json_array *json_statechangelist; + json_object *json_statechange_details; + au_node *temp_node; + int initial_host_state = AU_STATE_NO_DATA; + int initial_service_state = AU_STATE_NO_DATA; + au_log_entry *temp_entry = NULL; + au_log_alert *temp_state_log = NULL; + au_log_alert *start_log = NULL; + au_log_alert *end_log = NULL; + au_host *temp_host = NULL; + au_service *temp_service = NULL; + int have_seen_first_entry = 0; + int current = 0; + int counted = 0; + + if(assumed_initial_host_state != AU_STATE_NO_DATA) + initial_host_state = assumed_initial_host_state; + if(assumed_initial_service_state != AU_STATE_NO_DATA) + initial_service_state = assumed_initial_service_state; + + json_data = json_new_object(); + json_object_append_object(json_data, "selectors", + json_archive_statechange_selectors(format_options, start, count, + start_time, end_time, object_type, host_name, service_description, + state_types)); + + json_statechangelist = json_new_array(); + + for(temp_node = log->entry_list->head; temp_node != NULL; + temp_node = temp_node->next) { + + /* Skip all but notification type messages */ + temp_entry = (au_log_entry *)temp_node->data; + if(!(temp_entry->entry_type & (AU_LOGTYPE_STATE | AU_LOGTYPE_ALERT))) { + continue; + } + + /* Get the host/service object */ + temp_state_log = (au_log_alert *)temp_entry->entry; + switch(temp_state_log->obj_type) { + case AU_OBJTYPE_HOST: + temp_host = (au_host *)temp_state_log->object; + temp_service = NULL; + break; + case AU_OBJTYPE_SERVICE: + temp_host = NULL; + temp_service = (au_service *)temp_state_log->object; + break; + } + + /* Skip any entries not passing the selectors */ + if(json_archive_statechange_passes_selection(temp_entry->timestamp, + end_time, temp_state_log->obj_type, + object_type, temp_host, host_name, temp_service, + service_description, temp_state_log->state_type, + state_types) == 0) { + continue; + } + + if((start_time > 0) && (temp_entry->timestamp < start_time)) { + /* If we're before the start time and no initial assumed state + was provided, record the state to be used as the initial + state */ + switch(temp_state_log->obj_type) { + case AU_OBJTYPE_HOST: + if(AU_STATE_NO_DATA == assumed_initial_host_state) + initial_host_state = temp_state_log->state; + break; + case AU_OBJTYPE_SERVICE: + if(AU_STATE_NO_DATA == assumed_initial_service_state) + initial_service_state = temp_state_log->state; + break; + } + continue; + } + else if(0 == have_seen_first_entry) { + /* When we get to the first entry after the start, inject a + pseudo entry with the initial state */ + switch(object_type) { + case AU_OBJTYPE_HOST: + start_log = au_create_alert_or_state_log(object_type, + temp_host, AU_STATETYPE_HARD, initial_host_state, + "Initial Host Pseudo-State"); + break; + case AU_OBJTYPE_SERVICE: + start_log = au_create_alert_or_state_log(object_type, + temp_service, AU_STATETYPE_HARD, initial_service_state, + "Initial Service Pseudo-State"); + break; + } + if(start_log != NULL) { + json_statechange_details = json_new_object(); + json_archive_alert_details(json_statechange_details, + format_options, start_time, start_log); + json_array_append_object(json_statechangelist, + json_statechange_details); + au_free_alert_log(start_log); + } + have_seen_first_entry = 1; + } +#if 0 + else { + /* Ignore ALERT logs if their state is not different from the + previous state */ + switch(object_type) { + case AU_OBJTYPE_HOST: +// if((temp_entry->entry_type & (AU_LOGTYPE_ALERT | +// AU_LOGTYPE_STATE_INITIAL)) && + if((temp_entry->entry_type & AU_LOGTYPE_ALERT) && + (last_host_state == temp_state_log->state)) { + continue; + } + last_host_state = temp_state_log->state; + break; + case AU_OBJTYPE_SERVICE: +// if((temp_entry->entry_type & (AU_LOGTYPE_ALERT | +// AU_LOGTYPE_STATE_INITIAL)) && + if((temp_entry->entry_type & AU_LOGTYPE_ALERT) && + (last_service_state == temp_state_log->state)) { + continue; + } + last_service_state = temp_state_log->state; + break; + } + } +#endif + + /* If the current item passes the start and limit tests, display it */ + if( passes_start_and_count_limits(start, count, current, counted)) { + json_statechange_details = json_new_object(); + json_archive_alert_details(json_statechange_details, + format_options, temp_entry->timestamp, temp_state_log); + json_array_append_object(json_statechangelist, + json_statechange_details); + counted++; + } + current++; + } + + /* Inject a pseudo entry with the final state */ + switch(object_type) { + case AU_OBJTYPE_HOST: + temp_host = au_find_host(log->hosts, host_name); + if(NULL != temp_host) { + end_log = au_create_alert_or_state_log(object_type, + temp_host, AU_STATETYPE_HARD, temp_state_log->state, + "Final Host Pseudo-State"); + } + break; + case AU_OBJTYPE_SERVICE: + temp_service = au_find_service(log->hosts, host_name, + service_description); + if(NULL != temp_service) { + end_log = au_create_alert_or_state_log(object_type, + temp_service, AU_STATETYPE_HARD, temp_state_log->state, + "Final Service Pseudo-State"); + } + break; + } + if(end_log != NULL) { + json_statechange_details = json_new_object(); + json_archive_alert_details(json_statechange_details, format_options, + end_time, end_log); + json_array_append_object(json_statechangelist, + json_statechange_details); + au_free_alert_log(end_log); + } + + json_object_append_array(json_data, "statechangelist", + json_statechangelist); + + return json_data; + } + +/* + Return the initial state of Nagios itself. + */ +int get_initial_nagios_state(au_linked_list *log_entries, time_t start_time, + time_t end_time) { + + au_node *temp_node; + au_log_entry *current_log_entry; + au_log_nagios *temp_nagios_log; + int initial_state = AU_STATE_NO_DATA; + + for(temp_node = log_entries->head; temp_node != NULL; + temp_node = temp_node->next) { + current_log_entry = (au_log_entry *)temp_node->data; + if(current_log_entry->timestamp < start_time) { + /* Any log entries prior to the start time tell us something + about the initial state of Nagios so look at all of them */ + switch(current_log_entry->entry_type) { + case AU_LOGTYPE_NAGIOS: + /* If the log is a Nagios start or stop log, that is the + current program state */ + temp_nagios_log = (au_log_nagios *)current_log_entry->entry; + initial_state = temp_nagios_log->type; + break; + default: + /* Any other log indicates that Nagios is running */ + initial_state = AU_STATE_PROGRAM_START; + break; + } + } + else { + if(AU_STATE_NO_DATA != initial_state) { + /* Once we cross the threshold of the start time, if we have + an initial state, that is THE initial state */ + return initial_state; + } + else { + /* Otherwise the first log encountered tells us the initial + state of Nagios */ + switch(current_log_entry->entry_type) { + case AU_LOGTYPE_NAGIOS: + /* If the log is a Nagios start or stop log, that is + opposite the initial state */ + temp_nagios_log = (au_log_nagios *)current_log_entry->entry; + switch(temp_nagios_log->type) { + case AU_STATE_PROGRAM_START: + return AU_STATE_PROGRAM_END; + break; + case AU_STATE_PROGRAM_END: + return AU_STATE_PROGRAM_START; + break; + } + break; + default: + /* Any other log indicates that Nagios was running at + the start time */ + return AU_STATE_PROGRAM_START; + break; + } + } + } + } + /* If we reach this point, we are in bad shape because we had nothing + in the logs and the initial state should still be AU_STATE_NO_DATA, + which we return as an error indication */ + return initial_state; + } + +/* + Return the initial downtime state of the host or service. + */ +int get_initial_downtime_state(au_linked_list *log_entries, time_t start_time, + time_t end_time) { + + au_node *temp_node; + au_log_entry *current_log_entry; + au_log_downtime *temp_downtime_log; + int initial_state = AU_STATE_NO_DATA; + + for(temp_node = log_entries->head; temp_node != NULL; + temp_node = temp_node->next) { + current_log_entry = (au_log_entry *)temp_node->data; + if(current_log_entry->timestamp < start_time) { + /* Any downtime log prior to the start time may indicate the + initial downtime state so look at all of them */ + if(AU_LOGTYPE_DOWNTIME == current_log_entry->entry_type) { + temp_downtime_log = (au_log_downtime *)current_log_entry->entry; + initial_state = temp_downtime_log->downtime_type; + } + } + else if(current_log_entry->timestamp <= end_time) { + if(AU_STATE_NO_DATA != initial_state) { + /* Once we cross the start time, if we have a downtime state, + we have THE initial downtime state */ + return initial_state; + } + else { + /* If we dont' have a downtime state yet, the first downtime + state we encounter will be opposite the initial downtime + state */ + if(AU_LOGTYPE_NOTIFICATION == current_log_entry->entry_type) { + temp_downtime_log = (au_log_downtime *)current_log_entry->entry; + switch(temp_downtime_log->downtime_type) { + case AU_STATE_DOWNTIME_START: + return AU_STATE_DOWNTIME_END; + break; + case AU_STATE_DOWNTIME_END: + return AU_STATE_DOWNTIME_START; + break; + } + } + } + } + } + /* If we haven't encountered any indication of downtime yet, assume + we were not initially in downtime */ + if(AU_STATE_NO_DATA == initial_state) { + initial_state = AU_STATE_DOWNTIME_END; + } + + return initial_state; + } + +/* + Return the initial state of the host or service. + */ +int get_initial_subject_state(au_linked_list *log_entries, time_t start_time, + time_t end_time) { + + au_node *temp_node; + au_log_entry *current_log_entry; + int initial_state = AU_STATE_NO_DATA; + + for(temp_node = log_entries->head; temp_node != NULL; + temp_node = temp_node->next) { + current_log_entry = (au_log_entry *)temp_node->data; + if(current_log_entry->timestamp < start_time) { + /* Any state log prior to the start time may indicate the + initial state of the subject so look at all of them */ + switch(current_log_entry->entry_type) { + case AU_LOGTYPE_ALERT: + case AU_LOGTYPE_STATE_INITIAL: + case AU_LOGTYPE_STATE_CURRENT: + initial_state = get_log_entry_state(current_log_entry); + break; + } + } + } + return initial_state; + } + +int get_log_entry_state(au_log_entry *log_entry) { + + switch(log_entry->entry_type) { + case AU_LOGTYPE_ALERT: + case AU_LOGTYPE_STATE_INITIAL: + case AU_LOGTYPE_STATE_CURRENT: + return ((au_log_alert *)log_entry->entry)->state; + break; + case AU_LOGTYPE_DOWNTIME: + return ((au_log_downtime *)log_entry->entry)->downtime_type; + break; + case AU_LOGTYPE_NAGIOS: + return ((au_log_nagios *)log_entry->entry)->type; + break; + case AU_LOGTYPE_NOTIFICATION: + return ((au_log_notification *)log_entry->entry)->notification_type; + break; + default: + return AU_STATE_NO_DATA; + break; + } + } + +#define have_real_data(a) have_data((a), \ + ~(AU_STATE_NO_DATA | AU_STATE_PROGRAM_START | AU_STATE_PROGRAM_END)) +#define have_state_data(a) have_data((a), AU_STATE_ALL) + +int have_data(au_linked_list *log_entries, int mask) { + + au_node *temp_node; + int state; + + for(temp_node = log_entries->head; temp_node != NULL; + temp_node = temp_node->next) { + state = get_log_entry_state((au_log_entry *)temp_node->data); + if(state & mask) return TRUE; + } + return FALSE; + } + +unsigned long calculate_window_duration(time_t start_time, time_t end_time, + timeperiod *report_timeperiod) { + + struct tm *t; + unsigned long state_duration; + time_t midnight; + int weekday; + timerange *temp_timerange; + unsigned long temp_duration; + unsigned long temp_end; + unsigned long temp_start; + unsigned long start; + unsigned long end; + + /* MickeM - attempt to handle the the report time_period (if any) */ + if(report_timeperiod != NULL) { + t = localtime((time_t *)&start_time); + state_duration = 0; + + /* calculate the start of the day (midnight, 00:00 hours) */ + t->tm_sec = 0; + t->tm_min = 0; + t->tm_hour = 0; + t->tm_isdst = -1; + midnight = mktime(t); + weekday = t->tm_wday; + + while(midnight < end_time) { + temp_duration = 0; + temp_end = min(86400, end_time - midnight); + temp_start = 0; + if(start_time > midnight) { + temp_start = start_time - midnight; + } +#ifdef DEBUG + printf("Matching: %ld -> %ld. (%ld -> %ld)\n", temp_start, + temp_end, midnight + temp_start, midnight + temp_end); +#endif + /* check all time ranges for this day of the week */ + for(temp_timerange = report_timeperiod->days[weekday]; + temp_timerange != NULL; + temp_timerange = temp_timerange->next) { +#ifdef DEBUG + printf("Matching in timerange[%d]: %lu -> %lu (%lu -> %lu)\n", + weekday, temp_timerange->range_start, + temp_timerange->range_end, temp_start, temp_end); +#endif + + start = max(temp_timerange->range_start, temp_start); + end = min(temp_timerange->range_end, temp_end); + + if(start < end) { + temp_duration += end - start; +#ifdef DEBUG + printf("Matched time: %ld -> %ld = %lu\n", start, end, + temp_duration); +#endif + } +#ifdef DEBUG + else { + printf("Ignored time: %ld -> %ld\n", start, end); + } +#endif + } + state_duration += temp_duration; + temp_start = 0; + midnight += 86400; + if(++weekday > 6) weekday = 0; + } + } + + /* No report timeperiod was requested; assume 24x7 */ + else { + /* Calculate time in this state */ + state_duration = (unsigned long)(end_time - start_time); + } + + return state_duration; + } + +#ifdef DEBUG +void print_availability(au_availability *availability, const char *padding) { + + printf("%sAll:: up: %10lu\n", padding, + availability->time_up); + printf("%s down: %10lu\n", padding, + availability->time_down); + printf("%s unreachable: %10lu\n", padding, + availability->time_unreachable); + printf("%s ok: %10lu\n", padding, + availability->time_ok); + printf("%s warning: %10lu\n", padding, + availability->time_warning); + printf("%s critical: %10lu\n", padding, + availability->time_critical); + printf("%s unknown: %10lu\n", padding, + availability->time_unknown); + printf("%sScheduled:: up: %10lu\n", padding, + availability->scheduled_time_up); + printf("%s down: %10lu\n", padding, + availability->scheduled_time_down); + printf("%s unreachable: %10lu\n", padding, + availability->scheduled_time_unreachable); + printf("%s ok: %10lu\n", padding, + availability->scheduled_time_ok); + printf("%s warning: %10lu\n", padding, + availability->scheduled_time_warning); + printf("%s critical: %10lu\n", padding, + availability->scheduled_time_critical); + printf("%s unknown: %10lu\n", padding, + availability->scheduled_time_unknown); + printf("%sIndeterminate:: scheduled: %10lu\n", padding, + availability->scheduled_time_indeterminate); + printf("%s nodata: %10lu\n", padding, + availability->time_indeterminate_nodata); + printf("%s notrunning: %10lu\n", padding, + availability->time_indeterminate_notrunning); + } +#endif + +void compute_window_availability(time_t start_time, time_t end_time, + int last_subject_state, int last_downtime_state, int last_nagios_state, + timeperiod *report_timeperiod, au_availability *availability, + int assume_state_during_nagios_downtime, int object_type, + int assume_state_retention) { + + unsigned long state_duration; + +#ifdef DEBUG +printf( " %lu to %lu (%lus): %s/%s/%s\n", start_time, end_time, + (end_time - start_time), + svm_get_string_from_value(last_subject_state, svm_au_states), + svm_get_string_from_value(last_downtime_state, svm_au_states), + svm_get_string_from_value(last_nagios_state, svm_au_states)); +#endif + + /* Get the duration of this window as adjusted for the report timeperiod */ + state_duration = calculate_window_duration(start_time, end_time, + report_timeperiod); + + /* Determine the appropriate state */ + switch(last_nagios_state) { + case AU_STATE_PROGRAM_START: + switch(last_downtime_state) { + case AU_STATE_DOWNTIME_START: + switch(last_subject_state) { + case AU_STATE_NO_DATA: + availability->time_indeterminate_nodata += state_duration; + break; + case AU_STATE_HOST_UP: + availability->scheduled_time_up += state_duration; + break; + case AU_STATE_HOST_DOWN: + availability->scheduled_time_down += state_duration; + break; + case AU_STATE_HOST_UNREACHABLE: + availability->scheduled_time_unreachable += state_duration; + break; + case AU_STATE_SERVICE_OK: + availability->scheduled_time_ok += state_duration; + break; + case AU_STATE_SERVICE_WARNING: + availability->scheduled_time_warning += state_duration; + break; + case AU_STATE_SERVICE_UNKNOWN: + availability->scheduled_time_unknown += state_duration; + break; + case AU_STATE_SERVICE_CRITICAL: + availability->scheduled_time_critical += state_duration; + break; + } + break; + case AU_STATE_DOWNTIME_END: + switch(last_subject_state) { + case AU_STATE_NO_DATA: + availability->time_indeterminate_nodata += state_duration; + break; + case AU_STATE_HOST_UP: + availability->time_up += state_duration; + break; + case AU_STATE_HOST_DOWN: + availability->time_down += state_duration; + break; + case AU_STATE_HOST_UNREACHABLE: + availability->time_unreachable += state_duration; + break; + case AU_STATE_SERVICE_OK: + availability->time_ok += state_duration; + break; + case AU_STATE_SERVICE_WARNING: + availability->time_warning += state_duration; + break; + case AU_STATE_SERVICE_UNKNOWN: + availability->time_unknown += state_duration; + break; + case AU_STATE_SERVICE_CRITICAL: + availability->time_critical += state_duration; + break; + } + break; + } + break; + case AU_STATE_PROGRAM_END: + if(assume_state_during_nagios_downtime) { + switch(last_downtime_state) { + case AU_STATE_DOWNTIME_START: + switch(last_subject_state) { + case AU_STATE_NO_DATA: + availability->time_indeterminate_nodata += state_duration; + break; + case AU_STATE_HOST_UP: + availability->scheduled_time_up += state_duration; + break; + case AU_STATE_HOST_DOWN: + availability->scheduled_time_down += state_duration; + break; + case AU_STATE_HOST_UNREACHABLE: + availability->scheduled_time_unreachable += state_duration; + break; + case AU_STATE_SERVICE_OK: + availability->scheduled_time_ok += state_duration; + break; + case AU_STATE_SERVICE_WARNING: + availability->scheduled_time_warning += state_duration; + break; + case AU_STATE_SERVICE_UNKNOWN: + availability->scheduled_time_unknown += state_duration; + break; + case AU_STATE_SERVICE_CRITICAL: + availability->scheduled_time_critical += state_duration; + break; + } + break; + case AU_STATE_DOWNTIME_END: + switch(last_subject_state) { + case AU_STATE_NO_DATA: + availability->time_indeterminate_nodata += state_duration; + break; + case AU_STATE_HOST_UP: + availability->time_up += state_duration; + break; + case AU_STATE_HOST_DOWN: + availability->time_down += state_duration; + break; + case AU_STATE_HOST_UNREACHABLE: + availability->time_unreachable += state_duration; + break; + case AU_STATE_SERVICE_OK: + availability->time_ok += state_duration; + break; + case AU_STATE_SERVICE_WARNING: + availability->time_warning += state_duration; + break; + case AU_STATE_SERVICE_UNKNOWN: + availability->time_unknown += state_duration; + break; + case AU_STATE_SERVICE_CRITICAL: + availability->time_critical += state_duration; + break; + } + break; + } + } + else { + availability->time_indeterminate_notrunning += state_duration; + } + break; + } + +#ifdef DEBUG + print_availability(availability, " "); +#endif + + return; + } + +static void compute_availability(au_linked_list *log_entries, time_t query_time, + time_t start_time, time_t end_time, timeperiod *report_timeperiod, + au_availability *availability, int initial_subject_state, + int assume_state_during_nagios_downtime, int object_type, + int assume_state_retention) { + + int current_nagios_state; + int last_nagios_state; + int current_downtime_state; + int last_downtime_state; + int current_subject_state = initial_subject_state; + int last_subject_state = AU_STATE_NO_DATA; + au_node *temp_node; + au_log_entry *current_log_entry; + au_log_entry *last_log_entry = NULL; + au_log_alert *temp_alert_log; + au_log_downtime *temp_downtime_log; + au_log_nagios *temp_nagios_log; + time_t last_time = start_time; + time_t current_time; + +#ifdef DEBUG + printf(" initial state: %s\n", + svm_get_string_from_value(initial_subject_state, valid_states)); +#endif + + /* Determine the initial Nagios state */ + if((last_nagios_state = current_nagios_state = + get_initial_nagios_state(log_entries, start_time, end_time)) + == AU_STATE_NO_DATA) { + /* This is bad; I'm giving up. */ + return; + } + +#ifdef DEBUG + printf(" initial nagios state: %s\n", + svm_get_string_from_value(last_nagios_state, valid_states)); +#endif + + /* Determine the initial downtime state */ + if((last_downtime_state = current_downtime_state = + get_initial_downtime_state(log_entries, start_time, end_time)) + == AU_STATE_NO_DATA) { + /* This is bad; I'm giving up. */ + return; + } + +#ifdef DEBUG + printf(" initial downtime state: %s\n", + svm_get_string_from_value(last_downtime_state, valid_states)); +#endif + + + /* Process all entry pairs */ + for(temp_node = log_entries->head; temp_node != NULL; + temp_node = temp_node->next) { + current_log_entry = (au_log_entry *)temp_node->data; + + /* Skip everything before the start of the requested query window */ + if(current_log_entry->timestamp < start_time) continue; + +#ifdef DEBUG + printf(" Got log of type \"%s\" at %lu\n", + svm_get_string_from_value(current_log_entry->entry_type, + svm_au_log_types), current_log_entry->timestamp); +#endif + + /* Update states */ + last_subject_state = current_subject_state; + last_downtime_state = current_downtime_state; + last_nagios_state = current_nagios_state; + + switch(current_log_entry->entry_type) { + case AU_LOGTYPE_ALERT: + case AU_LOGTYPE_STATE_INITIAL: + case AU_LOGTYPE_STATE_CURRENT: + temp_alert_log = (au_log_alert *)current_log_entry->entry; + current_subject_state = temp_alert_log->state; +#ifdef DEBUG + printf(" Current alert state: \"%s\"\n", + svm_get_string_from_value(current_subject_state, + valid_states)); +#endif + break; + case AU_LOGTYPE_DOWNTIME: + temp_downtime_log = (au_log_downtime *)current_log_entry->entry; + current_downtime_state = temp_downtime_log->downtime_type; +#ifdef DEBUG + printf(" Current downtime state: \"%s\"\n", + svm_get_string_from_value(current_downtime_state, + valid_states)); +#endif + break; + case AU_LOGTYPE_NAGIOS: + temp_nagios_log = (au_log_nagios *)current_log_entry->entry; + current_nagios_state = temp_nagios_log->type; +#ifdef DEBUG + printf(" Current nagios state: \"%s\"\n", + svm_get_string_from_value(current_nagios_state, + valid_states)); +#endif + break; + default: + continue; + break; + } + + /* Record the time ranges for the current log pair */ + if(NULL != last_log_entry) last_time = last_log_entry->timestamp; + current_time = current_log_entry->timestamp; + + /* Bail out if we've already passed the end of the requested time + range*/ + if(last_time > end_time) break; + + /* Clip last time if it extends beyond the end of the requested + time range */ + if(current_time > end_time) current_time = end_time; + + /* Clip first time if it precedes the start of the requested + time range */ + if(last_time < start_time) last_time = start_time; + + /* compute availability times for this chunk */ + compute_window_availability(last_time, current_time, last_subject_state, + last_downtime_state, last_nagios_state, report_timeperiod, + availability, assume_state_during_nagios_downtime, object_type, + assume_state_retention); + + /* Return if we've reached the end of the requested time + range */ + if(current_time >= end_time) { + last_log_entry = current_log_entry; + break; + } + + /* Keep track of the last item */ + last_log_entry = current_log_entry; + } + + /* Process the last entry */ + if(last_log_entry != NULL) { + /* Update states */ + last_subject_state = current_subject_state; + last_downtime_state = current_downtime_state; + last_nagios_state = current_nagios_state; + + /* Don't process an entry that is beyond the end of the requested + time range */ + if(last_log_entry->timestamp < end_time) { + current_time = query_time; + if(current_time > end_time) current_time = end_time; + + last_time = last_log_entry->timestamp; + if(last_time < start_time) last_time = start_time; + + /* compute availability times for last state */ + compute_window_availability(last_time, current_time, + last_subject_state, last_downtime_state, last_nagios_state, + report_timeperiod, availability, + assume_state_during_nagios_downtime, object_type, + assume_state_retention); + } + } + else { + /* There were no log entries for the entire queried time, therefore + the whole query window was the same state */ + compute_window_availability(start_time, end_time, initial_subject_state, + last_downtime_state, last_nagios_state, report_timeperiod, + availability, assume_state_during_nagios_downtime, object_type, + assume_state_retention); + } + } + + +void compute_host_availability(time_t query_time, time_t start_time, + time_t end_time, au_log *log, au_host *host, + timeperiod *report_timeperiod, int assume_initial_state, + int assumed_initial_host_state, + int assume_state_during_nagios_downtime, int assume_state_retention) { + + hoststatus *host_status = NULL; + int last_known_state = AU_STATE_NO_DATA; + int initial_host_state = AU_STATE_NO_DATA; + +#ifdef DEBUG + printf("Computing availability for host %s\n from %lu to %lu\n", + host->name, start_time, end_time); +#endif + + /* If the start time is in the future, we can't compute anything */ + if(start_time > query_time) return; + + /* Get current host status if possible */ + host_status = find_hoststatus(host->name); + + /* If we don't have any data, the query time falls within the requested + query window, and we have the current host status, insert the + current state as the pseudo state at the start of the requested + query window. */ + if((have_state_data(host->log_entries) == FALSE) && + (query_time > start_time) && (query_time <= end_time) && + (host_status != NULL)) { + switch(host_status->status) { + case HOST_DOWN: + last_known_state = AU_STATE_HOST_DOWN; + break; + case HOST_UNREACHABLE: + last_known_state = AU_STATE_HOST_UNREACHABLE; + break; + case HOST_UP: + last_known_state = AU_STATE_HOST_UP; + break; + default: + last_known_state = AU_STATE_NO_DATA; + break; + } + + if(last_known_state != AU_STATE_NO_DATA) { + /* Add a dummy current state item */ +#ifdef DEBUG + printf(" Inserting %s as current service pseudo-state\n", + svm_get_string_from_value(last_known_state, valid_states)); +#endif + (void)au_add_alert_or_state_log(log, start_time, + AU_LOGTYPE_STATE_CURRENT, AU_OBJTYPE_HOST, host, + AU_STATETYPE_HARD, last_known_state, + "Current Host Pseudo-State"); + } + } + + /* Next determine the initial state of the host */ + initial_host_state = get_initial_subject_state(host->log_entries, + start_time, end_time); +#ifdef DEBUG + printf(" Initial state from logs: %s\n", + svm_get_string_from_value(initial_host_state, valid_states)); +#endif + + if((AU_STATE_NO_DATA == initial_host_state) && + (1 == assume_initial_state)) { + switch(assumed_initial_host_state) { + case AU_STATE_HOST_UP: + case AU_STATE_HOST_DOWN: + case AU_STATE_HOST_UNREACHABLE: + initial_host_state = assumed_initial_host_state; + break; + case AU_STATE_CURRENT_STATE: + if(host_status != NULL) { + switch(host_status->status) { + case HOST_DOWN: + initial_host_state = AU_STATE_HOST_DOWN; + break; + case HOST_UNREACHABLE: + initial_host_state = AU_STATE_HOST_UNREACHABLE; + break; + case HOST_UP: + initial_host_state = AU_STATE_HOST_UP; + break; + } + } + break; + } + } + + /* At this point, if we still don't have any real data, we can't compute + anything, so return */ + if((have_real_data(host->log_entries) != TRUE) && + (AU_STATE_NO_DATA == initial_host_state)) return; + + /* Compute the availability for every entry in the host's list of log + entries */ + compute_availability(host->log_entries, query_time, start_time, end_time, + report_timeperiod, host->availability, initial_host_state, + assume_state_during_nagios_downtime, AU_OBJTYPE_HOST, + assume_state_retention); + + } + +void compute_service_availability(time_t query_time, time_t start_time, + time_t end_time, au_log *log, au_service *service, + timeperiod *report_timeperiod, int assume_initial_state, + int assumed_initial_service_state, + int assume_state_during_nagios_downtime, int assume_state_retention) { + + servicestatus *service_status = NULL; + int last_known_state = AU_STATE_NO_DATA; + int initial_service_state = AU_STATE_NO_DATA; + +#ifdef DEBUG + printf("Computing availability for service %s:%s\n from %lu to %lu\n", + service->host_name, service->description, start_time, end_time); +#endif + + /* If the start time is in the future, we can't compute anything */ + if(start_time > query_time) return; + + /* Get current service status if possible */ + service_status = find_servicestatus(service->host_name, + service->description); + + /* If we don't have any data, the query time falls within the requested + query window, and we have the current service status, insert the + current state as the pseudo state at the start of the requested + query window. */ + if((have_state_data(service->log_entries) == FALSE) && + (query_time > start_time) && (query_time <= end_time) && + (service_status != NULL)) { + switch(service_status->status) { + case SERVICE_OK: + last_known_state = AU_STATE_SERVICE_OK; + break; + case SERVICE_WARNING: + last_known_state = AU_STATE_SERVICE_WARNING; + break; + case SERVICE_CRITICAL: + last_known_state = AU_STATE_SERVICE_CRITICAL; + break; + case SERVICE_UNKNOWN: + last_known_state = AU_STATE_SERVICE_UNKNOWN; + break; + default: + last_known_state = AU_STATE_NO_DATA; + break; + } + + if(last_known_state != AU_STATE_NO_DATA) { + /* Add a dummy current state item */ +#ifdef DEBUG + printf(" Inserting %s as current service pseudo-state\n", + svm_get_string_from_value(last_known_state, valid_states)); +#endif + (void)au_add_alert_or_state_log(log, start_time, + AU_LOGTYPE_STATE_CURRENT, AU_OBJTYPE_SERVICE, service, + AU_STATETYPE_HARD, last_known_state, + "Current Service Pseudo-State"); + } + } + + /* Next determine the initial state of the service */ + initial_service_state = get_initial_subject_state(service->log_entries, + start_time, end_time); +#ifdef DEBUG + printf(" Initial state from logs: %s\n", + svm_get_string_from_value(initial_service_state, valid_states)); +#endif + if((AU_STATE_NO_DATA == initial_service_state) && + (1 == assume_initial_state)) { + switch(assumed_initial_service_state) { + case AU_STATE_SERVICE_OK: + case AU_STATE_SERVICE_WARNING: + case AU_STATE_SERVICE_UNKNOWN: + case AU_STATE_SERVICE_CRITICAL: + initial_service_state = assumed_initial_service_state; + break; + case AU_STATE_CURRENT_STATE: + if(service_status == NULL) { + switch(service_status->status) { + case SERVICE_OK: + initial_service_state = AU_STATE_SERVICE_OK; + break; + case SERVICE_WARNING: + initial_service_state = AU_STATE_SERVICE_WARNING; + break; + case SERVICE_UNKNOWN: + initial_service_state = AU_STATE_SERVICE_UNKNOWN; + break; + case SERVICE_CRITICAL: + initial_service_state = AU_STATE_SERVICE_CRITICAL; + break; + } + } + break; + } + } + + /* At this point, if we still don't have any real data, we can't compute + anything, so return */ + if((have_real_data(service->log_entries) != TRUE) && + (AU_STATE_NO_DATA == initial_service_state)) return; + + /* Compute the availability for every entry in the service's list of log + entries */ + compute_availability(service->log_entries, query_time, start_time, end_time, + report_timeperiod, service->availability, initial_service_state, + assume_state_during_nagios_downtime, AU_OBJTYPE_SERVICE, + assume_state_retention); + + } + +json_object *json_archive_availability_selectors(unsigned format_options, + time_t start_time, time_t end_time, int availability_object_type, + char *host_name, char *service_description, hostgroup *hostgroup, + servicegroup *servicegroup, timeperiod *report_timeperiod, + int assume_initial_state, int assume_state_retention, + int assume_state_during_nagios_downtime, + int assumed_initial_host_state, int assumed_initial_service_state, + unsigned state_types) { + + json_object *json_selectors; + + json_selectors = json_new_object(); + + json_enumeration(json_selectors, format_options, "availabilityobjecttype", + availability_object_type, valid_availability_object_types); + + if(start_time > 0) { + json_object_append_time_t(json_selectors, "starttime", start_time); + } + + if(end_time > 0) { + json_object_append_time_t(json_selectors, "endtime", end_time); + } + + if(NULL != host_name) { + json_object_append_string(json_selectors, "hostname", &percent_escapes, + host_name); + } + + if(NULL != service_description) { + json_object_append_string(json_selectors, "servicedescription", + &percent_escapes, service_description); + } + + if(NULL != hostgroup) { + json_object_append_string(json_selectors, "hostgroup", &percent_escapes, + hostgroup->group_name); + } + + if(NULL != servicegroup) { + json_object_append_string(json_selectors, "servicegroup", + &percent_escapes, servicegroup->group_name); + } + + if(NULL != report_timeperiod) { + json_object_append_string(json_selectors, "timeperiod", + &percent_escapes, report_timeperiod->name); + } + + json_object_append_boolean(json_selectors, "assumeinitialstate", + assume_initial_state); + json_object_append_boolean(json_selectors, "assumestateretention", + assume_state_retention); + json_object_append_boolean(json_selectors, + "assumestateduringnagiosdowntime", + assume_state_during_nagios_downtime); + if(assumed_initial_host_state != AU_STATE_NO_DATA) { + json_enumeration(json_selectors, format_options, + "assumedinitialhoststate", assumed_initial_host_state, + valid_initial_host_states); + } + + if(assumed_initial_service_state != AU_STATE_NO_DATA) { + json_enumeration(json_selectors, format_options, + "assumedinitialservicestate", assumed_initial_service_state, + valid_initial_service_states); + } + + if(state_types != AU_STATETYPE_ALL) { + json_bitmask(json_selectors, format_options, "statetypes", state_types, + valid_state_types); + } + + return json_selectors; + } + +json_object *json_archive_availability(unsigned format_options, + time_t query_time, time_t start_time, time_t end_time, + int availability_object_type, char *host_name, + char *service_description, hostgroup *hostgroup_selector, + servicegroup *servicegroup_selector, timeperiod *report_timeperiod, + int assume_initial_state, int assume_state_retention, + int assume_state_during_nagios_downtime, + int assumed_initial_host_state, int assumed_initial_service_state, + unsigned state_types, au_log *log) { + + json_object *json_data; + + host *temp_host; + json_array *json_host_list; + json_object *json_host_object; + + service *temp_service; + json_array *json_service_list; + json_object *json_service_object; + + hostgroup *temp_hostgroup; + json_object *json_hostgroup_object; + json_array *json_hostgroup_list; + hostsmember *temp_hostgroup_member; + + servicegroup *temp_servicegroup; + json_object *json_servicegroup_object; + json_array *json_servicegroup_list; + servicesmember *temp_servicegroup_member; + + json_data = json_new_object(); + json_object_append_object(json_data, "selectors", + json_archive_availability_selectors(format_options, start_time, + end_time, availability_object_type, host_name, service_description, + hostgroup_selector, servicegroup_selector, report_timeperiod, + assume_initial_state, assume_state_retention, + assume_state_during_nagios_downtime, assumed_initial_host_state, + assumed_initial_service_state, state_types)); + + /* First compute the availability */ + switch(availability_object_type) { + case AU_OBJTYPE_HOST: + if(NULL == host_name) { /* compute for all hosts */ + json_host_list = json_new_array(); + for(temp_host = host_list; temp_host != NULL; + temp_host = temp_host->next) { + if(FALSE == is_authorized_for_host(temp_host, + ¤t_authdata)) { + continue; + } + json_host_object = + json_archive_single_host_availability( + format_options, query_time, start_time, end_time, + temp_host->name, report_timeperiod, + assume_initial_state, assume_state_retention, + assume_state_during_nagios_downtime, + assumed_initial_host_state, state_types, log); + if(NULL != json_host_object) { + json_array_append_object(json_host_list, + json_host_object); + } + } + json_object_append_array(json_data, "hosts", json_host_list); + } + else { + temp_host = find_host(host_name); + if((NULL != temp_host) && + (TRUE == is_authorized_for_host(temp_host, + ¤t_authdata))) { + json_host_object = + json_archive_single_host_availability(format_options, + query_time, start_time, end_time, host_name, + report_timeperiod, assume_initial_state, + assume_state_retention, + assume_state_during_nagios_downtime, + assumed_initial_host_state, state_types, log); + if(NULL != json_host_object) { + json_object_append_object(json_data, "host", + json_host_object); + } + } + } + break; + case AU_OBJTYPE_SERVICE: + if((NULL == host_name) && (NULL == service_description)) { + /* compute for all services on all hosts */ + json_service_list = json_new_array(); + for(temp_service = service_list; temp_service != NULL; + temp_service = temp_service->next) { + if(FALSE == is_authorized_for_service(temp_service, + ¤t_authdata)) { + continue; + } + json_service_object = + json_archive_single_service_availability( + format_options, query_time, start_time, end_time, + temp_service->host_name, temp_service->description, + report_timeperiod, assume_initial_state, + assume_state_retention, + assume_state_during_nagios_downtime, + assumed_initial_service_state, state_types, log); + if(NULL != json_service_object) { + json_array_append_object(json_service_list, + json_service_object); + } + } + json_object_append_array(json_data, "services", + json_service_list); + } + else if(NULL == service_description) { + /* compute for all services on the specified host */ + json_service_list = json_new_array(); + for(temp_service = service_list; temp_service != NULL; + temp_service = temp_service->next) { + if(!strcmp(temp_service->host_name, host_name) && + (TRUE == is_authorized_for_service(temp_service, + ¤t_authdata))) { + json_service_object = + json_archive_single_service_availability( + format_options, query_time, start_time, + end_time, temp_service->host_name, + temp_service->description, report_timeperiod, + assume_initial_state, assume_state_retention, + assume_state_during_nagios_downtime, + assumed_initial_service_state, state_types, + log); + if(NULL != json_service_object) { + json_array_append_object(json_service_list, + json_service_object); + } + } + } + json_object_append_array(json_data, "services", + json_service_list); + } + else if(NULL == host_name) { + /* compute for all services on the specified host */ + json_service_list = json_new_array(); + for(temp_service = service_list; temp_service != NULL; + temp_service = temp_service->next) { + if(!strcmp(temp_service->description, + service_description) && + (TRUE == is_authorized_for_service(temp_service, + ¤t_authdata))) { + json_service_object = + json_archive_single_service_availability( + format_options, query_time, start_time, + end_time, temp_service->host_name, + temp_service->description, report_timeperiod, + assume_initial_state, assume_state_retention, + assume_state_during_nagios_downtime, + assumed_initial_service_state, state_types, + log); + if(NULL != json_service_object) { + json_array_append_object(json_service_list, + json_service_object); + } + } + } + json_object_append_array(json_data, "services", + json_service_list); + } + else { + temp_service = find_service(host_name, service_description); + if((NULL != temp_service) && + (TRUE == is_authorized_for_service(temp_service, + ¤t_authdata))) { + json_service_object = + json_archive_single_service_availability(format_options, + query_time, start_time, end_time, host_name, + service_description, report_timeperiod, + assume_initial_state, assume_state_retention, + assume_state_during_nagios_downtime, + assumed_initial_service_state, state_types, log); + if(NULL != json_service_object) { + json_object_append_object(json_data, "service", + json_service_object); + } + } + } + break; + case AU_OBJTYPE_HOSTGROUP: + if(NULL == hostgroup_selector) { + /* compute for all hosts in all hostgroups */ + json_hostgroup_list = json_new_array(); + for(temp_hostgroup = hostgroup_list; temp_hostgroup != NULL; + temp_hostgroup = temp_hostgroup->next) { + json_host_list = json_new_array(); + for(temp_hostgroup_member = temp_hostgroup->members; + temp_hostgroup_member != NULL; + temp_hostgroup_member = + temp_hostgroup_member->next) { + if(FALSE == is_authorized_for_host(temp_hostgroup_member->host_ptr, + ¤t_authdata)) { + continue; + } + json_host_object = + json_archive_single_host_availability( + format_options, query_time, start_time, + end_time, temp_hostgroup_member->host_name, + report_timeperiod, assume_initial_state, + assume_state_retention, + assume_state_during_nagios_downtime, + assumed_initial_host_state, state_types, log); + if(NULL != json_host_object) { + json_array_append_object(json_host_list, + json_host_object); + } + } + json_hostgroup_object = json_new_object(); + json_object_append_string(json_hostgroup_object, "name", + &percent_escapes, temp_hostgroup->group_name); + json_object_append_array(json_hostgroup_object, "hosts", + json_host_list); + json_array_append_object(json_hostgroup_list, + json_hostgroup_object); + } + json_object_append_array(json_data, "hostgroups", + json_hostgroup_list); + } + else { + /* compute for all hosts in the specified hostgroup */ + json_host_list = json_new_array(); + for(temp_hostgroup_member = hostgroup_selector->members; + temp_hostgroup_member != NULL; + temp_hostgroup_member = temp_hostgroup_member->next) { + if(FALSE == is_authorized_for_host(temp_hostgroup_member->host_ptr, + ¤t_authdata)) { + continue; + } + json_host_object = + json_archive_single_host_availability( + format_options, query_time, start_time, end_time, + temp_hostgroup_member->host_name, report_timeperiod, + assume_initial_state, assume_state_retention, + assume_state_during_nagios_downtime, + assumed_initial_host_state, state_types, log); + if(NULL != json_host_object) { + json_array_append_object(json_host_list, + json_host_object); + } + } + json_hostgroup_object = json_new_object(); + json_object_append_string(json_hostgroup_object, "name", + &percent_escapes, hostgroup_selector->group_name); + json_object_append_array(json_hostgroup_object, "hosts", + json_host_list); + json_object_append_object(json_data, "hostgroup", + json_hostgroup_object); + } + break; + case AU_OBJTYPE_SERVICEGROUP: + if(NULL == servicegroup_selector) { + /* compute for all hosts in all hostgroups */ + json_servicegroup_list = json_new_array(); + for(temp_servicegroup = servicegroup_list; + temp_servicegroup != NULL; + temp_servicegroup = temp_servicegroup->next) { + json_service_list = json_new_array(); + for(temp_servicegroup_member = temp_servicegroup->members; + temp_servicegroup_member != NULL; + temp_servicegroup_member = + temp_servicegroup_member->next) { + if(FALSE == is_authorized_for_service(temp_servicegroup_member->service_ptr, + ¤t_authdata)) { + continue; + } + json_service_object = + json_archive_single_service_availability( + format_options, query_time, start_time, + end_time, temp_servicegroup_member->host_name, + temp_servicegroup_member->service_description, + report_timeperiod, assume_initial_state, + assume_state_retention, + assume_state_during_nagios_downtime, + assumed_initial_service_state, state_types, + log); + if(NULL != json_service_object) { + json_array_append_object(json_service_list, + json_service_object); + } + } + json_servicegroup_object = json_new_object(); + json_object_append_string(json_servicegroup_object, "name", + &percent_escapes, temp_servicegroup->group_name); + json_object_append_array(json_servicegroup_object, "hosts", + json_service_list); + json_array_append_object(json_servicegroup_list, + json_servicegroup_object); + } + json_object_append_array(json_data, "servicegroups", + json_servicegroup_list); + } + else { + /* compute for all services in the specified servicegroup */ + json_service_list = json_new_array(); + for(temp_servicegroup_member = servicegroup_selector->members; + temp_servicegroup_member != NULL; + temp_servicegroup_member = + temp_servicegroup_member->next) { + if(FALSE == is_authorized_for_service(temp_servicegroup_member->service_ptr, + ¤t_authdata)) { + continue; + } + json_service_object = + json_archive_single_service_availability( + format_options, query_time, start_time, end_time, + temp_servicegroup_member->host_name, + temp_servicegroup_member->service_description, + report_timeperiod, assume_initial_state, + assume_state_retention, + assume_state_during_nagios_downtime, + assumed_initial_service_state, state_types, log); + if(NULL != json_service_object) { + json_array_append_object(json_service_list, + json_service_object); + } + } + json_servicegroup_object = json_new_object(); + json_object_append_string(json_servicegroup_object, "name", + &percent_escapes, servicegroup_selector->group_name); + json_object_append_array(json_servicegroup_object, "services", + json_service_list); + json_object_append_object(json_data, "servicegroup", + json_servicegroup_object); + } + break; + default: + break; + } + + return json_data; + } + +json_object *json_archive_single_host_availability(unsigned format_options, + time_t query_time, time_t start_time, time_t end_time, char *host_name, + timeperiod *report_timeperiod, int assume_initial_state, + int assume_state_retention, int assume_state_during_nagios_downtime, + int assumed_initial_host_state, unsigned state_types, au_log *log) { + + au_host *host = NULL; + au_node *temp_entry = NULL; + au_host *global_host = NULL; + json_object *json_host_availability = NULL; + + host = au_find_host(log->hosts, host_name); + if(NULL == host) { + /* host has no log entries, so create the host */ + host = au_add_host(log->hosts, host_name); + /* Add global events to this new host */ + global_host = au_find_host(log->hosts, "*"); + if(NULL != global_host) { + for(temp_entry = global_host->log_entries->head; NULL != temp_entry; + temp_entry = temp_entry->next) { + if(au_list_add_node(host->log_entries, temp_entry->data, + au_cmp_log_entries) == 0) { + break; + } + } + } + } + + if((host->availability = calloc(1, sizeof(au_availability))) != NULL) { + compute_host_availability(query_time, start_time, end_time, log, host, + report_timeperiod, assume_initial_state, + assumed_initial_host_state, + assume_state_during_nagios_downtime, assume_state_retention); + json_host_availability = json_archive_host_availability(format_options, + host->name, host->availability); + } + + return json_host_availability; + } + +json_object *json_archive_single_service_availability(unsigned format_options, + time_t query_time, time_t start_time, time_t end_time, char *host_name, + char *service_description, timeperiod *report_timeperiod, + int assume_initial_state, int assume_state_retention, + int assume_state_during_nagios_downtime, + int assumed_initial_service_state, unsigned state_types, au_log *log) { + + au_service *service = NULL; + au_node *temp_entry = NULL; + au_host *global_host = NULL; + json_object *json_service_availability = NULL; + + service = au_find_service(log->services, host_name, service_description); + if(NULL == service) { + /* service has no log entries, so create the service */ + service = au_add_service(log->services, host_name, service_description); + /* Add global events to this new service */ + global_host = au_find_host(log->hosts, "*"); + if(NULL != global_host) { + for(temp_entry = global_host->log_entries->head; NULL != temp_entry; + temp_entry = temp_entry->next) { + if(au_list_add_node(service->log_entries, temp_entry->data, + au_cmp_log_entries) == 0) { + break; + } + } + } + } + + if((service->availability = calloc(1, sizeof(au_availability))) != NULL) { + compute_service_availability(query_time, start_time, end_time, log, + service, report_timeperiod, assume_initial_state, + assumed_initial_service_state, + assume_state_during_nagios_downtime, assume_state_retention); + json_service_availability = + json_archive_service_availability(format_options, + service->host_name, service->description, + service->availability); + } + + return json_service_availability; + } + +json_object *json_archive_host_availability(unsigned format_options, + char *name, au_availability *availability) { + + json_object *json_host_availability; + + json_host_availability = json_new_object(); + + if(name != NULL) { + json_object_append_string(json_host_availability, "name", + &percent_escapes, name); + } + + json_object_append_duration(json_host_availability, "time_up", + availability->time_up); + json_object_append_duration(json_host_availability, "time_down", + availability->time_down); + json_object_append_duration(json_host_availability, "time_unreachable", + availability->time_unreachable); + json_object_append_duration(json_host_availability, "scheduled_time_up", + availability->scheduled_time_up); + json_object_append_duration(json_host_availability, "scheduled_time_down", + availability->scheduled_time_down); + json_object_append_duration(json_host_availability, + "scheduled_time_unreachable", + availability->scheduled_time_unreachable); + json_object_append_duration(json_host_availability, + "time_indeterminate_nodata", + availability->time_indeterminate_nodata); + json_object_append_duration(json_host_availability, + "time_indeterminate_notrunning", + availability->time_indeterminate_notrunning); + + return json_host_availability; + } + +json_object *json_archive_service_availability(unsigned format_options, + char *host_name, char *description, au_availability *availability) { + + json_object *json_service_availability; + + json_service_availability = json_new_object(); + + if(host_name != NULL) { + json_object_append_string(json_service_availability, "host_name", + &percent_escapes, host_name); + } + if(description != NULL) { + json_object_append_string(json_service_availability, "description", + &percent_escapes, description); + } + + json_object_append_duration(json_service_availability, "time_ok", + availability->time_ok); + json_object_append_duration(json_service_availability, "time_warning", + availability->time_warning); + json_object_append_duration(json_service_availability, "time_critical", + availability->time_critical); + json_object_append_duration(json_service_availability, "time_unknown", + availability->time_unknown); + json_object_append_duration(json_service_availability, "scheduled_time_ok", + availability->scheduled_time_ok); + json_object_append_duration(json_service_availability, + "scheduled_time_warning", availability->scheduled_time_warning); + json_object_append_duration(json_service_availability, + "scheduled_time_critical", availability->scheduled_time_critical); + json_object_append_duration(json_service_availability, + "scheduled_time_unknown", availability->scheduled_time_unknown); + json_object_append_duration(json_service_availability, + "time_indeterminate_nodata", + availability->time_indeterminate_nodata); + json_object_append_duration(json_service_availability, + "time_indeterminate_notrunning", + availability->time_indeterminate_notrunning); + + return json_service_availability; + } diff --git a/cgi/archiveutils.c b/cgi/archiveutils.c new file mode 100644 index 0000000..b37ffcf --- /dev/null +++ b/cgi/archiveutils.c @@ -0,0 +1,1650 @@ +/************************************************************************** + * + * ARCHIVEUTILS.C - Utilities for Nagios CGIs that read archive logs + * + * Copyright (c) 2013 Nagios Enterprises, LLC + * Last Modified: 06-30-2013 + * + * License: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + *************************************************************************/ + +#include "../include/config.h" +#include "../include/common.h" +#include "../include/objects.h" +#include "../include/statusdata.h" +#include "../include/comments.h" + +#include "../include/cgiutils.h" +#include "../include/statusdata.h" +#include "../include/archiveutils.h" + +#define AU_INITIAL_LIST_SIZE 16 + +const string_value_mapping svm_au_object_types[] = { + { "none", AU_OBJTYPE_NONE, "None" }, + { "host", AU_OBJTYPE_HOST, "Host" }, + { "service", AU_OBJTYPE_SERVICE, "Service" }, + { NULL, -1, NULL }, + }; + +const string_value_mapping svm_au_state_types[] = { + { "hard", AU_STATETYPE_HARD, "Hard" }, + { "soft", AU_STATETYPE_SOFT, "Soft" }, + { "nodata", AU_STATETYPE_NO_DATA, "No Data" }, + { NULL, -1, NULL }, + }; + +const string_value_mapping svm_au_states[] = { + { "nodata", AU_STATE_NO_DATA, "No Data" }, + { "up", AU_STATE_HOST_UP, "Host Up" }, + { "down", AU_STATE_HOST_DOWN, "How Down" }, + { "unreachable", AU_STATE_HOST_UNREACHABLE, "Host Unreachable" }, + { "ok", AU_STATE_SERVICE_OK, "Service OK" }, + { "warning", AU_STATE_SERVICE_WARNING, "Service Warning" }, + { "critical", AU_STATE_SERVICE_CRITICAL, "Service Critical" }, + { "unknown", AU_STATE_SERVICE_UNKNOWN, "Service Unknown" }, + { "programstart", AU_STATE_PROGRAM_START, "Program Start"}, + { "programend", AU_STATE_PROGRAM_END, "Program End"}, + { "downtimestart", AU_STATE_DOWNTIME_START, "Downtime Start"}, + { "downtimeend", AU_STATE_DOWNTIME_END, "Downtime End"}, + { "currentstate", AU_STATE_CURRENT_STATE, "Current State"}, + { NULL, -1, NULL }, + }; + +const string_value_mapping svm_au_log_types[] = { + { "alert", AU_LOGTYPE_ALERT, "Alert" }, + { "initialstate", AU_LOGTYPE_STATE_INITIAL, "Initial State" }, + { "currentstate", AU_LOGTYPE_STATE_CURRENT, "Current State" }, + { "notification", AU_LOGTYPE_NOTIFICATION, "Notification" }, + { "downtime", AU_LOGTYPE_DOWNTIME, "Downtime" }, + { "nagios", AU_LOGTYPE_NAGIOS, "Nagios" }, + { NULL, -1, NULL }, + }; + +const string_value_mapping svm_au_notification_types[] = { + { "nodata", AU_NOTIFICATION_NO_DATA, + "No Data" }, + { "down", AU_NOTIFICATION_HOST_DOWN, + "Host Down" }, + { "unreachable", AU_NOTIFICATION_HOST_UNREACHABLE, + "Host Unreachable" }, + { "recovery", AU_NOTIFICATION_HOST_RECOVERY, + "Host Recovery" }, + { "hostcustom", AU_NOTIFICATION_HOST_CUSTOM, + "Host Custom" }, + { "hostack", AU_NOTIFICATION_HOST_ACK, + "Host Acknowledgement" }, + { "hostflapstart", AU_NOTIFICATION_HOST_FLAPPING_START, + "Host Flapping Start" }, + { "hostflapstop", AU_NOTIFICATION_HOST_FLAPPING_STOP, + "Host Flapping Stop" }, + { "critical", AU_NOTIFICATION_SERVICE_CRITICAL, + "Service Critical" }, + { "warning", AU_NOTIFICATION_SERVICE_WARNING, + "Service Warning" }, + { "recovery", AU_NOTIFICATION_SERVICE_RECOVERY, + "Service Recovery" }, + { "custom", AU_NOTIFICATION_SERVICE_CUSTOM, + "Service Custom" }, + { "serviceack", AU_NOTIFICATION_SERVICE_ACK, + "Service Acknowledgement" }, + { "serviceflapstart", AU_NOTIFICATION_SERVICE_FLAPPING_START, + "Service Flapping Start" }, + { "serviceflapstop", AU_NOTIFICATION_SERVICE_FLAPPING_STOP, + "Service Flapping Stop" }, + { "unknown", AU_NOTIFICATION_SERVICE_UNKNOWN, + "Service Unknown" }, + { NULL, -1, NULL }, + }; + +/* Function prototypes */ +int read_log_file(char *, unsigned, unsigned, unsigned, au_log *); +int au_add_nagios_log(au_log *, time_t, int, char *); +void au_free_nagios_log(au_log_nagios *); +int parse_states_and_alerts(char *, time_t, int, unsigned, unsigned, au_log *); +int parse_downtime_alerts(char *, time_t, unsigned, au_log *); +int au_add_downtime_log(au_log *, time_t, int, void *, int); +void au_free_downtime_log(au_log_downtime *); +int parse_notification_log(char *, time_t, int, au_log *); +int au_add_notification_log(au_log *, time_t, int, void *, au_contact *, int, + char *, char *); +void au_free_notification_log(au_log_notification *); +au_log_entry *au_add_log_entry(au_log *, time_t, int, void *); +void au_free_log_entry_void(void *); +void au_free_log_entry(au_log_entry *); +au_host *au_add_host_and_sort(au_array *, char *); +void au_free_host_void(void *); +void au_free_host(au_host *); +int au_cmp_hosts(const void *, const void *); +au_service *au_add_service_and_sort(au_array *, char *, char *); +int au_cmp_services(const void *, const void *); +void au_free_service_void(void *); +void au_free_service(au_service *); +au_contact *au_add_contact_and_sort(au_array *, char *); +au_contact *au_add_contact(au_array *, char *); +void au_free_contact_void(void *); +void au_free_contact(au_contact *); +int au_cmp_contacts(const void *, const void *); +au_contact *au_find_contact(au_array *, char *); +void au_sort_array(au_array *, int(*cmp)(const void *, const void *)); +void *au_find_in_array(au_array *, void *, + int(*cmp)(const void *, const void *)); +au_linked_list *au_init_list(char *); +void au_empty_list(au_linked_list *, void(*)(void *)); +void au_free_list(au_linked_list *, void(*)(void *)); + +/* External variables */ +extern int log_rotation_method; + +/* Initialize log structure */ +au_log *au_init_log(void) { + au_log *log; + + /* Initialize the log structure itself */ + if((log = calloc(1, sizeof( au_log))) == NULL) { + return NULL; + } + + /* Initialize the host subjects */ + if((log->host_subjects = au_init_array("host_subjects")) == NULL) { + au_free_log(log); + return NULL; + } + + /* Initialize the service subjects */ + if((log->service_subjects = au_init_array("service_subjects")) == NULL) { + au_free_log(log); + return NULL; + } + + /* Initialize the log entry list */ + if((log->entry_list = au_init_list("global log entries")) == NULL) { + au_free_log(log); + return NULL; + } + + /* Initialize the host list */ + if((log->hosts = au_init_array("hosts")) == NULL) { + au_free_log(log); + return NULL; + } + + /* Initialize the service list */ + if((log->services = au_init_array("services")) == NULL) { + au_free_log(log); + return NULL; + } + + /* Initialize the contact list */ + if((log->contacts = au_init_array("contacts")) == NULL) { + au_free_log(log); + return NULL; + } + + return log; + } + +void au_free_log(au_log *log) { + if(NULL == log) return; + if(NULL != log->host_subjects) { + au_free_array(log->host_subjects, au_free_host_void); + } + if(NULL != log->service_subjects) { + au_free_array(log->service_subjects, au_free_service_void); + } + if(NULL != log->hosts) { + au_free_array(log->hosts, au_free_host_void); + } + if(NULL != log->services) { + au_free_array(log->services, au_free_service_void); + } + if(NULL != log->contacts) { + au_free_array(log->contacts, au_free_contact_void); + } + if(NULL != log->entry_list) { + au_free_list(log->entry_list, au_free_log_entry_void); + } + free(log); + } + +/* reads log files for archived data */ +int read_archived_data(time_t start_time, time_t end_time, + int backtrack_archives, unsigned obj_types, unsigned state_types, + unsigned log_types, au_log *log, time_t *last_archive_data_update) { + + char filename[MAX_FILENAME_LENGTH]; + int oldest_archive = 0; + int newest_archive = 0; + int current_archive = 0; + int x; + int retval = 1; + au_host *global_host; + au_host *temp_host; + au_service *temp_service; + au_node *temp_entry; + struct stat adstat; + + /* Determine oldest archive to use when scanning for data + (include backtracked archives as well) */ + oldest_archive = determine_archive_to_use_from_time(start_time); + if(log_rotation_method != LOG_ROTATION_NONE) { + oldest_archive += backtrack_archives; + } + + /* determine most recent archive to use when scanning for data */ + newest_archive = determine_archive_to_use_from_time(end_time); + + if(oldest_archive < newest_archive) { + oldest_archive = newest_archive; + } + + /* read in all the necessary archived logs (from most recent to earliest) */ + for(current_archive = newest_archive; current_archive <= oldest_archive; + current_archive++) { + +#ifdef DEBUG + printf("Reading archive #%d... ", current_archive); +#endif + + /* get the name of the log file that contains this archive */ + get_log_archive_to_use(current_archive, filename, sizeof(filename) - 1); + +#ifdef DEBUG + printf("Archive name: '%s'\n", filename); +#endif + + /* Record the last modification time of the the archive file */ + if(stat(filename, &adstat) < 0) { + /* ENOENT is OK because Nagios may have been down when the + logs were being rotated */ + if(ENOENT != errno) return -1; + } + else { + if(*last_archive_data_update < adstat.st_mtime) { + *last_archive_data_update = adstat.st_mtime; + } + + /* scan the log file for archived state data */ + if(read_log_file(filename, obj_types, state_types, log_types, + log) == 0) { + return 0; /* Memory allocation error */ + } + } + } + + /* Add Nagios log events to all hosts and services found */ + global_host = au_find_host(log->hosts, "*"); + if(NULL != global_host) { + for(temp_entry = global_host->log_entries->head; NULL != temp_entry; + temp_entry = temp_entry->next) { + for(x = 0; x < log->hosts->count; x++) { + temp_host = log->hosts->members[x]; + if(temp_host == global_host) continue; + if(au_list_add_node(temp_host->log_entries, + temp_entry->data, au_cmp_log_entries) == 0) { + retval = 0; + break; + } + } + if(0 == retval) break; + for(x = 0; x < log->services->count; x++) { + temp_service = log->services->members[x]; + if(au_list_add_node(temp_service->log_entries, + temp_entry->data, au_cmp_log_entries) == 0) { + retval = 0; + break; + } + } + if(0 == retval) break; + } + } + + return 1; + } + +/* grabs archives state data from a log file */ +int read_log_file(char *filename, unsigned obj_types, unsigned state_types, + unsigned log_types, au_log *log) { + char *input = NULL; + char *input2 = NULL; + char *temp_buffer = NULL; + time_t time_stamp; + mmapfile *thefile = NULL; + int retval = 1; + + if((thefile = mmap_fopen(filename)) == NULL) { + return 1; + } + + while(1) { + + /* free memory */ + free(input); + free(input2); + input = NULL; + input2 = NULL; + + /* read the next line */ + if((input = mmap_fgets(thefile)) == NULL) break; + + strip(input); + + if((input2 = strdup(input)) == NULL) continue; + + temp_buffer = my_strtok(input2, "]"); + time_stamp = (temp_buffer == NULL) ? (time_t)0 : + (time_t)strtoul(temp_buffer + 1, NULL, 10); + + /* program starts/restarts */ + if(strstr(input, " starting...")) { + if(au_add_nagios_log(log, time_stamp, AU_STATE_PROGRAM_START, + "Program start") == 0) { + retval = 0; + break; + } + } + if(strstr(input, " restarting...")) { + if(au_add_nagios_log(log, time_stamp, AU_STATE_PROGRAM_START, + "Program restart") == 0) { + retval = 0; + break; + } + } + + /* program stops */ + if(strstr(input, " shutting down...")) { + if(au_add_nagios_log(log, time_stamp, AU_STATE_PROGRAM_END, + "Normal program termination") == 0) { + retval = 0; + break; + } + } + if(strstr(input, "Bailing out")) { + if(au_add_nagios_log(log, time_stamp, AU_STATE_PROGRAM_END, + "Abnormal program termination") == 0) { + retval = 0; + break; + } + } + + if(obj_types & AU_OBJTYPE_HOST) { + + /* normal host alerts */ + if((log_types & AU_LOGTYPE_ALERT) && strstr(input, "HOST ALERT:")) { + if(parse_states_and_alerts(input, time_stamp, AU_LOGTYPE_ALERT, + AU_OBJTYPE_HOST, state_types, log) == 0) { + retval = 0; + break; + } + } + + /* host initial states */ + else if((log_types & AU_LOGTYPE_STATE) && + strstr(input, "INITIAL HOST STATE:")) { + if(parse_states_and_alerts(input, time_stamp, + AU_LOGTYPE_STATE_INITIAL, AU_OBJTYPE_HOST, state_types, + log) == 0) { + retval = 0; + break; + } + } + + /* host current states */ + else if((log_types & AU_LOGTYPE_STATE) && + strstr(input, "CURRENT HOST STATE:")) { + if(parse_states_and_alerts(input, time_stamp, + AU_LOGTYPE_STATE_CURRENT, AU_OBJTYPE_HOST, state_types, + log) == 0) { + retval = 0; + break; + } + } + + /* scheduled downtime notices */ + else if((log_types & AU_LOGTYPE_DOWNTIME) && + strstr(input, "HOST DOWNTIME ALERT:")) { + if(parse_downtime_alerts(input, time_stamp, AU_OBJTYPE_HOST, + log) == 0) { + retval = 0; + break; + } + } + + /* host notifications */ + else if((log_types & AU_LOGTYPE_NOTIFICATION) && + strstr(input, "HOST NOTIFICATION:")) { + if(parse_notification_log(input, time_stamp, AU_OBJTYPE_HOST, + log) ==0) { + retval = 0; + break; + } + } + + } + + if(obj_types & AU_OBJTYPE_SERVICE) { + + /* normal service alerts */ + if((log_types & AU_LOGTYPE_ALERT) && + strstr(input, "SERVICE ALERT:")) { + if(parse_states_and_alerts(input, time_stamp, AU_LOGTYPE_ALERT, + AU_OBJTYPE_SERVICE, state_types, log) == 0) { + retval = 0; + break; + } + } + + /* service initial states */ + else if((log_types & AU_LOGTYPE_STATE) && + strstr(input, "INITIAL SERVICE STATE:")) { + if(parse_states_and_alerts(input, time_stamp, + AU_LOGTYPE_STATE_INITIAL, AU_OBJTYPE_SERVICE, + state_types, log) == 0) { + retval = 0; + break; + } + } + + /* service current states */ + else if((log_types & AU_LOGTYPE_STATE) && + strstr(input, "CURRENT SERVICE STATE:")) { + if(parse_states_and_alerts(input, time_stamp, + AU_LOGTYPE_STATE_CURRENT, AU_OBJTYPE_SERVICE, + state_types, log) == 0) { + retval = 0; + break; + } + } + + /* scheduled service downtime notices */ + else if((log_types & AU_LOGTYPE_DOWNTIME) && + strstr(input, "SERVICE DOWNTIME ALERT:")) { + if(parse_downtime_alerts(input, time_stamp, AU_OBJTYPE_SERVICE, + log) == 0) { + retval = 0; + break; + } + } + + /* service notifications */ + else if((log_types & AU_LOGTYPE_NOTIFICATION) && + strstr(input, "SERVICE NOTIFICATION:")) { + if(parse_notification_log(input, time_stamp, + AU_OBJTYPE_SERVICE, log) ==0) { + retval = 0; + break; + } + } + } + } + + /* free memory and close the file */ + free(input); + free(input2); + mmap_fclose(thefile); + return retval; + } + +int au_cmp_log_entries(const void *a, const void *b) { + + au_log_entry *lea = *(au_log_entry **)a; + au_log_entry *leb = *(au_log_entry **)b; + + if(lea->timestamp == leb->timestamp) return 0; + else if(lea->timestamp < leb->timestamp) return -1; + else return 1; + } + +int au_add_nagios_log(au_log *log, time_t timestamp, int type, + char *description) { + + au_log_nagios *nagios_log; + au_log_entry *new_log_entry; + au_host *global_host; + + /* Create the au_log_nagios */ + if((nagios_log = calloc(1, sizeof(au_log_nagios))) == NULL) { + return 0; + } + nagios_log->type = type; + if((nagios_log->description = strdup(description)) == NULL) { + au_free_nagios_log(nagios_log); + return 0; + } + + /* Create the log entry */ + if((new_log_entry = au_add_log_entry(log, timestamp, AU_LOGTYPE_NAGIOS, + (void *)nagios_log)) == NULL) { + au_free_nagios_log(nagios_log); + return 0; + } + + /* Find the au_host object associated with the global host */ + global_host = au_find_host(log->hosts, "*"); + if(NULL == global_host) { + global_host = au_add_host_and_sort(log->hosts, "*"); + if(NULL == global_host) { /* Could not allocate memory */ + return 0; + } + } + + /* Add the entry to the global host */ + if(au_list_add_node(global_host->log_entries, new_log_entry, + au_cmp_log_entries) == 0) { + return 0; + } + + return 1; + } + +void au_free_nagios_log(au_log_nagios *nagios_log) { + if(NULL == nagios_log) return; + if(NULL != nagios_log->description) free(nagios_log->description); + free(nagios_log); + } + +/* parse state and alert log entries */ +int parse_states_and_alerts(char *input, time_t timestamp, int log_type, + unsigned obj_type, unsigned state_types, au_log *log) { + + char *temp_buffer = NULL; + char entry_host_name[MAX_INPUT_BUFFER]; + char entry_svc_description[MAX_INPUT_BUFFER]; + char *plugin_output; + au_host *temp_host_subject; + au_host *temp_host = NULL; + au_service *temp_service_subject; + au_service *temp_service = NULL; + int state_type; + int state; + + /* get host name */ + temp_buffer = my_strtok(NULL, ":"); + temp_buffer = my_strtok(NULL, ";"); + strncpy(entry_host_name, (temp_buffer == NULL) ? "" : + temp_buffer + 1, sizeof(entry_host_name)); + entry_host_name[sizeof(entry_host_name) - 1] = '\x0'; + + switch(obj_type) { + case AU_OBJTYPE_HOST: + if(log->host_subjects->count > 0) { + /* see if there is a corresponding subject for this host */ + temp_host_subject = au_find_host(log->host_subjects, + entry_host_name); + if(temp_host_subject == NULL) return 1; + } + + /* Find the au_host object associated with the host name */ + temp_host = au_find_host(log->hosts, entry_host_name); + if(NULL == temp_host) { + temp_host = au_add_host_and_sort(log->hosts, entry_host_name); + if(NULL == temp_host) { /* Could not allocate memory */ + return 0; + } + } + + break; + case AU_OBJTYPE_SERVICE: + /* get service description */ + temp_buffer = my_strtok(NULL, ";"); + strncpy(entry_svc_description, (temp_buffer == NULL) ? "" : + temp_buffer, sizeof(entry_svc_description)); + entry_svc_description[sizeof(entry_svc_description) - 1] = '\x0'; + + if(log->service_subjects->count > 0) { + /* see if there is a corresponding subject for this service */ + temp_service_subject = au_find_service(log->service_subjects, + entry_host_name, entry_svc_description); + if(temp_service_subject == NULL) return 1; + } + + /* Find the au_service object associated with the service */ + temp_service = au_find_service(log->services, entry_host_name, + entry_svc_description); + if(NULL == temp_service) { + temp_service = au_add_service_and_sort(log->services, + entry_host_name, entry_svc_description); + if(NULL == temp_service) { /* Could not allocate memory */ + return 0; + } + } + + break; + } + + /* state types */ + if(strstr(input, ";SOFT;")) { + if(!(state_types & AU_STATETYPE_SOFT)) return 1; + state_type = AU_STATETYPE_SOFT; + } + if(strstr(input, ";HARD;")) { + if(!(state_types & AU_STATETYPE_HARD)) return 1; + state_type = AU_STATETYPE_HARD; + } + + /* get the plugin output */ + temp_buffer = my_strtok(NULL, ";"); + temp_buffer = my_strtok(NULL, ";"); + temp_buffer = my_strtok(NULL, ";"); + plugin_output = my_strtok(NULL, "\n"); + + switch(obj_type) { + case AU_OBJTYPE_HOST: + if(strstr(input, ";DOWN;")) { + state = AU_STATE_HOST_DOWN; + } + else if(strstr(input, ";UNREACHABLE;")) { + state = AU_STATE_HOST_UNREACHABLE; + } + else if(strstr(input, ";RECOVERY") || strstr(input, ";UP;")) { + state = AU_STATE_HOST_UP; + } + else { + state = AU_STATE_NO_DATA; + state_type = AU_STATETYPE_NO_DATA; + } + if(au_add_alert_or_state_log(log, timestamp, log_type, AU_OBJTYPE_HOST, + (void *)temp_host, state_type, state, plugin_output) == 0) { + return 0; + } + break; + case AU_OBJTYPE_SERVICE: + if(strstr(input, ";CRITICAL;")) { + state = AU_STATE_SERVICE_CRITICAL; + } + else if(strstr(input, ";WARNING;")) { + state = AU_STATE_SERVICE_WARNING; + } + else if(strstr(input, ";UNKNOWN;")) { + state = AU_STATE_SERVICE_UNKNOWN; + } + else if(strstr(input, ";RECOVERY;") || strstr(input, ";OK;")) { + state = AU_STATE_SERVICE_OK; + } + else { + state = AU_STATE_NO_DATA; + state_type = AU_STATETYPE_NO_DATA; + } + if(au_add_alert_or_state_log(log, timestamp, log_type, + AU_OBJTYPE_SERVICE, (void *)temp_service, state_type, state, + plugin_output) == 0) { + return 0; + } + break; + } + + return 1; + } + +int au_add_alert_or_state_log(au_log *log, time_t timestamp, int log_type, + int obj_type, void *object, int state_type, int state, + char *plugin_output) { + + au_log_alert *alert_log; + au_log_entry *new_log_entry; + + /* Create the au_log_alert */ + if((alert_log = au_create_alert_or_state_log(obj_type, object, state_type, + state, plugin_output)) == NULL) { + return 0; + } + + /* Create the log entry */ + if((new_log_entry = au_add_log_entry(log, timestamp, log_type, + (void *)alert_log)) == NULL) { + au_free_alert_log(alert_log); + return 0; + } + + /* Add the log entry to the logs for the object supplied */ + switch(obj_type) { + case AU_OBJTYPE_HOST: + if(au_list_add_node(((au_host *)object)->log_entries, + new_log_entry, au_cmp_log_entries) == 0) { + return 0; + } + break; + case AU_OBJTYPE_SERVICE: + if(au_list_add_node(((au_service *)object)->log_entries, + new_log_entry, au_cmp_log_entries) == 0) { + return 0; + } + break; + } + + return 1; + } + +au_log_alert *au_create_alert_or_state_log(int obj_type, void *object, + int state_type, int state, char *plugin_output) { + + au_log_alert *alert_log; + + /* Create the au_log_alert */ + if((alert_log = calloc(1, sizeof(au_log_alert))) == NULL) { + return NULL; + } + alert_log->obj_type = obj_type; + alert_log->object = object; + alert_log->state_type = state_type; + alert_log->state = state; + alert_log->plugin_output = NULL; + if(plugin_output != NULL) { + if((alert_log->plugin_output = strdup(plugin_output)) == NULL) { + au_free_alert_log(alert_log); + return NULL; + } + } + + return alert_log; + } + +void au_free_alert_log(au_log_alert *alert_log) { + if(NULL == alert_log) return; + if(NULL != alert_log->plugin_output) free(alert_log->plugin_output); + free(alert_log); + } + +/* parse archive log downtime notifications */ +int parse_downtime_alerts(char *input, time_t timestamp, unsigned obj_type, + au_log *log) { + + char *temp_buffer = NULL; + char entry_host_name[MAX_INPUT_BUFFER]; + char entry_svc_description[MAX_INPUT_BUFFER]; + au_host *temp_host_subject; + au_host *temp_host = NULL; + au_service *temp_service_subject; + au_service *temp_service = NULL; + + /* get host name */ + temp_buffer = my_strtok(NULL, ":"); + temp_buffer = my_strtok(NULL, ";"); + strncpy(entry_host_name, (temp_buffer == NULL) ? "" : + temp_buffer + 1, sizeof(entry_host_name)); + entry_host_name[sizeof(entry_host_name) - 1] = '\x0'; + + switch(obj_type) { + case AU_OBJTYPE_HOST: + if(log->host_subjects->count > 0) { + /* see if there is a corresponding subject for this host */ + temp_host_subject = au_find_host(log->host_subjects, + entry_host_name); + if(temp_host_subject == NULL) return 1; + } + + /* Find the au_host object associated with the host name */ + temp_host = au_find_host(log->hosts, entry_host_name); + if(NULL == temp_host) { + temp_host = au_add_host_and_sort(log->hosts, entry_host_name); + if(NULL == temp_host) { /* Could not allocate memory */ + return 0; + } + } + + break; + case AU_OBJTYPE_SERVICE: + /* get service description */ + temp_buffer = my_strtok(NULL, ";"); + strncpy(entry_svc_description, (temp_buffer == NULL) ? "" : + temp_buffer, sizeof(entry_svc_description)); + entry_svc_description[sizeof(entry_svc_description) - 1] = '\x0'; + + if(log->service_subjects->count > 0) { + /* see if there is a corresponding subject for this service */ + temp_service_subject = au_find_service(log->service_subjects, + entry_host_name, entry_svc_description); + if(temp_service_subject == NULL) return 1; + } + + /* Find the au_service object associated with the service */ + temp_service = au_find_service(log->services, entry_host_name, + entry_svc_description); + if(NULL == temp_service) { + temp_service = au_add_service_and_sort(log->services, + entry_host_name, entry_svc_description); + if(NULL == temp_service) { /* Could not allocate memory */ + return 0; + } + } + + break; + } + + switch(obj_type) { + case AU_OBJTYPE_HOST: + if(strstr(input, ";STARTED;")) { + if(au_add_downtime_log(log, timestamp, AU_OBJTYPE_HOST, + (void *)temp_host, AU_STATE_DOWNTIME_START) == 0) { + return 0; + } + } + else { + if(au_add_downtime_log(log, timestamp, AU_OBJTYPE_HOST, + (void *)temp_host, AU_STATE_DOWNTIME_END) == 0) { + return 0; + } + } + break; + case AU_OBJTYPE_SERVICE: + if(strstr(input, ";STARTED;")) { + if(au_add_downtime_log(log, timestamp, AU_OBJTYPE_SERVICE, + (void *)temp_service, AU_STATE_DOWNTIME_START) == 0) { + return 0; + } + } + else { + if(au_add_downtime_log(log, timestamp, AU_OBJTYPE_SERVICE, + (void *)temp_service, AU_STATE_DOWNTIME_END) == 0) { + return 0; + } + } + break; + } + + return 1; + } + +int au_add_downtime_log(au_log *log, time_t timestamp, int obj_type, + void *object, int downtime_type) { + + au_log_downtime *downtime_log; + au_log_entry *new_log_entry; + + /* Create the au_log_downtime */ + if((downtime_log = calloc(1, sizeof(au_log_downtime))) == NULL) { + return 0; + } + downtime_log->obj_type = obj_type; + downtime_log->object = object; + downtime_log->downtime_type = downtime_type; + + /* Create the log entry */ + if((new_log_entry = au_add_log_entry(log, timestamp, AU_LOGTYPE_DOWNTIME, + (void *)downtime_log)) == NULL) { + au_free_downtime_log(downtime_log); + return 0; + } + + /* Add the log entry to the logs for the object supplied */ + switch(obj_type) { + case AU_OBJTYPE_HOST: + if(au_list_add_node(((au_host *)object)->log_entries, + new_log_entry, au_cmp_log_entries) == 0) { + return 0; + } + break; + case AU_OBJTYPE_SERVICE: + if(au_list_add_node(((au_service *)object)->log_entries, + new_log_entry, au_cmp_log_entries) == 0) { + return 0; + } + break; + } + + return 1; + } + +void au_free_downtime_log(au_log_downtime *downtime_log) { + if(NULL == downtime_log) return; + free(downtime_log); + } + +int parse_notification_log(char *input, time_t timestamp, int obj_type, + au_log *log) { + + char entry_contact_name[MAX_INPUT_BUFFER]; + char entry_host_name[MAX_INPUT_BUFFER]; + char entry_svc_description[MAX_INPUT_BUFFER]; + char alert_level[MAX_INPUT_BUFFER]; + char method_name[MAX_INPUT_BUFFER]; + int notification_detail_type = AU_NOTIFICATION_NO_DATA; + char *temp_buffer = NULL; + au_host *temp_host_subject; + au_service *temp_service_subject; + au_contact *temp_contact; + au_host *temp_host = NULL; + au_service *temp_service = NULL; + + /* get the contact name */ + temp_buffer = my_strtok(NULL, ":"); + temp_buffer = my_strtok(NULL, ";"); + strncpy(entry_contact_name, (temp_buffer == NULL) ? "" : + temp_buffer + 1, sizeof(entry_contact_name)); + entry_contact_name[sizeof(entry_contact_name) - 1] = '\x0'; + + /* Find the au_contact object associated with the contact name */ + temp_contact = au_find_contact(log->contacts, entry_contact_name); + if(NULL == temp_contact) { + temp_contact = au_add_contact_and_sort(log->contacts, + entry_contact_name); + if(NULL == temp_contact) { /* Could not allocate memory */ + return 0; + } + } + + /* get the host name */ + temp_buffer = (char *)my_strtok(NULL, ";"); + snprintf(entry_host_name, sizeof(entry_host_name), "%s", + (temp_buffer == NULL) ? "" : temp_buffer); + entry_host_name[sizeof(entry_host_name) - 1] = '\x0'; + + switch(obj_type) { + case AU_OBJTYPE_HOST: + if(log->host_subjects->count > 0) { + /* see if there is a corresponding subject for this host */ + temp_host_subject = au_find_host(log->host_subjects, + entry_host_name); + if(temp_host_subject == NULL) return 1; + } + + /* Find the au_host object associated with the host name */ + temp_host = au_find_host(log->hosts, entry_host_name); + if(NULL == temp_host) { + temp_host = au_add_host_and_sort(log->hosts, entry_host_name); + if(NULL == temp_host) { /* Could not allocate memory */ + return 0; + } + } + + break; + case AU_OBJTYPE_SERVICE: + /* get service description */ + temp_buffer = my_strtok(NULL, ";"); + strncpy(entry_svc_description, (temp_buffer == NULL) ? "" : + temp_buffer, sizeof(entry_svc_description)); + entry_svc_description[sizeof(entry_svc_description) - 1] = '\x0'; + + if(log->service_subjects->count > 0) { + /* see if there is a corresponding subject for this service */ + temp_service_subject = au_find_service(log->service_subjects, + entry_host_name, entry_svc_description); + if(temp_service_subject == NULL) return 1; + } + + /* Find the au_service object associated with the service */ + temp_service = au_find_service(log->services, entry_host_name, + entry_svc_description); + if(NULL == temp_service) { + temp_service = au_add_service_and_sort(log->services, + entry_host_name, entry_svc_description); + if(NULL == temp_service) { /* Could not allocate memory */ + return 0; + } + } + + break; + } + + /* get the alert level */ + temp_buffer = (char *)my_strtok(NULL, ";"); + snprintf(alert_level, sizeof(alert_level), "%s", + (temp_buffer == NULL) ? "" : temp_buffer); + alert_level[sizeof(alert_level) - 1] = '\x0'; + + switch(obj_type) { + case AU_OBJTYPE_HOST: + if(!strcmp(alert_level, "DOWN")) { + notification_detail_type = AU_NOTIFICATION_HOST_DOWN; + } + else if(!strcmp(alert_level, "UNREACHABLE")) { + notification_detail_type = AU_NOTIFICATION_HOST_UNREACHABLE; + } + else if(!strcmp(alert_level, "RECOVERY") || + !strcmp(alert_level, "UP")) { + notification_detail_type = AU_NOTIFICATION_HOST_RECOVERY; + } + else if(strstr(alert_level, "CUSTOM (")) { + notification_detail_type = AU_NOTIFICATION_HOST_CUSTOM; + } + else if(strstr(alert_level, "ACKNOWLEDGEMENT (")) { + notification_detail_type = AU_NOTIFICATION_HOST_ACK; + } + else if(strstr(alert_level, "FLAPPINGSTART (")) { + notification_detail_type = AU_NOTIFICATION_HOST_FLAPPING_START; + } + else if(strstr(alert_level, "FLAPPINGSTOP (")) { + notification_detail_type = AU_NOTIFICATION_HOST_FLAPPING_STOP; + } + break; + case AU_OBJTYPE_SERVICE: + if(!strcmp(alert_level, "CRITICAL")) { + notification_detail_type = AU_NOTIFICATION_SERVICE_CRITICAL; + } + else if(!strcmp(alert_level, "WARNING")) { + notification_detail_type = AU_NOTIFICATION_SERVICE_WARNING; + } + else if(!strcmp(alert_level, "RECOVERY") || + !strcmp(alert_level, "OK")) { + notification_detail_type = AU_NOTIFICATION_SERVICE_RECOVERY; + } + else if(strstr(alert_level, "CUSTOM (")) { + notification_detail_type = AU_NOTIFICATION_SERVICE_CUSTOM; + } + else if(strstr(alert_level, "ACKNOWLEDGEMENT (")) { + notification_detail_type = AU_NOTIFICATION_SERVICE_ACK; + } + else if(strstr(alert_level, "FLAPPINGSTART (")) { + notification_detail_type = AU_NOTIFICATION_SERVICE_FLAPPING_START; + } + else if(strstr(alert_level, "FLAPPINGSTOP (")) { + notification_detail_type = AU_NOTIFICATION_SERVICE_FLAPPING_STOP; + } + else { + notification_detail_type = AU_NOTIFICATION_SERVICE_UNKNOWN; + } + break; + } + + /* get the method name */ + temp_buffer = (char *)my_strtok(NULL, ";"); + snprintf(method_name, sizeof(method_name), "%s", + (temp_buffer == NULL) ? "" : temp_buffer); + method_name[sizeof(method_name) - 1] = '\x0'; + + /* move to the informational message */ + temp_buffer = my_strtok(NULL, ";"); + + /* Create the log entry */ + switch(obj_type) { + case AU_OBJTYPE_HOST: + if(au_add_notification_log(log, timestamp, AU_OBJTYPE_HOST, + (void *)temp_host, temp_contact, notification_detail_type, + method_name, temp_buffer) == 0) { + return 0; + } + break; + case AU_OBJTYPE_SERVICE: + if(au_add_notification_log(log, timestamp, AU_OBJTYPE_SERVICE, + (void *)temp_service, temp_contact, notification_detail_type, + method_name, temp_buffer) == 0) { + return 0; + } + break; + } + + return 1; + } + +int au_add_notification_log(au_log *log, time_t timestamp, int obj_type, + void *object, au_contact *contact, int notification_type, + char *method, char *message) { + + au_log_notification *notification_log; + au_log_entry *new_log_entry; + + /* Create the au_log_downtime */ + if((notification_log = calloc(1, sizeof(au_log_notification))) == NULL) { + return 0; + } + notification_log->obj_type = obj_type; + notification_log->object = object; + notification_log->contact = contact; + notification_log->notification_type = notification_type; + if((notification_log->method = strdup(method)) + == NULL) { + au_free_notification_log(notification_log); + return 0; + } + if((notification_log->message = strdup(message)) == NULL) { + au_free_notification_log(notification_log); + return 0; + } + + /* Create the log entry */ + if((new_log_entry = au_add_log_entry(log, timestamp, + AU_LOGTYPE_NOTIFICATION, (void *)notification_log)) == NULL) { + au_free_notification_log(notification_log); + return 0; + } + + /* Add the log entry to the logs for the object supplied */ + switch(obj_type) { + case AU_OBJTYPE_HOST: + if(au_list_add_node((void *)((au_host *)object)->log_entries, + new_log_entry, au_cmp_log_entries) == 0) { + return 0; + } + break; + case AU_OBJTYPE_SERVICE: + if(au_list_add_node((void *)((au_service *)object)->log_entries, + new_log_entry, au_cmp_log_entries) == 0) { + return 0; + } + break; + } + + return 1; + } + +void au_free_notification_log(au_log_notification *notification_log) { + if(NULL == notification_log) return; + if(NULL != notification_log->method) free(notification_log->method); + if(NULL != notification_log->message) free(notification_log->message); + free(notification_log); + } + +au_log_entry *au_add_log_entry(au_log *log, time_t timestamp, int entry_type, + void *entry) { + + au_log_entry *new_log_entry; + + /* Create the au_log_entry */ + if((new_log_entry = calloc(1, sizeof(au_log_entry))) == NULL) { + return NULL; + } + new_log_entry->timestamp = timestamp; + new_log_entry->entry_type = entry_type; + new_log_entry->entry = entry; + + if(au_list_add_node(log->entry_list, (void *)new_log_entry, + au_cmp_log_entries) == NULL) { + au_free_log_entry(new_log_entry); + return NULL; + } + + return new_log_entry; + } + +void au_free_log_entry_void(void *log_entry) { + au_free_log_entry((au_log_entry *)log_entry); + } + +void au_free_log_entry(au_log_entry *log_entry) { + if(NULL == log_entry) return; + switch(log_entry->entry_type) { + case AU_LOGTYPE_ALERT: + case AU_LOGTYPE_STATE: + au_free_alert_log((au_log_alert *)log_entry->entry); + break; + case AU_LOGTYPE_NOTIFICATION: + au_free_notification_log((au_log_notification *)log_entry->entry); + break; + case AU_LOGTYPE_DOWNTIME: + au_free_downtime_log((au_log_downtime *)log_entry->entry); + break; + case AU_LOGTYPE_NAGIOS: + au_free_nagios_log((au_log_nagios *)log_entry->entry); + break; + } + free(log_entry); + } + +/* Add a host to a host list and sort the list */ +au_host *au_add_host_and_sort(au_array *host_list, char *name) { + + au_host *temp_host; + + temp_host = au_add_host(host_list, name); + if(NULL != temp_host) { + au_sort_array(host_list, au_cmp_hosts); + } + + return temp_host; + } + +/* Add a host to a host list */ +au_host *au_add_host(au_array *host_list, char *name) { + + au_host *new_host; + char buf[8192]; + + /* Should have been allocated during au_log_init() */ + if(NULL == host_list) { + return NULL; + } + + /* Create the host */ + if((new_host = calloc(1, sizeof(au_host))) == NULL) { + return NULL; + } + if((new_host->name = strdup(name)) == NULL) { + au_free_host(new_host); + return NULL; + } + new_host->hostp = find_host(name); + new_host->availability = NULL; + snprintf(buf, sizeof(buf) - 1, "Host %s log entries", name); + if((new_host->log_entries = au_init_list(buf)) == NULL) { + au_free_host(new_host); + return NULL; + } + + /* Add it to the list of hosts */ + if(0 == au_array_append_member(host_list, (void *)new_host)) { + au_free_host(new_host); + return NULL; + } + + return new_host; + } + +void au_free_host_void(void *host) { + au_free_host((au_host *)host); + } + +void au_free_host(au_host *host) { + if(NULL == host) return; + if(NULL != host->name) free(host->name); + /* Do not free the log entry data here because they are freed when the + master list's log entries are freed */ + if(NULL != host->log_entries) au_free_list(host->log_entries, NULL); + if(NULL != host->availability) free(host->availability); + free(host); + return; + } + +int au_cmp_hosts(const void *a, const void *b) { + au_host *hosta = *(au_host **)a; + au_host *hostb = *(au_host **)b; + + return strcmp(hosta->name, hostb->name); + } + +au_host *au_find_host(au_array *host_list, char *name) { + + au_host key; + void *found; + + if(NULL == host_list) return NULL; + key.name = name; + found = au_find_in_array(host_list, (void *)&key, au_cmp_hosts); + if(NULL == found) return NULL; + return *(au_host **)found; + } + +au_service *au_add_service_and_sort(au_array *service_list, char *host_name, + char *description) { + + au_service *temp_service; + + temp_service = au_add_service(service_list, host_name, description); + if(NULL != temp_service) { + au_sort_array(service_list, au_cmp_services); + } + + return temp_service; + } + +au_service *au_add_service(au_array *service_list, char *host_name, + char *description) { + + au_service *new_service; + char buf[8192]; + + /* Should have been allocated during au_log_init() */ + if(NULL == service_list) { + return NULL; + } + + /* Create the service */ + if((new_service = calloc(1, sizeof(au_service))) == NULL) { + return NULL; + } + if((new_service->host_name = strdup(host_name)) == NULL) { + au_free_service(new_service); + return NULL; + } + if((new_service->description = strdup(description)) == NULL) { + au_free_service(new_service); + return NULL; + } + new_service->servicep = find_service(host_name, description); + new_service->availability = NULL; + snprintf(buf, sizeof(buf) - 1, "Service %s:%s log entries", host_name, + description); + if((new_service->log_entries = au_init_list(buf)) == NULL) { + au_free_service(new_service); + return NULL; + } + + /* Add it to the list of services */ + if(0 == au_array_append_member(service_list, (void *)new_service)) { + au_free_service(new_service); + return NULL; + } + + return new_service; + } + +void au_free_service_void(void *service) { + au_free_service((au_service *)service); + } + +void au_free_service(au_service *service) { + if(NULL == service) return; + if(NULL != service->host_name) free(service->host_name); + if(NULL != service->description) free(service->description); + /* Do not free the log entry data here because they are freed when the + master list's log entries are freed */ + if(NULL != service->log_entries) au_free_list(service->log_entries, NULL); + if(NULL != service->availability) free(service->availability); + free(service); + return; + } + +au_service *au_find_service(au_array *service_list, char *host_name, + char *description) { + + au_service key; + void *found; + + if(NULL == service_list) return NULL; + key.host_name = host_name; + key.description = description; + found = (au_service *)au_find_in_array(service_list, (void *)&key, + au_cmp_services); + if(NULL == found) return NULL; + return *(au_service **)found; + } + +int au_cmp_services(const void *a, const void *b) { + + au_service *servicea = *(au_service **)a; + au_service *serviceb = *(au_service **)b; + int host_result; + + host_result = strcmp(servicea->host_name, serviceb->host_name); + if(0 == host_result) { + return strcmp(servicea->description, serviceb->description); + } + else { + return host_result; + } + } + +/* Add a contact to a contact list and sort the list */ +au_contact *au_add_contact_and_sort(au_array *contact_list, char *name) { + + au_contact *temp_contact; + + temp_contact = au_add_contact(contact_list, name); + if(NULL != temp_contact) { + au_sort_array(contact_list, au_cmp_contacts); + } + return temp_contact; + } + +/* Add a contact to a contact list */ +au_contact *au_add_contact(au_array *contact_list, char *name) { + + au_contact *new_contact; + + /* Should have been allocated during au_log_init() */ + if(NULL == contact_list) { + return NULL; + } + + /* Create the contact */ + if((new_contact = calloc(1, sizeof(au_contact))) == NULL) { + return NULL; + } + if((new_contact->name = strdup(name)) == NULL) { + au_free_contact(new_contact); + return NULL; + } + + /* Add it to the list of contacts */ + if(0 == au_array_append_member(contact_list, (void *)new_contact)) { + au_free_contact(new_contact); + return NULL; + } + + return new_contact; + } + +void au_free_contact_void(void *contact) { + au_free_contact((au_contact *)contact); + } + +void au_free_contact(au_contact *contact) { + if(NULL == contact) return; + if(NULL != contact->name) free(contact->name); + free(contact); + return; + } + +int au_cmp_contacts(const void *a, const void *b) { + + au_contact *contacta = (au_contact *)a; + au_contact *contactb = (au_contact *)b; + + return strcmp(contacta->name, contactb->name); + } + +au_contact *au_find_contact(au_array *contact_list, char *name) { + + au_contact key; + void *found; + + if(NULL == contact_list) return NULL; + key.name = name; + found = (au_contact *)au_find_in_array(contact_list, (void *)&key, + au_cmp_contacts); + if(NULL == found) return NULL; + return *(au_contact **)found; + } + +au_array *au_init_array(char *label) { + au_array *array; + + if((array = calloc(1, sizeof(au_array))) == NULL) { + return NULL; + } + array->label = NULL; + if(NULL != label) { + if((array->label = strdup(label)) == NULL) { + free(array); + return NULL; + } + } + array->size = 0; + array->count = 0; + array->members = (void **)NULL; + array->new = 0; + + return array; + } + +void au_free_array(au_array *array, void(*datafree)(void *)) { + + int x; + + if(NULL == array) return; + if(NULL != array->label) free(array->label); + for(x = 0; x < array->count; x++) { + if((NULL != datafree) && (NULL != array->members[x])) { + datafree(array->members[x]); + } + } + if(NULL != array->members) free(array->members); + free(array); + return; + } + +int au_array_append_member(au_array *array, void *member) { + + /* Check whether the list needs to be grown before adding the member */ + if(array->count == array->size) { + /* Need to grow the list */ + if(0 == array->count) { + /* Never had any members */ + if((array->members = (void **)calloc(AU_INITIAL_LIST_SIZE, + sizeof(void *))) == NULL) { + return 0; + } + array->size = AU_INITIAL_LIST_SIZE; + } + else { + /* Double the size of the list */ + if((array->members = (void **)realloc(array->members, + sizeof(void *) * array->size * 2)) == NULL) { + return 0; + } + array->size *= 2; + } + } + + array->members[array->count] = member; + array->new++; /* Number of appends since last sort */ + array->count++; + + return 1; + } + +void au_sort_array(au_array *array, int(*cmp)(const void *, const void *)) { + + /* TODO: Use array->new to determine whether to do a quick sort or a + bubble sort */ + qsort(array->members, array->count, sizeof(void *), cmp); + array->new = 0; + } + +void *au_find_in_array(au_array *array, void *key, + int(*cmp)(const void *, const void *)) { + + return bsearch(&key, array->members, array->count, sizeof(void *), cmp); + } + +au_linked_list *au_init_list(char *label) { + + au_linked_list *list; + + if((list = calloc(1, sizeof(au_linked_list))) == NULL) { + return NULL; + } + list->label = NULL; + if(NULL != label) { + if((list->label = strdup(label)) == NULL) { + free(list); + return NULL; + } + } + list->head = (au_node *)0; + list->last_new = (au_node *)0; + + return list; + } + +au_node *au_list_add_node(au_linked_list *list, void *data, + int(*cmp)(const void *, const void *)) { + + au_node *new_node; + au_node *temp_node; + + /* Create the new node */ + if((new_node = calloc(1, sizeof(au_node))) == NULL) { + return NULL; + } + new_node->data = data; + new_node->next = NULL; + + /* Add it to the list */ + if(NULL == list->head) { + /* If the list is empty, add this node as the only item in the list */ + list->head = new_node; + } + else if(cmp(&(list->last_new->data), &(new_node->data)) <= 0) { + /* The new node goes somewhere on the list downstream of the most + recently added node */ + if(NULL == list->last_new->next) { + /* If the most recently added node is the last one on the list, + append the list with this node */ + list->last_new->next = new_node; + } + else if(cmp(&(list->last_new->next->data), &(new_node->data)) > 0) { + /* If the next node is "greater than" the new node, the new + node goes here */ + new_node->next = list->last_new->next; + list->last_new->next = new_node; + } + else { + /* Visit each node downstream in the list until we reach the + end of the list or until we find a node whose next + node is "greater than" the new node */ + temp_node = list->last_new; + while((NULL != temp_node->next) && (cmp(&(temp_node->next->data), + &(new_node->data)) <= 0)) { + temp_node = temp_node->next; + } + if(NULL == temp_node->next) { + /* If we reach the end of the list, the new node gets + appended */ + temp_node->next = new_node; + } + else { + /* Otherwise, the new node gets inserted here */ + new_node->next = temp_node->next; + temp_node->next = new_node; + } + } + } + else { + /* The new node is "less than" the last new node. Visit each node + starting at the beginning of the list until we reach the end of + the list (which shouldn't happen because that case was covered + earlier) or we find a node whose next node is is "greater than" + the new node. */ + temp_node = list->head; + while((NULL != temp_node->next) && (cmp(&(temp_node->next->data), + &(new_node->data)) <= 0)) { + temp_node = temp_node->next; + } + if(temp_node == list->head) { + /* We insert at the beginning of the list */ + new_node->next = list->head; + list->head = new_node; + } + else if(NULL == temp_node->next) { + /* If we reach the end of the list, the new node gets appended */ + temp_node->next = new_node; + } + else { + /* Otherwise, the new node gets inserted here */ + new_node->next = temp_node->next; + temp_node->next = new_node; + } + } + list->last_new = new_node; + + return new_node; + } + +void au_empty_list(au_linked_list *list, void(*datafree)(void *)) { + + au_node *temp_node1; + au_node *temp_node2; + + temp_node1 = list->head; + while(NULL != temp_node1) { + temp_node2 = temp_node1->next; + if((NULL != datafree) && (NULL != temp_node1->data)) { + datafree(temp_node1->data); + } + free(temp_node1); + temp_node1 = temp_node2; + } + list->head = NULL; + list->last_new = NULL; + } + +void au_free_list(au_linked_list *list, void(*datafree)(void *)) { + + if(NULL == list) return; + if(NULL != list->label) free(list->label); + au_empty_list(list, datafree); + free(list); + } diff --git a/cgi/avail.c b/cgi/avail.c index db9f0b5..c61262e 100644 --- a/cgi/avail.c +++ b/cgi/avail.c @@ -2,8 +2,6 @@ * * AVAIL.C - Nagios Availability CGI * - * Copyright (c) 2000-2010 Ethan Galstad (egalstad@nagios.org) - * Last Modified: 08-05-2010 * * License: * @@ -37,14 +35,6 @@ extern char url_html_path[MAX_FILENAME_LENGTH]; extern char url_images_path[MAX_FILENAME_LENGTH]; extern char url_stylesheets_path[MAX_FILENAME_LENGTH]; -extern host *host_list; -extern hostgroup *hostgroup_list; -extern servicegroup *servicegroup_list; -extern service *service_list; -extern timeperiod *timeperiod_list; - -extern int log_rotation_method; - #ifndef max #define max(a,b) (((a) > (b)) ? (a) : (b)) #endif @@ -232,14 +222,14 @@ void write_log_entries(avail_subject *); void get_running_average(double *, double, int); -void host_report_url(char *, char *); -void service_report_url(char *, char *, char *); +void host_report_url(const char *, const char *); +void service_report_url(const char *, const char *, const char *); void compute_report_times(void); int convert_host_state_to_archived_state(int); int convert_service_state_to_archived_state(int); -void add_global_archived_state(int, int, time_t, char *); -void add_archived_state(int, int, time_t, char *, avail_subject *); +void add_global_archived_state(int, int, time_t, const char *); +void add_archived_state(int, int, time_t, const char *, avail_subject *); void add_scheduled_downtime(int, time_t, avail_subject *); void free_availability_data(void); void free_archived_state_list(archived_state *); @@ -267,7 +257,6 @@ int output_format = HTML_OUTPUT; int main(int argc, char **argv) { - int result = OK; char temp_buffer[MAX_INPUT_BUFFER]; char start_timestring[MAX_DATETIME_LENGTH]; char end_timestring[MAX_DATETIME_LENGTH]; @@ -288,41 +277,7 @@ int main(int argc, char **argv) { /* reset internal CGI variables */ reset_cgi_vars(); - /* read the CGI configuration file */ - result = read_cgi_config_file(get_cgi_config_location()); - if(result == ERROR) { - document_header(FALSE); - cgi_config_file_error(get_cgi_config_location()); - document_footer(); - return ERROR; - } - - /* read the main configuration file */ - result = read_main_config_file(main_config_file); - if(result == ERROR) { - document_header(FALSE); - main_config_file_error(main_config_file); - document_footer(); - return ERROR; - } - - /* read all object configuration data */ - result = read_all_object_configuration_data(main_config_file, READ_ALL_OBJECT_DATA); - if(result == ERROR) { - document_header(FALSE); - object_data_error(); - document_footer(); - return ERROR; - } - - /* read all status data */ - result = read_all_status_data(get_cgi_config_location(), READ_ALL_STATUS_DATA); - if(result == ERROR) { - document_header(FALSE); - status_data_error(); - document_footer(); - return ERROR; - } + cgi_init(document_header, document_footer, READ_ALL_OBJECT_DATA, READ_ALL_STATUS_DATA); /* initialize time period to last 24 hours */ time(¤t_time); @@ -489,7 +444,10 @@ int main(int argc, char **argv) { printf("
%s to %s
\n", start_timestring, end_timestring); get_time_breakdown((time_t)(t2 - t1), &days, &hours, &minutes, &seconds); - printf("
Duration: %dd %dh %dm %ds
\n", days, hours, minutes, seconds); + printf("
Duration: %dd %dh %dm %ds", days, hours, minutes, seconds); + if (current_timeperiod) + printf("
(using timeperiod %s)", current_timeperiod->name); + printf("
\n"); } printf("\n"); @@ -1078,7 +1036,7 @@ void document_header(int use_stylesheet) { printf("Expires: %s\r\n", date_time); if(output_format == HTML_OUTPUT) - printf("Content-type: text/html\r\n\r\n"); + printf("Content-type: text/html; charset=utf-8\r\n\r\n"); else { printf("Content-type: text/csv\r\n\r\n"); return; @@ -1141,7 +1099,6 @@ int process_cgivars(void) { /* do some basic length checking on the variable identifier to prevent buffer overflows */ if(strlen(variables[x]) >= MAX_INPUT_BUFFER - 1) { - x++; continue; } @@ -1635,7 +1592,7 @@ int process_cgivars(void) { } for(temp_timeperiod = timeperiod_list; temp_timeperiod != NULL; temp_timeperiod = temp_timeperiod->next) { - if(!strcmp(url_encode(temp_timeperiod->name), variables[x])) { + if(!strcmp(temp_timeperiod->name, variables[x])) { current_timeperiod = temp_timeperiod; break; } @@ -1679,7 +1636,6 @@ void compute_subject_availability(avail_subject *subject, time_t current_time) { int have_some_real_data = FALSE; hoststatus *hststatus = NULL; servicestatus *svcstatus = NULL; - int first_real_state = AS_NO_DATA; time_t initial_assumed_time; int initial_assumed_state = AS_NO_DATA; int error; @@ -1710,11 +1666,11 @@ void compute_subject_availability(avail_subject *subject, time_t current_time) { if(subject->type == HOST_SUBJECT) { if(hststatus != NULL) { - if(hststatus->status == HOST_DOWN) + if(hststatus->status == SD_HOST_DOWN) subject->last_known_state = AS_HOST_DOWN; - else if(hststatus->status == HOST_UNREACHABLE) + else if(hststatus->status == SD_HOST_UNREACHABLE) subject->last_known_state = AS_HOST_UNREACHABLE; - else if(hststatus->status == HOST_UP) + else if(hststatus->status == SD_HOST_UP) subject->last_known_state = AS_HOST_UP; else subject->last_known_state = AS_NO_DATA; @@ -1723,9 +1679,6 @@ void compute_subject_availability(avail_subject *subject, time_t current_time) { /* add a dummy archived state item, so something can get graphed */ add_archived_state(subject->last_known_state, AS_HARD_STATE, t1, "Current Host State Assumed (Faked Log Entry)", subject); - - /* use the current state as the last known real state */ - first_real_state = subject->last_known_state; } } } @@ -1747,9 +1700,6 @@ void compute_subject_availability(avail_subject *subject, time_t current_time) { /* add a dummy archived state item, so something can get graphed */ add_archived_state(subject->last_known_state, AS_HARD_STATE, t1, "Current Service State Assumed (Faked Log Entry)", subject); - - /* use the current state as the last known real state */ - first_real_state = subject->last_known_state; } } } @@ -1805,13 +1755,13 @@ void compute_subject_availability(avail_subject *subject, time_t current_time) { } else { switch(hststatus->status) { - case HOST_DOWN: + case SD_HOST_DOWN: initial_assumed_state = AS_HOST_DOWN; break; - case HOST_UNREACHABLE: + case SD_HOST_UNREACHABLE: initial_assumed_state = AS_HOST_UNREACHABLE; break; - case HOST_UP: + case SD_HOST_UP: initial_assumed_state = AS_HOST_UP; break; default: @@ -1981,10 +1931,9 @@ void compute_subject_availability(avail_subject *subject, time_t current_time) { /* computes availability times */ void compute_subject_availability_times(int first_state, int last_state, time_t real_start_time, time_t start_time, time_t end_time, avail_subject *subject, archived_state *as) { int start_state; - int end_state; unsigned long state_duration; struct tm *t; - unsigned long midnight_today; + time_t midnight_today; int weekday; timerange *temp_timerange; unsigned long temp_duration; @@ -2116,12 +2065,6 @@ void compute_subject_availability_times(int first_state, int last_state, time_t subject->last_known_state = first_state; } - /* special case if last entry was program stop */ - if(last_state == AS_PROGRAM_END) - end_state = first_state; - else - end_state = last_state; - /* save "processed state" info */ as->processed_state = start_state; @@ -2166,8 +2109,8 @@ void compute_subject_downtime(avail_subject *subject, time_t current_time) { archived_state *temp_sd; time_t start_time; time_t end_time; - int host_downtime_depth = 0; - int service_downtime_depth = 0; + int host_downtime_state = 0; + int service_downtime_state = 0; int process_chunk = FALSE; #ifdef DEBUG2 @@ -2209,20 +2152,20 @@ void compute_subject_downtime(avail_subject *subject, time_t current_time) { break; if(temp_sd->entry_type == AS_HOST_DOWNTIME_START) - host_downtime_depth++; + host_downtime_state = 1; else if(temp_sd->entry_type == AS_HOST_DOWNTIME_END) - host_downtime_depth--; + host_downtime_state = 0; else if(temp_sd->entry_type == AS_SVC_DOWNTIME_START) - service_downtime_depth++; + service_downtime_state = 1; else if(temp_sd->entry_type == AS_SVC_DOWNTIME_END) - service_downtime_depth--; + service_downtime_state = 0; else continue; process_chunk = FALSE; if(temp_sd->entry_type == AS_HOST_DOWNTIME_START || temp_sd->entry_type == AS_SVC_DOWNTIME_START) process_chunk = TRUE; - else if(subject->type == SERVICE_SUBJECT && (host_downtime_depth > 0 || service_downtime_depth > 0)) + else if(subject->type == SERVICE_SUBJECT && (host_downtime_state == 1 || service_downtime_state == 1)) process_chunk = TRUE; /* process this specific "chunk" of scheduled downtime */ @@ -2257,10 +2200,9 @@ void compute_subject_downtime(avail_subject *subject, time_t current_time) { /* computes downtime times */ void compute_subject_downtime_times(time_t start_time, time_t end_time, avail_subject *subject, archived_state *sd) { archived_state *temp_as = NULL; - time_t part_start_time = 0L; time_t part_subject_state = 0L; int saved_status = 0; - int saved_stamp = 0; + time_t saved_stamp = 0; int count = 0; archived_state *temp_before = NULL; archived_state *last = NULL; @@ -2302,7 +2244,6 @@ void compute_subject_downtime_times(time_t start_time, time_t end_time, avail_su } /* initialize values */ - part_start_time = start_time; if(temp_as == NULL) part_subject_state = AS_NO_DATA; else if(temp_as->processed_state == AS_PROGRAM_START || temp_as->processed_state == AS_PROGRAM_END || temp_as->processed_state == AS_NO_DATA) { @@ -2364,6 +2305,11 @@ void compute_subject_downtime_times(time_t start_time, time_t end_time, avail_su } saved_status = temp_as->entry_type; saved_stamp = temp_as->time_stamp; + + /* check if first time is before schedule downtime */ + if(saved_stamp < start_time) + saved_stamp = start_time; + } } @@ -2436,11 +2382,11 @@ void compute_subject_downtime_part_times(time_t start_time, time_t end_time, int /* convert current host state to archived state value */ int convert_host_state_to_archived_state(int current_status) { - if(current_status == HOST_UP) + if(current_status == SD_HOST_UP) return AS_HOST_UP; - if(current_status == HOST_DOWN) + if(current_status == SD_HOST_DOWN) return AS_HOST_DOWN; - if(current_status == HOST_UNREACHABLE) + if(current_status == SD_HOST_UNREACHABLE) return AS_HOST_UNREACHABLE; return AS_NO_DATA; @@ -2472,7 +2418,7 @@ void create_subject_list(void) { servicesmember *temp_sgmember; host *temp_host; service *temp_service; - char *last_host_name = ""; + const char *last_host_name = ""; /* we're displaying one or more hosts */ if(display_type == DISPLAY_HOST_AVAIL && host_name && strcmp(host_name, "")) { @@ -2681,7 +2627,7 @@ avail_subject *find_subject(int type, char *hn, char *sd) { /* adds an archived state entry to all subjects */ -void add_global_archived_state(int entry_type, int state_type, time_t time_stamp, char *state_info) { +void add_global_archived_state(int entry_type, int state_type, time_t time_stamp, const char *state_info) { avail_subject *temp_subject; for(temp_subject = subject_list; temp_subject != NULL; temp_subject = temp_subject->next) @@ -2694,7 +2640,7 @@ void add_global_archived_state(int entry_type, int state_type, time_t time_stamp /* adds an archived state entry to a specific subject */ -void add_archived_state(int entry_type, int state_type, time_t time_stamp, char *state_info, avail_subject *subject) { +void add_archived_state(int entry_type, int state_type, time_t time_stamp, const char *state_info, avail_subject *subject) { archived_state *last_as = NULL; archived_state *temp_as = NULL; archived_state *new_as = NULL; @@ -3240,10 +3186,10 @@ void write_log_entries(avail_subject *subject) { char start_date_time[MAX_DATETIME_LENGTH]; char end_date_time[MAX_DATETIME_LENGTH]; char duration[20]; - char *bgclass = ""; - char *ebgclass = ""; - char *entry_type = ""; - char *state_type = ""; + const char *bgclass = ""; + const char *ebgclass = ""; + const char *entry_type = ""; + const char *state_type = ""; int days; int hours; int minutes; @@ -3473,7 +3419,7 @@ void display_specific_hostgroup_availability(hostgroup *hg) { int current_subject = 0; - char *bgclass = ""; + const char *bgclass = ""; int odd = 1; host *temp_host; @@ -3633,7 +3579,7 @@ void display_specific_servicegroup_availability(servicegroup *sg) { int current_subject = 0; - char *bgclass = ""; + const char *bgclass = ""; int odd = 1; host *temp_host; service *temp_service; @@ -3886,8 +3832,6 @@ void display_host_availability(void) { char time_indeterminate_scheduled_string[48]; char time_indeterminate_unscheduled_string[48]; - double percent_time_indeterminate_scheduled = 0.0; - double percent_time_indeterminate_unscheduled = 0.0; char time_indeterminate_notrunning_string[48]; char time_indeterminate_nodata_string[48]; double percent_time_indeterminate_notrunning = 0.0; @@ -3912,7 +3856,7 @@ void display_host_availability(void) { int current_subject = 0; - char *bgclass = ""; + const char *bgclass = ""; int odd = 1; /* calculate total time during period based on timeperiod used for reporting */ @@ -3996,8 +3940,6 @@ void display_host_availability(void) { percent_time_unreachable_scheduled = (double)(((double)temp_subject->scheduled_time_unreachable * 100.0) / (double)total_time); percent_time_unreachable_unscheduled = percent_time_unreachable - percent_time_unreachable_scheduled; percent_time_indeterminate = (double)(((double)time_indeterminate * 100.0) / (double)total_time); - percent_time_indeterminate_scheduled = (double)(((double)temp_subject->scheduled_time_indeterminate * 100.0) / (double)total_time); - percent_time_indeterminate_unscheduled = percent_time_indeterminate - percent_time_indeterminate_scheduled; percent_time_indeterminate_notrunning = (double)(((double)temp_subject->time_indeterminate_notrunning * 100.0) / (double)total_time); percent_time_indeterminate_nodata = (double)(((double)temp_subject->time_indeterminate_nodata * 100.0) / (double)total_time); if(time_determinate > 0) { @@ -4019,7 +3961,11 @@ void display_host_availability(void) { printf("

\n"); printf("", t1, t2, (include_soft_states == TRUE) ? "yes" : "no", (assume_state_retention == TRUE) ? "yes" : "no", (assume_initial_states == TRUE) ? "yes" : "no", (assume_states_during_notrunning == TRUE) ? "yes" : "no", initial_assumed_host_state, backtrack_archives); +#ifdef LEGACY_GRAPHICAL_CGIS printf("Host State Trends", t1, t2, (include_soft_states == TRUE) ? "yes" : "no", (assume_state_retention == TRUE) ? "yes" : "no", (assume_initial_states == TRUE) ? "yes" : "no", (assume_states_during_notrunning == TRUE) ? "yes" : "no", initial_assumed_host_state, backtrack_archives); printf("
\n"); printf("

\n"); @@ -4216,8 +4162,6 @@ void display_host_availability(void) { percent_time_unreachable_scheduled = 0.0; percent_time_unreachable_unscheduled = 0.0; percent_time_indeterminate = 0.0; - percent_time_indeterminate_scheduled = 0.0; - percent_time_indeterminate_unscheduled = 0.0; percent_time_indeterminate_notrunning = 0.0; percent_time_indeterminate_nodata = 0.0; percent_time_up_known = 0.0; @@ -4241,8 +4185,6 @@ void display_host_availability(void) { percent_time_unreachable_scheduled = (double)(((double)temp_subject->scheduled_time_unreachable * 100.0) / (double)total_time); percent_time_unreachable_unscheduled = percent_time_unreachable - percent_time_unreachable_scheduled; percent_time_indeterminate = (double)(((double)time_indeterminate * 100.0) / (double)total_time); - percent_time_indeterminate_scheduled = (double)(((double)temp_subject->scheduled_time_indeterminate * 100.0) / (double)total_time); - percent_time_indeterminate_unscheduled = percent_time_indeterminate - percent_time_indeterminate_scheduled; percent_time_indeterminate_notrunning = (double)(((double)temp_subject->time_indeterminate_notrunning * 100.0) / (double)total_time); percent_time_indeterminate_nodata = (double)(((double)temp_subject->time_indeterminate_nodata * 100.0) / (double)total_time); if(time_determinate > 0) { @@ -4386,15 +4328,13 @@ void display_service_availability(void) { char time_indeterminate_scheduled_string[48]; char time_indeterminate_unscheduled_string[48]; - double percent_time_indeterminate_scheduled = 0.0; - double percent_time_indeterminate_unscheduled = 0.0; char time_indeterminate_notrunning_string[48]; char time_indeterminate_nodata_string[48]; double percent_time_indeterminate_notrunning = 0.0; double percent_time_indeterminate_nodata = 0.0; int odd = 1; - char *bgclass = ""; + const char *bgclass = ""; char last_host[128] = ""; @@ -4477,7 +4417,7 @@ void display_service_availability(void) { percent_time_ok_scheduled = (double)(((double)temp_subject->scheduled_time_ok * 100.0) / (double)total_time); percent_time_ok_unscheduled = percent_time_ok - percent_time_ok_scheduled; percent_time_warning = (double)(((double)temp_subject->time_warning * 100.0) / (double)total_time); - percent_time_warning_scheduled = (double)(((double)temp_subject->scheduled_time_unknown * 100.0) / (double)total_time); + percent_time_warning_scheduled = (double)(((double)temp_subject->scheduled_time_warning * 100.0) / (double)total_time); percent_time_warning_unscheduled = percent_time_warning - percent_time_warning_scheduled; percent_time_unknown = (double)(((double)temp_subject->time_unknown * 100.0) / (double)total_time); percent_time_unknown_scheduled = (double)(((double)temp_subject->scheduled_time_unknown * 100.0) / (double)total_time); @@ -4486,8 +4426,6 @@ void display_service_availability(void) { percent_time_critical_scheduled = (double)(((double)temp_subject->scheduled_time_critical * 100.0) / (double)total_time); percent_time_critical_unscheduled = percent_time_critical - percent_time_critical_scheduled; percent_time_indeterminate = (double)(((double)time_indeterminate * 100.0) / (double)total_time); - percent_time_indeterminate_scheduled = (double)(((double)temp_subject->scheduled_time_indeterminate * 100.0) / (double)total_time); - percent_time_indeterminate_unscheduled = percent_time_indeterminate - percent_time_indeterminate_scheduled; percent_time_indeterminate_notrunning = (double)(((double)temp_subject->time_indeterminate_notrunning * 100.0) / (double)total_time); percent_time_indeterminate_nodata = (double)(((double)temp_subject->time_indeterminate_nodata * 100.0) / (double)total_time); if(time_determinate > 0) { @@ -4511,7 +4449,11 @@ void display_service_availability(void) { printf("

\n"); printf("", url_encode(svc_description), t1, t2, (include_soft_states == TRUE) ? "yes" : "no", (assume_state_retention == TRUE) ? "yes" : "no", (assume_initial_states == TRUE) ? "yes" : "no", (assume_states_during_notrunning == TRUE) ? "yes" : "no", initial_assumed_service_state, backtrack_archives); +#ifdef LEGACY_GRAPHICAL_CGIS printf("Service State Trends", url_encode(svc_description), t1, t2, (include_soft_states == TRUE) ? "yes" : "no", (assume_state_retention == TRUE) ? "yes" : "no", (assume_initial_states == TRUE) ? "yes" : "no", (assume_states_during_notrunning == TRUE) ? "yes" : "no", initial_assumed_service_state, backtrack_archives); printf("
\n"); printf("

\n"); @@ -4547,10 +4489,7 @@ void display_service_availability(void) { printf("Undetermined"); - /* - printf("Unscheduled%s%2.3f%%\n",time_indeterminate_unscheduled_string,percent_time_indeterminate_unscheduled); - printf("Scheduled%s%2.3f%%\n",time_indeterminate_scheduled_string,percent_time_indeterminate_scheduled); - */ + printf("Nagios Not Running%s%2.3f%%\n", time_indeterminate_notrunning_string, percent_time_indeterminate_notrunning); printf("Insufficient Data%s%2.3f%%\n", time_indeterminate_nodata_string, percent_time_indeterminate_nodata); printf("Total%s%2.3f%%\n", time_indeterminate_string, percent_time_indeterminate); @@ -4626,8 +4565,6 @@ void display_service_availability(void) { percent_time_critical_scheduled = 0.0; percent_time_critical_unscheduled = 0.0; percent_time_indeterminate = 0.0; - percent_time_indeterminate_scheduled = 0.0; - percent_time_indeterminate_unscheduled = 0.0; percent_time_indeterminate_notrunning = 0.0; percent_time_indeterminate_nodata = 0.0; percent_time_ok_known = 0.0; @@ -4648,7 +4585,7 @@ void display_service_availability(void) { percent_time_ok_scheduled = (double)(((double)temp_subject->scheduled_time_ok * 100.0) / (double)total_time); percent_time_ok_unscheduled = percent_time_ok - percent_time_ok_scheduled; percent_time_warning = (double)(((double)temp_subject->time_warning * 100.0) / (double)total_time); - percent_time_warning_scheduled = (double)(((double)temp_subject->scheduled_time_unknown * 100.0) / (double)total_time); + percent_time_warning_scheduled = (double)(((double)temp_subject->scheduled_time_warning * 100.0) / (double)total_time); percent_time_warning_unscheduled = percent_time_warning - percent_time_warning_scheduled; percent_time_unknown = (double)(((double)temp_subject->time_unknown * 100.0) / (double)total_time); percent_time_unknown_scheduled = (double)(((double)temp_subject->scheduled_time_unknown * 100.0) / (double)total_time); @@ -4657,8 +4594,6 @@ void display_service_availability(void) { percent_time_critical_scheduled = (double)(((double)temp_subject->scheduled_time_critical * 100.0) / (double)total_time); percent_time_critical_unscheduled = percent_time_critical - percent_time_critical_scheduled; percent_time_indeterminate = (double)(((double)time_indeterminate * 100.0) / (double)total_time); - percent_time_indeterminate_scheduled = (double)(((double)temp_subject->scheduled_time_indeterminate * 100.0) / (double)total_time); - percent_time_indeterminate_unscheduled = percent_time_indeterminate - percent_time_indeterminate_scheduled; percent_time_indeterminate_notrunning = (double)(((double)temp_subject->time_indeterminate_notrunning * 100.0) / (double)total_time); percent_time_indeterminate_nodata = (double)(((double)temp_subject->time_indeterminate_nodata * 100.0) / (double)total_time); if(time_determinate > 0) { @@ -4754,7 +4689,7 @@ void display_service_availability(void) { -void host_report_url(char *hn, char *label) { +void host_report_url(const char *hn, const char *label) { printf("name)); + if(include_soft_states == TRUE) + printf("&includesoftstates=%s", (include_soft_states == TRUE) ? "yes" : "no"); printf("'>%s", label); return; @@ -4814,7 +4751,7 @@ void get_running_average(double *running_average, double new_value, int current_ /* used in reports where a timeperiod is selected */ unsigned long calculate_total_time(time_t start_time, time_t end_time) { struct tm *t; - unsigned long midnight_today; + time_t midnight_today; int weekday; unsigned long total_time; timerange *temp_timerange; @@ -4835,7 +4772,7 @@ unsigned long calculate_total_time(time_t start_time, time_t end_time) { t->tm_min = 0; t->tm_hour = 0; t->tm_isdst = -1; - midnight_today = (unsigned long)mktime(t); + midnight_today = mktime(t); weekday = t->tm_wday; total_time = 0; diff --git a/cgi/cgiauth.c b/cgi/cgiauth.c index f53ce97..abbf323 100644 --- a/cgi/cgiauth.c +++ b/cgi/cgiauth.c @@ -2,8 +2,6 @@ * * CGIAUTH.C - Authorization utilities for Nagios CGIs * - * Copyright (c) 1999-2008 Ethan Galstad (egalstad@nagios.org) - * Last Modified: 11-30-2008 * * License: * @@ -31,9 +29,6 @@ extern char main_config_file[MAX_FILENAME_LENGTH]; -extern hostgroup *hostgroup_list; -extern servicegroup *servicegroup_list; - extern int use_authentication; extern int use_ssl_authentication; diff --git a/cgi/cgiutils.c b/cgi/cgiutils.c index b57ad3f..ed16661 100644 --- a/cgi/cgiutils.c +++ b/cgi/cgiutils.c @@ -2,9 +2,6 @@ * * CGIUTILS.C - Common utilities for Nagios CGIs * - * Copyright (c) 2010 Nagios Core Development Team and Community Contributors - * Copyright (c) 1999-2010 Ethan Galstad (egalstad@nagios.org) - * Last Modified: 08-05-2010 * * License: * @@ -28,6 +25,7 @@ #include "../include/objects.h" #include "../include/statusdata.h" +#include "../include/downtime.h" #include "../include/cgiutils.h" char main_config_file[MAX_FILENAME_LENGTH]; @@ -56,14 +54,11 @@ char *normal_sound = NULL; char *statusmap_background_image = NULL; char *statuswrl_include = NULL; -char *illegal_output_chars = NULL; - char *notes_url_target = NULL; char *action_url_target = NULL; char *ping_syntax = NULL; -char nagios_check_command[MAX_INPUT_BUFFER] = ""; char nagios_process_info[MAX_INPUT_BUFFER] = ""; int nagios_process_state = STATE_OK; @@ -71,24 +66,12 @@ int enable_splunk_integration = FALSE; char *splunk_url = NULL; int lock_author_names = TRUE; -extern time_t program_start; -extern int nagios_pid; -extern int daemon_mode; -extern int enable_notifications; -extern int execute_service_checks; -extern int accept_passive_service_checks; -extern int enable_event_handlers; -extern int obsess_over_services; -extern int enable_failure_prediction; -extern int process_performance_data; -extern time_t last_command_check; -extern time_t last_log_rotation; +int navbar_search_addresses = TRUE; +int navbar_search_aliases = TRUE; -int check_external_commands = 0; - -int date_format = DATE_FORMAT_US; - -int log_rotation_method = LOG_ROTATION_NONE; +int ack_no_sticky = FALSE; +int ack_no_send = FALSE; +int tac_cgi_hard_only = FALSE; time_t this_scheduled_log_rotation = 0L; time_t last_scheduled_log_rotation = 0L; @@ -96,8 +79,6 @@ time_t next_scheduled_log_rotation = 0L; int use_authentication = TRUE; -int interval_length = 60; - int show_context_help = FALSE; int use_pending_states = TRUE; @@ -120,13 +101,6 @@ int color_transparency_index_r = 255; int color_transparency_index_g = 255; int color_transparency_index_b = 255; -extern hostgroup *hostgroup_list; -extern contactgroup *contactgroup_list; -extern command *command_list; -extern timeperiod *timeperiod_list; -extern contact *contact_list; -extern serviceescalation *serviceescalation_list; - extern hoststatus *hoststatus_list; extern servicestatus *servicestatus_list; @@ -135,15 +109,6 @@ lifo *lifo_list = NULL; char encoded_url_string[2][MAX_INPUT_BUFFER]; // 2 to be able use url_encode twice char *encoded_html_string = NULL; -#ifdef HAVE_TZNAME -#ifdef CYGWIN -extern char *_tzname[2] __declspec(dllimport); -#else -extern char *tzname[2]; -#endif -#endif - - /* * These function stubs allow us to compile a lot of the @@ -160,6 +125,31 @@ int log_debug_info(int leve, int verbosity, const char *fmt, ...) { return 0; } +/*** helpers ****/ +/* + * find a command with arguments still attached + * if we're unsuccessful, the buffer pointed to by 'name' is modified + * to have only the real command name (everything up until the first '!') + */ +static command *find_bang_command(char *name) +{ + char *bang; + command *cmd; + + if (!name) + return NULL; + + bang = strchr(name, '!'); + if (!bang) + return find_command(name); + *bang = 0; + cmd = find_command(name); + *bang = '!'; + return cmd; +} + + + /********************************************************** ***************** CLEANUP FUNCTIONS ********************** **********************************************************/ @@ -186,7 +176,6 @@ void reset_cgi_vars(void) { strcat(log_archive_path, "/"); strcpy(command_file, get_cmd_file_location()); - strcpy(nagios_check_command, ""); strcpy(nagios_process_info, ""); nagios_process_state = STATE_OK; @@ -252,7 +241,7 @@ void free_memory(void) { **********************************************************/ /* read the CGI config file location from an environment variable */ -char * get_cgi_config_location(void) { +const char *get_cgi_config_location(void) { static char *cgiloc = NULL; if(!cgiloc) { @@ -266,7 +255,7 @@ char * get_cgi_config_location(void) { /* read the command file location from an environment variable */ -char * get_cmd_file_location(void) { +const char *get_cmd_file_location(void) { static char *cmdloc = NULL; if(!cmdloc) { @@ -279,11 +268,12 @@ char * get_cmd_file_location(void) { /*read the CGI configuration file */ -int read_cgi_config_file(char *filename) { +int read_cgi_config_file(const char *filename) { char *input = NULL; mmapfile *thefile; char *var = NULL; char *val = NULL; + char *p = NULL; if((thefile = mmap_fopen(filename)) == NULL) @@ -321,12 +311,6 @@ int read_cgi_config_file(char *filename) { else if(!strcmp(var, "use_authentication")) use_authentication = (atoi(val) > 0) ? TRUE : FALSE; - else if(!strcmp(var, "nagios_check_command")) { - strncpy(nagios_check_command, val, sizeof(nagios_check_command)); - nagios_check_command[sizeof(nagios_check_command) - 1] = '\x0'; - strip(nagios_check_command); - } - else if(!strcmp(var, "refresh_rate")) refresh_rate = atoi(val); @@ -446,8 +430,23 @@ int read_cgi_config_file(char *filename) { else if(!strcmp(var, "use_ssl_authentication")) use_ssl_authentication = (atoi(val) > 0) ? TRUE : FALSE; + + else if(!strcmp(var, "navbar_search_addresses")) + navbar_search_addresses = (atoi(val) > 0) ? TRUE : FALSE; + + else if(!strcmp(var, "navbar_search_aliases")) + navbar_search_aliases = (atoi(val) > 0) ? TRUE : FALSE; + else if(!strcmp(var, "ack_no_sticky")) + ack_no_sticky = (atoi(val) > 0) ? TRUE : FALSE; + else if(!strcmp(var, "ack_no_send")) + ack_no_send = (atoi(val) > 0) ? TRUE : FALSE; + else if(!strcmp(var, "tac_cgi_hard_only")) + tac_cgi_hard_only = (atoi(val) > 0) ? TRUE : FALSE; } + for(p = illegal_output_chars; p && *p; p++) + illegal_output_char_map[(int)*p] = 1; + /* free memory and close the file */ free(input); mmap_fclose(thefile); @@ -461,11 +460,12 @@ int read_cgi_config_file(char *filename) { /* read the main configuration file */ -int read_main_config_file(char *filename) { +int read_main_config_file(const char *filename) { char *input = NULL; char *temp_buffer; mmapfile *thefile; + config_file_dir = nspath_absolute_dirname(filename, NULL); if((thefile = mmap_fopen(filename)) == NULL) return ERROR; @@ -490,11 +490,22 @@ int read_main_config_file(char *filename) { else if(strstr(input, "log_file=") == input) { temp_buffer = strtok(input, "="); temp_buffer = strtok(NULL, "\x0"); - strncpy(log_file, (temp_buffer == NULL) ? "" : temp_buffer, sizeof(log_file)); + strncpy(log_file, (temp_buffer == NULL) ? "" : nspath_absolute(temp_buffer, config_file_dir),sizeof(log_file) - 1); log_file[sizeof(log_file) - 1] = '\x0'; strip(log_file); } + else if(strstr(input, "object_cache_file=") == input) { + temp_buffer = strtok(input, "="); + temp_buffer = strtok(NULL, "\x0"); + object_cache_file = nspath_absolute(temp_buffer, config_file_dir); + } + else if(strstr(input, "status_file=") == input) { + temp_buffer = strtok(input, "="); + temp_buffer = strtok(NULL, "\x0"); + status_file = nspath_absolute(temp_buffer, config_file_dir); + } + else if(strstr(input, "log_archive_path=") == input) { temp_buffer = strtok(input, "="); temp_buffer = strtok(NULL, "\n"); @@ -560,18 +571,90 @@ int read_main_config_file(char *filename) { /* read all object definitions */ -int read_all_object_configuration_data(char *config_file, int options) { +int read_all_object_configuration_data(const char *cfgfile, int options) { int result = OK; + host *temp_host = NULL; + host *parent_host = NULL; + hostsmember *temp_hostsmember = NULL; + service *temp_service = NULL; + service *parent_service = NULL; + servicesmember *temp_servicesmember = NULL; /* read in all external config data of the desired type(s) */ - result = read_object_config_data(config_file, options, FALSE, FALSE); + result = read_object_config_data(cfgfile, options); + + /* Resolve objects in the host object */ + for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) { + /* Find the command object for the check command */ + temp_host->check_command_ptr = + find_bang_command(temp_host->check_command); + + /* Find the command object for the event handler */ + temp_host->event_handler_ptr = + find_bang_command(temp_host->event_handler); + + /* Resolve host child->parent relationships */ + for(temp_hostsmember = temp_host->parent_hosts; + temp_hostsmember != NULL; + temp_hostsmember = temp_hostsmember->next) { + if((parent_host = find_host(temp_hostsmember->host_name)) == NULL) { + logit(NSLOG_CONFIG_ERROR, TRUE, + "Error: '%s' is not a valid parent for host '%s'!", + temp_hostsmember->host_name, temp_host->name); + } + /* save the parent host pointer for later */ + temp_hostsmember->host_ptr = parent_host; + + /* add a reverse (child) link to make searches faster later on */ + if(add_child_link_to_host(parent_host, temp_host) == NULL) { + logit(NSLOG_CONFIG_ERROR, TRUE, + "Error: Failed to add '%s' as a child host of '%s'", + temp_host->name, parent_host->name); + } + } + } + + /* Resolve objects in the service object */ + for(temp_service = service_list; temp_service != NULL; + temp_service = temp_service->next) { + /* Find the command object for the check command */ + temp_service->check_command_ptr = + find_bang_command(temp_service->check_command); + + /* Find the command object for the event handler */ + temp_service->event_handler_ptr = + find_bang_command(temp_service->event_handler); + + /* Resolve service child->parent relationships */ + for(temp_servicesmember = temp_service->parents; + temp_servicesmember != NULL; + temp_servicesmember = temp_servicesmember->next) { + /* Find the parent service */ + if((parent_service = find_service(temp_servicesmember->host_name, + temp_servicesmember->service_description)) == NULL) { + logit(NSLOG_CONFIG_ERROR, TRUE, + "Error: '%s:%s' is not a valid parent for service '%s:%s'!", + temp_servicesmember->host_name, + temp_servicesmember->service_description, + temp_service->host_name, temp_service->description); + } + /* add a reverse (child) link to make searches faster later on */ + if(add_child_link_to_service(parent_service, + temp_service) == NULL) { + logit(NSLOG_CONFIG_ERROR, TRUE, + "Error: Failed to add '%s:%s' as a child service of '%s:%s'", + temp_service->host_name, temp_service->description, + parent_service->host_name, parent_service->description); + } + } + } return result; } /* read all status data */ -int read_all_status_data(char *config_file, int options) { +int read_all_status_data(const char *status_file_name, int options) { int result = OK; /* don't duplicate things we've already read in */ @@ -586,8 +669,11 @@ int read_all_status_data(char *config_file, int options) { if(options <= 0) return OK; + /* Initialize the downtime data */ + initialize_downtime_data(); + /* read in all external status data */ - result = read_status_data(config_file, options); + result = read_status_data(status_file_name, options); /* mark what items we've read in... */ if(options & READ_PROGRAM_STATUS) @@ -601,6 +687,51 @@ int read_all_status_data(char *config_file, int options) { } +void cgi_init(void (*doc_header)(int), void (*doc_footer)(void), int object_options, int status_options) { + int result; + + /* Initialize shared configuration variables */ + init_shared_cfg_vars(1); + + /* read the CGI configuration file */ + result = read_cgi_config_file(get_cgi_config_location()); + if(result == ERROR) { + doc_header(FALSE); + cgi_config_file_error(get_cgi_config_location()); + doc_footer(); + exit(EXIT_FAILURE); + } + + /* read the main configuration file */ + result = read_main_config_file(main_config_file); + if(result == ERROR) { + doc_header(FALSE); + main_config_file_error(main_config_file); + doc_footer(); + exit(EXIT_FAILURE); + } + + /* read all object configuration data */ + result = read_all_object_configuration_data(main_config_file, object_options); + if(result == ERROR) { + doc_header(FALSE); + object_data_error(); + doc_footer(); + exit(EXIT_FAILURE); + } + + /* read all status data */ + result = read_all_status_data(status_file, status_options); + if(result == ERROR) { + doc_header(FALSE); + status_data_error(); + doc_footer(); + free_memory(); + exit(EXIT_FAILURE); + } + } + + /********************************************************** ******************* LIFO FUNCTIONS *********************** **********************************************************/ @@ -727,7 +858,7 @@ char *unescape_newlines(char *rawbuf) { } /* unescape backslashes and other stuff */ - if(rawbuf[x + 1] != '\x0') { + else if(rawbuf[x + 1] != '\x0') { rawbuf[y++] = rawbuf[x + 1]; x++; } @@ -816,9 +947,9 @@ void get_time_string(time_t *raw_time, char *buffer, int buffer_length, int type int month = 0; int day = 0; int year = 0; - char *weekdays[7] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; - char *months[12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; - char *tzone = ""; + const char *weekdays[7] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; + const char *months[12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; + const char *tzone = ""; if(raw_time == NULL) time(&t); @@ -902,7 +1033,7 @@ void get_interval_time_string(double time_units, char *buffer, int buffer_length /* encodes a string in proper URL format */ -char *url_encode(char *input) { +const char *url_encode(const char *input) { int len, output_len; int x, y; char temp_expansion[4]; @@ -916,7 +1047,7 @@ char *url_encode(char *input) { return str; len = (int)strlen(input); - output_len = (int)sizeof(encoded_url_string[0]); + output_len = (int)sizeof(encoded_url_string[i]); str[0] = '\x0'; @@ -944,19 +1075,57 @@ char *url_encode(char *input) { else { str[y] = '\x0'; if((int)strlen(str) < (output_len - 3)) { - sprintf(temp_expansion, "%%%02X", (unsigned char)input[x]); + sprintf(temp_expansion, "%%%02X", (unsigned int)(input[x] & 0xFF)); strcat(str, temp_expansion); y += 3; } } } - str[sizeof(encoded_url_string[0]) - 1] = '\x0'; + str[sizeof(encoded_url_string[i]) - 1] = '\x0'; + i = !i; return str; } +static char * copy_wc_to_output(wchar_t wc, char *outstp, int output_max) { + int wctomb_result; + char mbtemp[ 10]; + + wctomb_result = wctomb(mbtemp, wc); + if(( wctomb_result > 0) && + ((( outstp - encoded_html_string) + wctomb_result) < output_max)) { + strncpy( outstp, mbtemp, wctomb_result); + outstp += wctomb_result; + } + return outstp; + } + +static char * encode_character(wchar_t wc, char *outstp, int output_max) { + + char temp_expansion[11]; + + sprintf(temp_expansion, "&#%u;", (unsigned int)wc); + if(((outstp - encoded_html_string) + strlen(temp_expansion)) < + (unsigned int)output_max) { + strncpy(outstp, temp_expansion, strlen( temp_expansion)); + outstp += strlen( temp_expansion); + } + return outstp; + } + +#define WHERE_OUTSIDE_TAG 0 /* Not in an HTML tag */ +#define WHERE_IN_TAG_NAME 1 /* In HTML tag name (either opening + or closing tag) */ +#define WHERE_IN_TAG_OUTSIDE_ATTRIBUTE 2 /* In HTML tag, but before or after + an attribute. Should be <, > or + space */ +#define WHERE_IN_TAG_IN_ATTRIBUTE_NAME 3 /* In the attribute name */ +#define WHERE_IN_TAG_AT_EQUALS 4 /* At the equals sign between the + attribute name and value */ +#define WHERE_IN_TAG_IN_ATTRIBUTE_VALUE 5 /* In the attribute value */ +#define WHERE_IN_COMMENT 6 /* In an HTML comment */ /* escapes a string used in HTML */ char * html_encode(char *input, int escape_newlines) { @@ -965,114 +1134,206 @@ char * html_encode(char *input, int escape_newlines) { char *outstp; wchar_t *wcinput; wchar_t *inwcp; + wchar_t *tagname = L""; size_t mbstowcs_result; - char mbtemp[ 10]; - int wctomb_result; int x; - char temp_expansion[10]; + int where_in_tag = WHERE_OUTSIDE_TAG; /* Location in HTML tag */ + wchar_t attr_value_start = (wchar_t)0; /* character that starts the + attribute value */ + int tag_depth = 0; /* depth of nested HTML tags */ /* we need up to six times the space to do the conversion */ len = (int)strlen(input); output_max = len * 6; - if((outstp = encoded_html_string = (char *)malloc(output_max + 1)) == NULL) + if(( outstp = encoded_html_string = (char *)malloc(output_max + 1)) == NULL) return ""; strcpy(encoded_html_string, ""); /* Convert the string to a wide character string */ - if((wcinput = malloc(len * sizeof(wchar_t))) == NULL) { + if(( wcinput = malloc( len * sizeof( wchar_t))) == NULL) { return ""; } - if((mbstowcs_result = mbstowcs(wcinput, input, len)) < 0) { - free(wcinput); + if((mbstowcs_result = mbstowcs( wcinput, input, len)) == (size_t)-1) { + free( wcinput); return ""; } /* Process all converted characters */ - for(x = 0, inwcp = wcinput; x < mbstowcs_result && '\0' != *inwcp; x++, inwcp++) { + for( x = 0, inwcp = wcinput; x < (int)mbstowcs_result && '\0' != *inwcp; + x++, inwcp++) { /* Most ASCII characters don't get encoded */ - if((*inwcp >= 0x20 && *inwcp <= 0x7e) && - (!('"' == *inwcp || '&' == *inwcp || '\'' == *inwcp || - '<' == *inwcp || '>' == *inwcp))) { - wctomb_result = wctomb(mbtemp, *inwcp); - if((wctomb_result > 0) && - (((outstp - encoded_html_string) + wctomb_result) < output_max)) { - strncpy(outstp, mbtemp, wctomb_result); - outstp += wctomb_result; + if(( *inwcp >= 0x20 && *inwcp <= 0x7e) && + ( !( '"' == *inwcp || '&' == *inwcp || '\'' == *inwcp || + '<' == *inwcp || '>' == *inwcp))) { + outstp = copy_wc_to_output(*inwcp, outstp, output_max); + switch(where_in_tag) { + case WHERE_IN_TAG_NAME: + switch(*inwcp) { + case 0x20: + where_in_tag = WHERE_IN_TAG_OUTSIDE_ATTRIBUTE; + *inwcp = 0; + break; + case '!': + where_in_tag = WHERE_IN_COMMENT; + break; + } + break; + case WHERE_IN_TAG_OUTSIDE_ATTRIBUTE: + if(*inwcp != 0x20) { + where_in_tag = WHERE_IN_TAG_IN_ATTRIBUTE_NAME; + } + break; + case WHERE_IN_TAG_IN_ATTRIBUTE_NAME: + if(*inwcp == '=') { + where_in_tag = WHERE_IN_TAG_AT_EQUALS; + } + break; + case WHERE_IN_TAG_AT_EQUALS: + if(*inwcp != 0x20) { + attr_value_start = *inwcp; + where_in_tag = WHERE_IN_TAG_IN_ATTRIBUTE_VALUE; + } + break; + case WHERE_IN_TAG_IN_ATTRIBUTE_VALUE: + if((*inwcp == 0x20) && (attr_value_start != '"') && + (attr_value_start != '\'')) { + where_in_tag = WHERE_IN_TAG_OUTSIDE_ATTRIBUTE; + } + break; + } + } + + /* Special handling for quotes */ + else if(FALSE == escape_html_tags && + ('"' == *inwcp || '\'' == *inwcp)) { + switch(where_in_tag) { + case WHERE_OUTSIDE_TAG: + if(tag_depth >0) { + outstp = copy_wc_to_output(*inwcp, outstp, output_max); + } + else { + outstp = encode_character(*inwcp, outstp, output_max); + } + break; + case WHERE_IN_COMMENT: + outstp = copy_wc_to_output(*inwcp, outstp, output_max); + break; + case WHERE_IN_TAG_AT_EQUALS: + outstp = copy_wc_to_output(*inwcp, outstp, output_max); + attr_value_start = *inwcp; + where_in_tag = WHERE_IN_TAG_IN_ATTRIBUTE_VALUE; + break; + case WHERE_IN_TAG_IN_ATTRIBUTE_VALUE: + if(*(inwcp-1) == '\\') { + /* This covers the case where the quote is backslash + escaped. */ + outstp = copy_wc_to_output(*inwcp, outstp, output_max); + } + else if(attr_value_start == *inwcp) { + /* If the quote is the same type of quote that started + the attribute value and it is not backslash + escaped, it signals the end of the attribute value */ + outstp = copy_wc_to_output(*inwcp, outstp, output_max); + where_in_tag = WHERE_IN_TAG_OUTSIDE_ATTRIBUTE; + } + else { + /* If we encounter an quote that did not start the + attribute value and is not backslash escaped, + use it as is */ + outstp = copy_wc_to_output(*inwcp, outstp, output_max); + } + break; + default: + if (tag_depth > 0 && !wcscmp(tagname, L"script")) + outstp = copy_wc_to_output(*inwcp, outstp, output_max); + else + outstp = encode_character(*inwcp, outstp, output_max); + break; } } /* newlines turn to
tags */ else if(escape_newlines == TRUE && '\n' == *inwcp) { - strncpy(outstp, "
", 4); + strncpy( outstp, "
", 4); outstp += 4; } - else if(escape_newlines == TRUE && '\\' == *inwcp && '\n' == *(inwcp + 1)) { - strncpy(outstp, "
", 4); + else if(escape_newlines == TRUE && '\\' == *inwcp && '\n' == *( inwcp + 1)) { + strncpy( outstp, "
", 4); outstp += 4; inwcp++; /* needed so loop skips two wide characters */ } /* TODO - strip all but allowed HTML tags out... */ + else if(('<' == *inwcp) && (FALSE == escape_html_tags)) { - else if('<' == *inwcp) { - - if(escape_html_tags == FALSE) { - wctomb_result = wctomb(mbtemp, *inwcp); - if((wctomb_result > 0) && - (((outstp - encoded_html_string) + wctomb_result) < output_max)) { - strncpy(outstp, mbtemp, wctomb_result); - outstp += wctomb_result; - } - } - else { - if(((outstp - encoded_html_string) + 4) < output_max) { - strncpy(outstp, "<", 4); - outstp += 4; + switch(where_in_tag) { + case WHERE_OUTSIDE_TAG: + outstp = copy_wc_to_output(*inwcp, outstp, output_max); + where_in_tag = WHERE_IN_TAG_NAME; + switch(*(inwcp+1)) { + case '/': + tag_depth--; + break; + case '!': + break; + default: + tag_depth++; + tagname = inwcp + 1; + break; } + break; + default: + if (tag_depth > 0 && !wcscmp(tagname, L"script")) + outstp = copy_wc_to_output(*inwcp, outstp, output_max); + else + outstp = encode_character(*inwcp, outstp, output_max); + break; } } - else if('>' == *inwcp) { + else if(('>' == *inwcp) && (FALSE == escape_html_tags)) { - if(escape_html_tags == FALSE) { - wctomb_result = wctomb(mbtemp, *inwcp); - if((wctomb_result > 0) && - (((outstp - encoded_html_string) + wctomb_result) < output_max)) { - strncpy(outstp, mbtemp, wctomb_result); - outstp += wctomb_result; + switch(where_in_tag) { + case WHERE_IN_TAG_NAME: + case WHERE_IN_TAG_OUTSIDE_ATTRIBUTE: + case WHERE_IN_COMMENT: + case WHERE_IN_TAG_IN_ATTRIBUTE_NAME: + outstp = copy_wc_to_output(*inwcp, outstp, output_max); + where_in_tag = WHERE_OUTSIDE_TAG; + *inwcp = 0; + break; + case WHERE_IN_TAG_IN_ATTRIBUTE_VALUE: + if((attr_value_start != '"') && (attr_value_start != '\'')) { + outstp = copy_wc_to_output(*inwcp, outstp, output_max); + where_in_tag = WHERE_OUTSIDE_TAG; } - } - else { - if(((outstp - encoded_html_string) + 4) < output_max) { - strncpy(outstp, ">", 4); - outstp += 4; + else { + outstp = encode_character(*inwcp, outstp, output_max); } + break; + default: + if (tag_depth > 0 && !wcscmp(tagname, L"script")) + outstp = copy_wc_to_output(*inwcp, outstp, output_max); + else + outstp = encode_character(*inwcp, outstp, output_max); + break; } } - /* When not escaping HTML tags, don't encode quotes or ampersands - (left and right carets are handled above */ - else if((escape_html_tags == FALSE) && ('"' == *inwcp || - '&' == *inwcp || '\'' == *inwcp)) { - wctomb_result = wctomb(mbtemp, *inwcp); - if((wctomb_result > 0) && - (((outstp - encoded_html_string) + wctomb_result) < output_max)) { - strncpy(outstp, mbtemp, wctomb_result); - outstp += wctomb_result; - } + /* check_multi puts out a '&ndash' so don't encode the '&' in that case */ + else if (*inwcp == '&' && escape_html_tags == FALSE) { + if (tag_depth > 0 && !wcsncmp(inwcp, L"&ndash", 6)) + outstp = copy_wc_to_output(*inwcp, outstp, output_max); + else + outstp = encode_character(*inwcp, outstp, output_max); } /* for simplicity, all other chars represented by their numeric value */ else { - sprintf(temp_expansion, "&#%u;", *(unsigned int *)inwcp); - if(((outstp - encoded_html_string) + strlen(temp_expansion)) < - output_max) { - strncpy(outstp, temp_expansion, strlen(temp_expansion)); - outstp += strlen(temp_expansion); - } + outstp = encode_character(*inwcp, outstp, output_max); } } @@ -1094,7 +1355,7 @@ void strip_html_brackets(char *buffer) { if(buffer == NULL || buffer[0] == '\x0') return; - /* remove all occurances in string */ + /* remove all occurrences in string */ z = (int)strlen(buffer); for(x = 0, y = 0; x < z; x++) { if(buffer[x] == '<' || buffer[x] == '>') @@ -1108,7 +1369,7 @@ void strip_html_brackets(char *buffer) { /* escape string for html form usage */ -char *escape_string(char *input) { +char *escape_string(const char *input) { int len; int output_max; wchar_t wctemp[1]; @@ -1116,49 +1377,49 @@ char *escape_string(char *input) { char mbtemp[ 10]; int wctomb_result; char *stp; - char temp_expansion[10]; + char temp_expansion[11]; /* If they don't give us anything to do... */ - if(NULL == input) { + if( NULL == input) { return ""; } /* We need up to six times the space to do the conversion */ len = (int)strlen(input); output_max = len * 6; - if((stp = encoded_html_string = (char *)malloc(output_max + 1)) == NULL) + if(( stp = encoded_html_string = (char *)malloc(output_max + 1)) == NULL) return ""; strcpy(encoded_html_string, ""); /* Get the first multibyte character in the input string */ - mbtowc_result = mbtowc(wctemp, input, MB_CUR_MAX); + mbtowc_result = mbtowc( wctemp, input, MB_CUR_MAX); /* Process all characters until a null character is found */ - while(0 != mbtowc_result) { /* 0 indicates a null character was found */ + while( 0 != mbtowc_result) { /* 0 indicates a null character was found */ - if((size_t) - 2 == mbtowc_result) { + if(( size_t)-2 == mbtowc_result) { /* No complete multibyte character found - try at next memory address */ input++; } - else if(((size_t) - 1 == mbtowc_result) && (EILSEQ == errno)) { + else if((( size_t)-1 == mbtowc_result) && ( EILSEQ == errno)) { /* Invalid multibyte character found - try at next memory address */ input++; } /* Alpha-numeric characters and a few other characters don't get encoded */ - else if((*wctemp >= '0' && *wctemp <= '9') || - (*wctemp >= 'A' && *wctemp <= 'Z') || - (*wctemp >= 'a' && *wctemp <= 'z') || - ' ' == *wctemp || '-' == *wctemp || '.' == *wctemp || - '_' == *wctemp || ':' == *wctemp) { - wctomb_result = wctomb(mbtemp, wctemp[0]); - if((wctomb_result > 0) && - (((stp - encoded_html_string) + wctomb_result) < output_max)) { - strncpy(stp, mbtemp, wctomb_result); + else if(( *wctemp >= '0' && *wctemp <= '9') || + ( *wctemp >= 'A' && *wctemp <= 'Z') || + ( *wctemp >= 'a' && *wctemp <= 'z') || + ' ' == *wctemp || '-' == *wctemp || '.' == *wctemp || + '_' == *wctemp || ':' == *wctemp) { + wctomb_result = wctomb( mbtemp, wctemp[0]); + if(( wctomb_result > 0) && + ((( stp - encoded_html_string) + wctomb_result) < output_max)) { + strncpy( stp, mbtemp, wctomb_result); stp += wctomb_result; } input += mbtowc_result; @@ -1166,17 +1427,17 @@ char *escape_string(char *input) { /* Encode everything else (this may be excessive) */ else { - sprintf(temp_expansion, "&#%u;", (unsigned int)wctemp[ 0]); - if(((stp - encoded_html_string) + strlen(temp_expansion)) < - output_max) { - strncpy(stp, temp_expansion, strlen(temp_expansion)); - stp += strlen(temp_expansion); + sprintf( temp_expansion, "&#%u;", ( unsigned int)wctemp[ 0]); + if((( stp - encoded_html_string) + strlen( temp_expansion)) < + (unsigned int)output_max) { + strncpy( stp, temp_expansion, strlen( temp_expansion)); + stp += strlen( temp_expansion); } input += mbtowc_result; } /* Read the next character */ - mbtowc_result = mbtowc(wctemp, input, MB_CUR_MAX); + mbtowc_result = mbtowc( wctemp, input, MB_CUR_MAX); } /* Null terminate the encoded string */ @@ -1348,13 +1609,13 @@ void determine_log_rotation_times(int archive) { *************** COMMON HTML FUNCTIONS ******************** **********************************************************/ -void display_info_table(char *title, int refresh, authdata *current_authdata) { +void display_info_table(const char *title, int refresh, authdata *current_authdata) { time_t current_time; char date_time[MAX_DATETIME_LENGTH]; int result; /* read program status */ - result = read_all_status_data(get_cgi_config_location(), READ_PROGRAM_STATUS); + result = read_all_status_data(status_file, READ_PROGRAM_STATUS); printf("\n"); printf(""); printf("\n"); - /* check all the service escalations... */ - for(temp_se = serviceescalation_list; temp_se != NULL; temp_se = temp_se->next) if(((*to_expand) == '\0') || (!strcmp(to_expand, temp_se->host_name))) { - if(odd) { - odd = 0; - bg_class = "dataOdd"; - } - else { - odd = 1; - bg_class = "dataEven"; - } + for(i = 0; i < num_objects.serviceescalations; i++) { + temp_se = serviceescalation_ary[i]; + if(*to_expand != '\0' && strcmp(to_expand, temp_se->host_name)) + continue; - printf("\n", bg_class); - - printf("", bg_class, CONFIG_CGI, url_encode(temp_se->host_name), html_encode(temp_se->host_name, FALSE)); - - printf("\n", url_encode(temp_se->description), html_encode(temp_se->description, FALSE)); - - printf("\n"); - - printf("", bg_class, temp_se->first_notification); - - printf("\n"); - - get_interval_time_string(temp_se->notification_interval, time_string, sizeof(time_string)); - printf("\n"); - - printf("\n"); - - printf("\n"); - - printf("\n"); + if(odd) { + odd = 0; + bg_class = "dataOdd"; } + else { + odd = 1; + bg_class = "dataEven"; + } + + printf("\n", bg_class); + + printf("", bg_class, CONFIG_CGI, url_encode(temp_se->host_name), html_encode(temp_se->host_name, FALSE)); + + printf("\n", url_encode(temp_se->description), html_encode(temp_se->description, FALSE)); + + printf("\n"); + + printf("", bg_class, temp_se->first_notification); + + printf("\n"); + + get_interval_time_string(temp_se->notification_interval, time_string, sizeof(time_string)); + printf("\n"); + + printf("\n"); + + printf("\n"); + + printf("\n"); + } printf("
\n"); @@ -1367,7 +1628,7 @@ void display_info_table(char *title, int refresh, authdata *current_authdata) { if(refresh == TRUE) printf("Updated every %d seconds
\n", refresh_rate); - printf("Nagios® Core™ %s - www.nagios.org
\n", PROGRAM_VERSION); + printf("Nagios® Core™ %s - www.nagios.org
\n", PROGRAM_VERSION); if(current_authdata != NULL) printf("Logged in as %s
\n", (!strcmp(current_authdata->username, "")) ? "?" : current_authdata->username); @@ -1563,12 +1824,11 @@ void print_extra_servicegroup_url(char *group_name, char *url) { /* include user-defined SSI footers or headers */ -void include_ssi_files(char *cgi_name, int type) { +void include_ssi_files(const char *cgi_name, int type) { char common_ssi_file[MAX_INPUT_BUFFER]; char cgi_ssi_file[MAX_INPUT_BUFFER]; char raw_cgi_name[MAX_INPUT_BUFFER]; char *stripped_cgi_name; - int x; /* common header or footer */ snprintf(common_ssi_file, sizeof(common_ssi_file) - 1, "%scommon-%s.ssi", physical_ssi_path, (type == SSI_HEADER) ? "header" : "footer"); @@ -1582,14 +1842,14 @@ void include_ssi_files(char *cgi_name, int type) { cgi_ssi_file[sizeof(cgi_ssi_file) - 1] = '\x0'; if(type == SSI_HEADER) { - printf("\n\n"); + printf("\n\n"); include_ssi_file(common_ssi_file); include_ssi_file(cgi_ssi_file); } else { include_ssi_file(cgi_ssi_file); include_ssi_file(common_ssi_file); - printf("\n\n"); + printf("\n\n"); } return; @@ -1598,7 +1858,7 @@ void include_ssi_files(char *cgi_name, int type) { /* include user-defined SSI footer or header */ -void include_ssi_file(char *filename) { +void include_ssi_file(const char *filename) { char buffer[MAX_INPUT_BUFFER]; FILE *fp; struct stat stat_result; @@ -1660,7 +1920,7 @@ void include_ssi_file(char *filename) { /* displays an error if CGI config file could not be read */ -void cgi_config_file_error(char *config_file) { +void cgi_config_file_error(const char *config_file) { printf("

Whoops!

\n"); @@ -1680,7 +1940,7 @@ void cgi_config_file_error(char *config_file) { printf("

\n"); printf("

\n"); - printf("Make sure you read the documentation on installing and configuring Nagios thoroughly before continuing. If all else fails, try sending a message to one of the mailing lists. More information can be found at http://www.nagios.org.\n"); + printf("Make sure you read the documentation on installing and configuring Nagios thoroughly before continuing. If all else fails, try sending a message to one of the mailing lists. More information can be found at https://www.nagios.org.\n"); printf("

\n"); return; @@ -1689,7 +1949,7 @@ void cgi_config_file_error(char *config_file) { /* displays an error if main config file could not be read */ -void main_config_file_error(char *config_file) { +void main_config_file_error(const char *config_file) { printf("

Whoops!

\n"); @@ -1709,7 +1969,7 @@ void main_config_file_error(char *config_file) { printf("

\n"); printf("

\n"); - printf("Make sure you read the documentation on installing and configuring Nagios thoroughly before continuing. If all else fails, try sending a message to one of the mailing lists. More information can be found at http://www.nagios.org.\n"); + printf("Make sure you read the documentation on installing and configuring Nagios thoroughly before continuing. If all else fails, try sending a message to one of the mailing lists. More information can be found at https://www.nagios.org.\n"); printf("

\n"); return; @@ -1737,7 +1997,7 @@ void object_data_error(void) { printf("

\n"); printf("

\n"); - printf("Make sure you read the documentation on installing, configuring and running Nagios thoroughly before continuing. If all else fails, try sending a message to one of the mailing lists. More information can be found at http://www.nagios.org.\n"); + printf("Make sure you read the documentation on installing, configuring and running Nagios thoroughly before continuing. If all else fails, try sending a message to one of the mailing lists. More information can be found at https://www.nagios.org.\n"); printf("

\n"); return; @@ -1769,7 +2029,7 @@ void status_data_error(void) { printf("

\n"); printf("

\n"); - printf("Make sure you read the documentation on installing, configuring and running Nagios thoroughly before continuing. If all else fails, try sending a message to one of the mailing lists. More information can be found at http://www.nagios.org.\n"); + printf("Make sure you read the documentation on installing, configuring and running Nagios thoroughly before continuing. If all else fails, try sending a message to one of the mailing lists. More information can be found at https://www.nagios.org.\n"); printf("

\n"); return; @@ -1779,8 +2039,8 @@ void status_data_error(void) { /* displays context-sensitive help window */ -void display_context_help(char *chid) { - char *icon = CONTEXT_HELP_ICON1; +void display_context_help(const char *chid) { + const char *icon = CONTEXT_HELP_ICON1; if(show_context_help == FALSE) return; @@ -1858,7 +2118,7 @@ void strip_splunk_query_terms(char *buffer) { if(buffer == NULL || buffer[0] == '\x0') return; - /* remove all occurances in string */ + /* remove all occurrences in string */ z = (int)strlen(buffer); for(x = 0, y = 0; x < z; x++) { if(buffer[x] == '\'' || buffer[x] == '\"' || buffer[x] == ';' || buffer[x] == ':' || buffer[x] == ',' || buffer[x] == '-' || buffer[x] == '=') @@ -1870,5 +2130,3 @@ void strip_splunk_query_terms(char *buffer) { return; } - - diff --git a/cgi/cmd.c b/cgi/cmd.c index 6fc2939..f577efe 100644 --- a/cgi/cmd.c +++ b/cgi/cmd.c @@ -2,8 +2,6 @@ * * CMD.C - Nagios Command CGI * - * Copyright (c) 1999-2010 Ethan Galstad (egalstad@nagios.org) - * Last Modified: 08-28-2010 * * License: * @@ -37,23 +35,17 @@ extern char main_config_file[MAX_FILENAME_LENGTH]; extern char url_html_path[MAX_FILENAME_LENGTH]; extern char url_images_path[MAX_FILENAME_LENGTH]; extern char command_file[MAX_FILENAME_LENGTH]; -extern char comment_file[MAX_FILENAME_LENGTH]; extern char url_stylesheets_path[MAX_FILENAME_LENGTH]; extern int nagios_process_state; -extern int check_external_commands; - extern int use_authentication; extern int lock_author_names; -extern scheduled_downtime *scheduled_downtime_list; -extern comment *comment_list; - -extern int date_format; - +extern int ack_no_sticky; +extern int ack_no_send; #define MAX_AUTHOR_LENGTH 64 #define MAX_COMMENT_LENGTH 1024 @@ -70,6 +62,7 @@ char *comment_author = ""; char *comment_data = ""; char *start_time_string = ""; char *end_time_string = ""; +char *cookie_form_id = NULL, *form_id = NULL; unsigned long comment_id = 0; unsigned long downtime_id = 0; @@ -119,6 +112,10 @@ int string_to_time(char *, time_t *); int main(void) { int result = OK; + int formid_ok = OK; + + /* Initialize shared configuration variables */ + init_shared_cfg_vars(1); /* get the arguments passed in the URL */ process_cgivars(); @@ -219,7 +216,15 @@ int main(void) { free_object_data(); return OK; + } + + if (cookie_form_id && *cookie_form_id) { + formid_ok = ERROR; + if (form_id && *form_id) { + if (!strcmp(form_id, cookie_form_id)) + formid_ok = OK; } + } /* if no command was specified... */ if(command_type == CMD_NONE) { @@ -234,8 +239,12 @@ int main(void) { request_command_data(command_type); /* the user wants to commit the command */ - else if(command_mode == CMDMODE_COMMIT) - commit_command_data(command_type); + else if(command_mode == CMDMODE_COMMIT) { + if (formid_ok == ERROR) /* we're expecting an id but it wasn't there... */ + printf("

Error: Invalid form id!

\n"); + else + commit_command_data(command_type); + } document_footer(); @@ -264,7 +273,7 @@ void document_header(int use_stylesheet) { else { - printf("Content-type: text/html\r\n\r\n"); + printf("Content-type: text/html; charset=utf-8\r\n\r\n"); printf("\n"); printf("\n"); @@ -321,7 +330,6 @@ int process_cgivars(void) { /* do some basic length checking on the variable identifier to prevent buffer overflows */ if(strlen(variables[x]) >= MAX_INPUT_BUFFER - 1) { - x++; continue; } @@ -654,8 +662,30 @@ int process_cgivars(void) { else if(!strcmp(variables[x], "broadcast_notification")) broadcast_notification = NOTIFICATION_OPTION_BROADCAST; + /* we found the cookie form id */ + else if (!strcmp(variables[x], "NagFormId")) { + x++; + if (variables[x] == NULL) { + error = TRUE; + break; + } + + cookie_form_id = (char*)strdup(variables[x]); } + /* we found the form id on the form */ + else if (!strcmp(variables[x], "nagFormId")) { + x++; + if (variables[x] == NULL) { + error = TRUE; + break; + } + + form_id = (char*)strdup(variables[x]); + } + + } + /* free memory allocated to the CGI variables */ free_cgivars(variables); @@ -666,7 +696,7 @@ int process_cgivars(void) { void request_command_data(int cmd) { time_t t; - char start_time[MAX_DATETIME_LENGTH]; + char start_time_str[MAX_DATETIME_LENGTH]; char buffer[MAX_INPUT_BUFFER]; contact *temp_contact; scheduled_downtime *temp_downtime; @@ -851,11 +881,6 @@ void request_command_data(int cmd) { printf("cancel scheduled downtime for a particular %s", (cmd == CMD_DEL_HOST_DOWNTIME) ? "host" : "service"); break; - case CMD_ENABLE_FAILURE_PREDICTION: - case CMD_DISABLE_FAILURE_PREDICTION: - printf("%s failure prediction for hosts and service", (cmd == CMD_ENABLE_FAILURE_PREDICTION) ? "enable" : "disable"); - break; - case CMD_ENABLE_PERFORMANCE_DATA: case CMD_DISABLE_PERFORMANCE_DATA: printf("%s performance data processing for hosts and services", (cmd == CMD_ENABLE_PERFORMANCE_DATA) ? "enable" : "disable"); @@ -926,6 +951,11 @@ void request_command_data(int cmd) { printf("schedule downtime for all services in a particular servicegroup"); break; + case CMD_CLEAR_HOST_FLAPPING_STATE: + case CMD_CLEAR_SVC_FLAPPING_STATE: + printf("clear flapping state for a %s", (cmd == CMD_CLEAR_HOST_FLAPPING_STATE) ? "host" : "service"); + break; + case CMD_SEND_CUSTOM_HOST_NOTIFICATION: case CMD_SEND_CUSTOM_SVC_NOTIFICATION: printf("send a custom %s notification", (cmd == CMD_SEND_CUSTOM_HOST_NOTIFICATION) ? "host" : "service"); @@ -950,6 +980,8 @@ void request_command_data(int cmd) { printf("\n"); printf("\n", cmd, CMDMODE_COMMIT); @@ -963,10 +995,10 @@ void request_command_data(int cmd) { printf("\n"); if(cmd == CMD_ACKNOWLEDGE_HOST_PROBLEM) { printf("\n"); printf("\n"); } printf("\n"); printf("\n"); } printf("\n"); @@ -1096,6 +1129,7 @@ void request_command_data(int cmd) { case CMD_DISABLE_PASSIVE_HOST_CHECKS: case CMD_START_OBSESSING_OVER_HOST: case CMD_STOP_OBSESSING_OVER_HOST: + case CMD_CLEAR_HOST_FLAPPING_STATE: printf("\n"); @@ -1125,8 +1159,6 @@ void request_command_data(int cmd) { case CMD_STOP_OBSESSING_OVER_SVC_CHECKS: case CMD_ENABLE_FLAP_DETECTION: case CMD_DISABLE_FLAP_DETECTION: - case CMD_ENABLE_FAILURE_PREDICTION: - case CMD_DISABLE_FAILURE_PREDICTION: case CMD_ENABLE_PERFORMANCE_DATA: case CMD_DISABLE_PERFORMANCE_DATA: case CMD_START_EXECUTING_HOST_CHECKS: @@ -1199,15 +1231,15 @@ void request_command_data(int cmd) { if(temp_downtime->type != HOST_DOWNTIME) continue; printf("
\n"); printf("
\n", COMMAND_CGI); + if (cookie_form_id && *cookie_form_id) + printf("\n"); printf("
Sticky Acknowledgement:"); - printf(""); + printf("", (ack_no_sticky == TRUE) ? "" : "CHECKED"); printf("
Send Notification:"); - printf(""); + printf("", (ack_no_send == TRUE) ? "" : "CHECKED"); printf("
Persistent%s:", (cmd == CMD_ACKNOWLEDGE_HOST_PROBLEM) ? " Comment" : ""); @@ -989,10 +1021,10 @@ void request_command_data(int cmd) { printf("", escape_string(service_desc)); if(cmd == CMD_ACKNOWLEDGE_SVC_PROBLEM) { printf("
Sticky Acknowledgement:"); - printf(""); + printf("", (ack_no_sticky == TRUE) ? "" : "CHECKED"); printf("
Send Notification:"); - printf(""); + printf("", (ack_no_send == TRUE) ? "" : "CHECKED"); printf("
Persistent%s:", (cmd == CMD_ACKNOWLEDGE_SVC_PROBLEM) ? " Comment" : ""); @@ -1068,6 +1100,7 @@ void request_command_data(int cmd) { case CMD_DISABLE_SVC_FLAP_DETECTION: case CMD_START_OBSESSING_OVER_SVC: case CMD_STOP_OBSESSING_OVER_SVC: + case CMD_CLEAR_SVC_FLAPPING_STATE: printf("
Host Name:"); printf("", escape_string(host_name)); printf("
Host Name:"); printf("", escape_string(host_name)); printf("
\n"); @@ -2626,14 +2661,6 @@ void show_command_help(cmd) { printf("This command is used to cancel active or pending scheduled downtime for the specified service.\n"); break; - case CMD_ENABLE_FAILURE_PREDICTION: - printf("This command is used to enable failure prediction for hosts and services on a program-wide basis. Individual hosts and services may have failure prediction disabled.\n"); - break; - - case CMD_DISABLE_FAILURE_PREDICTION: - printf("This command is used to disable failure prediction for hosts and services on a program-wide basis.\n"); - break; - case CMD_ENABLE_PERFORMANCE_DATA: printf("This command is used to enable the processing of performance data for hosts and services on a program-wide basis. Individual hosts and services may have performance data processing disabled.\n"); break; @@ -2648,7 +2675,7 @@ void show_command_help(cmd) { printf("across program shutdowns and restarts. Both the start and end times should be specified in the following format: mm/dd/yyyy hh:mm:ss.\n"); printf("If you select the fixed option, the downtime will be in effect between the start and end times you specify. If you do not select the fixed\n"); printf("option, Nagios will treat this as \"flexible\" downtime. Flexible downtime starts when a host goes down or becomes unreachable (sometime between the\n"); - printf("start and end times you specified) and lasts as long as the duration of time you enter. The duration fields do not apply for fixed dowtime.\n"); + printf("start and end times you specified) and lasts as long as the duration of time you enter. The duration fields do not apply for fixed downtime.\n"); break; case CMD_SCHEDULE_HOSTGROUP_SVC_DOWNTIME: @@ -2657,7 +2684,7 @@ void show_command_help(cmd) { printf("across program shutdowns and restarts. Both the start and end times should be specified in the following format: mm/dd/yyyy hh:mm:ss.\n"); printf("If you select the fixed option, the downtime will be in effect between the start and end times you specify. If you do not select the fixed\n"); printf("option, Nagios will treat this as \"flexible\" downtime. Flexible downtime starts when a service enters a non-OK state (sometime between the\n"); - printf("start and end times you specified) and lasts as long as the duration of time you enter. The duration fields do not apply for fixed dowtime.\n"); + printf("start and end times you specified) and lasts as long as the duration of time you enter. The duration fields do not apply for fixed downtime.\n"); printf("Note that scheduling downtime for services does not automatically schedule downtime for the hosts those services are associated with. If you want to also schedule downtime for all hosts in the hostgroup, check the 'Schedule downtime for hosts too' option.\n"); break; @@ -2748,7 +2775,7 @@ void show_command_help(cmd) { printf("across program shutdowns and restarts. Both the start and end times should be specified in the following format: mm/dd/yyyy hh:mm:ss.\n"); printf("If you select the fixed option, the downtime will be in effect between the start and end times you specify. If you do not select the fixed\n"); printf("option, Nagios will treat this as \"flexible\" downtime. Flexible downtime starts when a host goes down or becomes unreachable (sometime between the\n"); - printf("start and end times you specified) and lasts as long as the duration of time you enter. The duration fields do not apply for fixed dowtime.\n"); + printf("start and end times you specified) and lasts as long as the duration of time you enter. The duration fields do not apply for fixed downtime.\n"); break; case CMD_SCHEDULE_SERVICEGROUP_SVC_DOWNTIME: @@ -2757,10 +2784,18 @@ void show_command_help(cmd) { printf("across program shutdowns and restarts. Both the start and end times should be specified in the following format: mm/dd/yyyy hh:mm:ss.\n"); printf("If you select the fixed option, the downtime will be in effect between the start and end times you specify. If you do not select the fixed\n"); printf("option, Nagios will treat this as \"flexible\" downtime. Flexible downtime starts when a service enters a non-OK state (sometime between the\n"); - printf("start and end times you specified) and lasts as long as the duration of time you enter. The duration fields do not apply for fixed dowtime.\n"); + printf("start and end times you specified) and lasts as long as the duration of time you enter. The duration fields do not apply for fixed downtime.\n"); printf("Note that scheduling downtime for services does not automatically schedule downtime for the hosts those services are associated with. If you want to also schedule downtime for all hosts in the servicegroup, check the 'Schedule downtime for hosts too' option.\n"); break; + case CMD_CLEAR_HOST_FLAPPING_STATE: + case CMD_CLEAR_SVC_FLAPPING_STATE: + printf("This command is used to reset the flapping state for the specified %s.\n", + (cmd == CMD_CLEAR_HOST_FLAPPING_STATE) ? "host" : "service"); + printf("All state history for the specified %s will be cleared.\n", + (cmd == CMD_CLEAR_HOST_FLAPPING_STATE) ? "host" : "service"); + break; + case CMD_SEND_CUSTOM_HOST_NOTIFICATION: case CMD_SEND_CUSTOM_SVC_NOTIFICATION: printf("This command is used to send a custom notification about the specified %s. Useful in emergencies when you need to notify admins of an issue regarding a monitored system or service.\n", (cmd == CMD_SEND_CUSTOM_HOST_NOTIFICATION) ? "host" : "service"); diff --git a/cgi/config.c b/cgi/config.c index ae1c693..8db78cc 100644 --- a/cgi/config.c +++ b/cgi/config.c @@ -2,8 +2,6 @@ * * CONFIG.C - Nagios Configuration CGI (View Only) * - * Copyright (c) 1999-2009 Ethan Galstad (egalstad@nagios.org) - * Last Modified: 05-15-2009 * * This CGI program will display various configuration information. * @@ -39,20 +37,6 @@ extern char url_images_path[MAX_FILENAME_LENGTH]; extern char url_logo_images_path[MAX_FILENAME_LENGTH]; extern char url_stylesheets_path[MAX_FILENAME_LENGTH]; -extern host *host_list; -extern service *service_list; -extern hostgroup *hostgroup_list; -extern servicegroup *servicegroup_list; -extern contactgroup *contactgroup_list; -extern command *command_list; -extern timeperiod *timeperiod_list; -extern contact *contact_list; -extern servicedependency *servicedependency_list; -extern serviceescalation *serviceescalation_list; -extern hostdependency *hostdependency_list; -extern hostescalation *hostescalation_list; - - #define DISPLAY_NONE 0 #define DISPLAY_HOSTS 1 #define DISPLAY_HOSTGROUPS 2 @@ -100,8 +84,8 @@ char hashed_color[8]; int embedded = FALSE; -void print_expand_input(int type) { - char *seldesc = ""; +static void print_expand_input(int type) { + const char *seldesc = ""; if(type == DISPLAY_COMMAND_EXPANSION) return; /* Has its own form, w/ larger */ else if(type == DISPLAY_SERVICES) { @@ -125,7 +109,6 @@ void print_expand_input(int type) { } int main(void) { - int result = OK; mac = get_global_macros(); /* get the arguments passed in the URL */ @@ -134,32 +117,7 @@ int main(void) { /* reset internal variables */ reset_cgi_vars(); - /* read the CGI configuration file */ - result = read_cgi_config_file(get_cgi_config_location()); - if(result == ERROR) { - document_header(FALSE); - cgi_config_file_error(get_cgi_config_location()); - document_footer(); - return ERROR; - } - - /* read the main configuration file */ - result = read_main_config_file(main_config_file); - if(result == ERROR) { - document_header(FALSE); - main_config_file_error(main_config_file); - document_footer(); - return ERROR; - } - - /* read all object configuration data */ - result = read_all_object_configuration_data(main_config_file, READ_ALL_OBJECT_DATA); - if(result == ERROR) { - document_header(FALSE); - object_data_error(); - document_footer(); - return ERROR; - } + cgi_init(document_header, document_footer, READ_ALL_OBJECT_DATA, 0); /* initialize macros */ init_macros(); @@ -333,7 +291,7 @@ void document_header(int use_stylesheet) { printf("Pragma: no-cache\r\n"); printf("Last-Modified: %s\r\n", date_time); printf("Expires: %s\r\n", date_time); - printf("Content-type: text/html\r\n\r\n"); + printf("Content-type: text/html; charset=utf-8\r\n\r\n"); printf("\n"); printf("\n"); @@ -386,7 +344,6 @@ int process_cgivars(void) { /* do some basic length checking on the variable identifier to prevent buffer overflows */ if(strlen(variables[x]) >= MAX_INPUT_BUFFER - 1) { - x++; continue; } @@ -466,8 +423,8 @@ void display_hosts(void) { int options = 0; int odd = 0; char time_string[16]; - char *bg_class = ""; - int contact = 0; + const char *bg_class = ""; + int num_contacts = 0; /* see if user is authorized to view host information... */ if(is_authorized_for_configuration_information(¤t_authdata) == FALSE) { @@ -485,6 +442,8 @@ void display_hosts(void) { printf(""); printf(""); printf(""); + printf(""); + printf(""); printf(""); printf(""); printf("\n"); @@ -509,8 +468,6 @@ void display_hosts(void) { printf(""); printf("\n"); printf(""); - printf(""); - printf(""); printf(""); printf(""); printf(""); @@ -544,6 +501,8 @@ void display_hosts(void) { url_encode(temp_host->name), CONFIG_CGI, url_encode(temp_host->name), html_encode(temp_host->name, FALSE)); printf("\n", bg_class, html_encode(temp_host->alias, FALSE)); printf("\n", bg_class, html_encode(temp_host->address, FALSE)); + printf("\n", bg_class, temp_host->hourly_value); + printf("\n", bg_class, temp_host->hourly_value + host_services_value(temp_host)); printf("\n", bg_class, time_string); printf("\n",CONFIG_CGI,url_encode(strtok(temp_host->host_check_command,"!")),html_encode(temp_host->host_check_command,FALSE)); */ - printf("%s\n", CONFIG_CGI, url_encode(temp_host->host_check_command), html_encode(temp_host->host_check_command, FALSE)); + printf("%s\n", CONFIG_CGI, url_encode(temp_host->check_command), html_encode(temp_host->check_command, FALSE)); printf("\n"); printf("\n"); - printf("\n", bg_class, (temp_host->obsess_over_host == TRUE) ? "Yes" : "No"); + printf("\n", bg_class, (temp_host->obsess == TRUE) ? "Yes" : "No"); printf("\n", bg_class, (temp_host->checks_enabled == TRUE) ? "Yes" : "No"); - printf("\n", bg_class, (temp_host->accept_passive_host_checks == TRUE) ? "Yes" : "No"); + printf("\n", bg_class, (temp_host->accept_passive_checks == TRUE) ? "Yes" : "No"); printf("\n", bg_class, (temp_host->check_freshness == TRUE) ? "Yes" : "No"); @@ -598,21 +556,21 @@ void display_hosts(void) { printf("\n"); @@ -624,23 +582,23 @@ void display_hosts(void) { printf("\n"); - printf("\n"); - - printf("\n", bg_class, (temp_host->failure_prediction_options == NULL) ? " " : html_encode(temp_host->failure_prediction_options, FALSE)); - printf("", bg_class, (temp_host->notes == NULL) ? " " : html_encode(temp_host->notes, FALSE)); printf("", bg_class, (temp_host->notes_url == NULL) ? " " : html_encode(temp_host->notes_url, FALSE)); @@ -797,7 +749,7 @@ void display_hostgroups(void) { hostgroup *temp_hostgroup; hostsmember *temp_hostsmember; int odd = 0; - char *bg_class = ""; + const char *bg_class = ""; /* see if user is authorized to view hostgroup information... */ if(is_authorized_for_configuration_information(¤t_authdata) == FALSE) { @@ -872,7 +824,7 @@ void display_servicegroups(void) { servicegroup *temp_servicegroup; servicesmember *temp_servicesmember; int odd = 0; - char *bg_class = ""; + const char *bg_class = ""; /* see if user is authorized to view servicegroup information... */ if(is_authorized_for_configuration_information(¤t_authdata) == FALSE) { @@ -951,7 +903,7 @@ void display_contacts(void) { int odd = 0; int options; int found; - char *bg_class = ""; + const char *bg_class = ""; /* see if user is authorized to view contact information... */ if(is_authorized_for_configuration_information(¤t_authdata) == FALSE) { @@ -972,6 +924,7 @@ void display_contacts(void) { printf(""); printf(""); printf(""); + printf(""); printf(""); printf(""); printf(""); @@ -999,30 +952,31 @@ void display_contacts(void) { printf("\n", bg_class, html_encode(temp_contact->alias, FALSE)); printf("\n", bg_class, (temp_contact->email == NULL) ? " " : url_encode(temp_contact->email), (temp_contact->email == NULL) ? " " : html_encode(temp_contact->email, FALSE)); printf("\n", bg_class, (temp_contact->pager == NULL) ? " " : html_encode(temp_contact->pager, FALSE)); + printf("\n", bg_class, temp_contact->minimum_value); printf("\n"); printf("\n"); printf("\n"); + printf("\n"); printf("\n"); printf("\n"); - printf("\n"); + printf("\n"); printf("\n"); printf("\n"); printf("\n"); @@ -1254,8 +1209,6 @@ void display_services(void) { printf(""); printf(""); printf(""); - printf(""); - printf(""); printf(""); printf(""); printf(""); @@ -1287,6 +1240,7 @@ void display_services(void) { printf("%s\n", CONFIG_CGI, url_encode(temp_service->host_name), html_encode(temp_service->host_name, FALSE)); printf("\n", bg_class, html_encode(temp_service->description, FALSE)); + printf("\n", bg_class, temp_service->hourly_value); printf("\n", bg_class, temp_service->max_attempts); @@ -1295,7 +1249,7 @@ void display_services(void) { get_interval_time_string(temp_service->retry_interval, time_string, sizeof(time_string)); printf("\n", bg_class, time_string); - strncpy(command_line, temp_service->service_check_command, sizeof(command_line)); + strncpy(command_line, temp_service->check_command, sizeof(command_line)); command_line[sizeof(command_line) - 1] = '\x0'; command_name = strtok(strdup(command_line), "!"); @@ -1313,11 +1267,11 @@ void display_services(void) { printf("\n", bg_class, (temp_service->is_volatile == TRUE) ? "Yes" : "No"); - printf("\n", bg_class, (temp_service->obsess_over_service == TRUE) ? "Yes" : "No"); + printf("\n", bg_class, (temp_service->obsess == TRUE) ? "Yes" : "No"); printf("\n", bg_class, (temp_service->checks_enabled == TRUE) ? "Yes" : "No"); - printf("\n", bg_class, (temp_service->accept_passive_service_checks == TRUE) ? "Yes" : "No"); + printf("\n", bg_class, (temp_service->accept_passive_checks == TRUE) ? "Yes" : "No"); printf("\n", bg_class, (temp_service->check_freshness == TRUE) ? "Yes" : "No"); @@ -1329,20 +1283,20 @@ void display_services(void) { printf("\n"); printf("\n"); @@ -1358,27 +1312,27 @@ void display_services(void) { printf("\n"); - printf("\n"); - - printf("\n", bg_class, (temp_service->failure_prediction_options == NULL) ? " " : html_encode(temp_service->failure_prediction_options, FALSE)); - printf("", bg_class, (temp_service->notes == NULL) ? " " : html_encode(temp_service->notes, FALSE)); printf("", bg_class, (temp_service->notes_url == NULL) ? " " : html_encode(temp_service->notes_url, FALSE)); @@ -1522,12 +1470,12 @@ void display_timeperiods(void) { daterange *temp_daterange = NULL; timeperiod *temp_timeperiod = NULL; timeperiodexclusion *temp_timeperiodexclusion = NULL; - char *months[12] = {"january", "february", "march", "april", "may", "june", "july", "august", "september", "october", "november", "december"}; - char *days[7] = {"sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"}; + const char *months[12] = {"january", "february", "march", "april", "may", "june", "july", "august", "september", "october", "november", "december"}; + const char *days[7] = {"sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"}; int odd = 0; int day = 0; int x = 0; - char *bg_class = ""; + const char *bg_class = ""; char timestring[10]; int hours = 0; int minutes = 0; @@ -1718,7 +1666,7 @@ void display_timeperiods(void) { void display_commands(void) { command *temp_command; int odd = 0; - char *bg_class = ""; + const char *bg_class = ""; /* see if user is authorized to view command information... */ if(is_authorized_for_configuration_information(¤t_authdata) == FALSE) { @@ -1760,12 +1708,70 @@ void display_commands(void) { } +static void display_servicedependency(servicedependency *temp_sd) +{ + const char *bg_class; + static int odd = 0; + int options; + + if(*to_expand != '\0' && (strcmp(to_expand, temp_sd->dependent_host_name) || strcmp(to_expand, temp_sd->host_name))) + return; + + if(odd) + bg_class = "dataOdd"; + else + bg_class = "dataEven"; + odd ^= 1; /* xor with 1 always flips the switch */ + + printf("\n", bg_class); + + printf("", bg_class, CONFIG_CGI, url_encode(temp_sd->dependent_host_name), html_encode(temp_sd->dependent_host_name, FALSE)); + + printf("\n", url_encode(temp_sd->dependent_service_description), html_encode(temp_sd->dependent_service_description, FALSE)); + + printf("", bg_class, CONFIG_CGI, url_encode(temp_sd->host_name), html_encode(temp_sd->host_name, FALSE)); + + printf("\n", url_encode(temp_sd->service_description), html_encode(temp_sd->service_description, FALSE)); + + printf("", bg_class, (temp_sd->dependency_type == NOTIFICATION_DEPENDENCY) ? "Notification" : "Check Execution"); + + printf("\n"); + + printf("\n"); + printf("\n"); + } void display_servicedependencies(void) { - servicedependency *temp_sd; - int odd = 0; - int options; - char *bg_class = ""; + unsigned int i; /* see if user is authorized to view hostgroup information... */ if(is_authorized_for_configuration_information(¤t_authdata) == FALSE) { @@ -1794,66 +1800,9 @@ void display_servicedependencies(void) { printf(""); printf("\n"); - /* check all the service dependencies... */ - for(temp_sd = servicedependency_list; temp_sd != NULL; temp_sd = temp_sd->next) - if(((*to_expand) == '\0') || (!strcmp(to_expand, temp_sd->dependent_host_name)) || (!strcmp(to_expand, temp_sd->host_name))) { - - if(odd) { - odd = 0; - bg_class = "dataOdd"; - } - else { - odd = 1; - bg_class = "dataEven"; - } - - printf("\n", bg_class); - - printf("", bg_class, CONFIG_CGI, url_encode(temp_sd->dependent_host_name), html_encode(temp_sd->dependent_host_name, FALSE)); - - printf("\n", url_encode(temp_sd->dependent_service_description), html_encode(temp_sd->dependent_service_description, FALSE)); - - printf("", bg_class, CONFIG_CGI, url_encode(temp_sd->host_name), html_encode(temp_sd->host_name, FALSE)); - - printf("\n", url_encode(temp_sd->service_description), html_encode(temp_sd->service_description, FALSE)); - - printf("", bg_class, (temp_sd->dependency_type == NOTIFICATION_DEPENDENCY) ? "Notification" : "Check Execution"); - - printf("\n"); - - printf("\n"); - - printf("\n"); - } + for(i = 0; i < num_objects.servicedependencies; i++) { + display_servicedependency(servicedependency_ary[i]); + } printf("
Host NameAlias/DescriptionAddressImportance (Host)Importance (Host + Services)Parent HostsMax. Check AttemptsCheck IntervalHigh Flap ThresholdFlap Detection OptionsProcess Performance DataEnable Failure PredictionFailure Prediction OptionsNotesNotes URLAction URL%s%s%u%u", bg_class); for(temp_hostsmember = temp_host->parent_hosts; temp_hostsmember != NULL; temp_hostsmember = temp_hostsmember->next) { @@ -566,11 +525,10 @@ void display_hosts(void) { printf("%s", bg_class); - if(temp_host->host_check_command == NULL) + if(temp_host->check_command == NULL) printf(" "); else - /* printf("%s", bg_class); @@ -580,11 +538,11 @@ void display_hosts(void) { printf("%s", CONFIG_CGI, url_encode(temp_host->check_period), html_encode(temp_host->check_period, FALSE)); printf("%s%s%s%s%s%s", bg_class); /* find all the contacts for this host... */ - contact = 0; + num_contacts = 0; for(temp_contactsmember = temp_host->contacts; temp_contactsmember != NULL; temp_contactsmember = temp_contactsmember->next) { - contact++; - if(contact > 1) + num_contacts++; + if(num_contacts > 1) printf(", "); printf("%s\n", CONFIG_CGI, url_encode(temp_contactsmember->contact_name), html_encode(temp_contactsmember->contact_name, FALSE)); } for(temp_contactgroupsmember = temp_host->contact_groups; temp_contactgroupsmember != NULL; temp_contactgroupsmember = temp_contactgroupsmember->next) { - contact++; - if(contact > 1) + num_contacts++; + if(num_contacts > 1) printf(", "); printf("%s\n", CONFIG_CGI, url_encode(temp_contactgroupsmember->group_name), html_encode(temp_contactgroupsmember->group_name, FALSE)); } - if(contact == 0) + if(num_contacts == 0) printf(" "); printf("", bg_class); options = 0; - if(temp_host->notify_on_down == TRUE) { + if(flag_isset(temp_host->notification_options, OPT_DOWN) == TRUE) { options = 1; printf("Down"); } - if(temp_host->notify_on_unreachable == TRUE) { + if(flag_isset(temp_host->notification_options, OPT_UNREACHABLE) == TRUE) { printf("%sUnreachable", (options) ? ", " : ""); options = 1; } - if(temp_host->notify_on_recovery == TRUE) { + if(flag_isset(temp_host->notification_options, OPT_RECOVERY) == TRUE) { printf("%sRecovery", (options) ? ", " : ""); options = 1; } - if(temp_host->notify_on_flapping == TRUE) { + if(flag_isset(temp_host->notification_options, OPT_FLAPPING) == TRUE) { printf("%sFlapping", (options) ? ", " : ""); options = 1; } - if(temp_host->notify_on_downtime == TRUE) { + if(flag_isset(temp_host->notification_options, OPT_DOWNTIME) == TRUE) { printf("%sDowntime", (options) ? ", " : ""); options = 1; } @@ -669,15 +627,15 @@ void display_hosts(void) { printf("", bg_class); options = 0; - if(temp_host->stalk_on_up == TRUE) { + if(flag_isset(temp_host->stalking_options, OPT_UP) == TRUE) { options = 1; printf("Up"); } - if(temp_host->stalk_on_down == TRUE) { + if(flag_isset(temp_host->stalking_options, OPT_DOWN) == TRUE) { printf("%sDown", (options) ? ", " : ""); options = 1; } - if(temp_host->stalk_on_unreachable == TRUE) { + if(flag_isset(temp_host->stalking_options, OPT_UNREACHABLE) == TRUE) { printf("%sUnreachable", (options) ? ", " : ""); options = 1; } @@ -705,15 +663,15 @@ void display_hosts(void) { printf("", bg_class); options = 0; - if(temp_host->flap_detection_on_up == TRUE) { + if(flag_isset(temp_host->flap_detection_options, OPT_UP) == TRUE) { options = 1; printf("Up"); } - if(temp_host->flap_detection_on_down == TRUE) { + if(flag_isset(temp_host->flap_detection_options, OPT_DOWN) == TRUE) { printf("%sDown", (options) ? ", " : ""); options = 1; } - if(temp_host->flap_detection_on_unreachable == TRUE) { + if(flag_isset(temp_host->flap_detection_options, OPT_UNREACHABLE) == TRUE) { printf("%sUnreachable", (options) ? ", " : ""); options = 1; } @@ -725,12 +683,6 @@ void display_hosts(void) { printf("%s\n", (temp_host->process_performance_data == TRUE) ? "Yes" : "No"); printf("", bg_class); - printf("%s\n", (temp_host->failure_prediction_enabled == TRUE) ? "Yes" : "No"); - printf("%s%s%sAliasEmail AddressPager Address/NumberMinimum ImportanceService Notification OptionsHost Notification OptionsService Notification Period%s%s%s%u", bg_class); options = 0; - if(temp_contact->notify_on_service_unknown == TRUE) { + if(flag_isset(temp_contact->service_notification_options, OPT_UNKNOWN)) { options = 1; printf("Unknown"); } - if(temp_contact->notify_on_service_warning == TRUE) { + if(flag_isset(temp_contact->service_notification_options, OPT_WARNING)) { printf("%sWarning", (options) ? ", " : ""); options = 1; } - if(temp_contact->notify_on_service_critical == TRUE) { + if(flag_isset(temp_contact->service_notification_options, OPT_CRITICAL)) { printf("%sCritical", (options) ? ", " : ""); options = 1; } - if(temp_contact->notify_on_service_recovery == TRUE) { + if(flag_isset(temp_contact->service_notification_options, OPT_RECOVERY)) { printf("%sRecovery", (options) ? ", " : ""); options = 1; } - if(temp_contact->notify_on_service_flapping == TRUE) { + if(flag_isset(temp_contact->service_notification_options, OPT_FLAPPING)) { printf("%sFlapping", (options) ? ", " : ""); options = 1; } - if(temp_contact->notify_on_service_downtime == TRUE) { + if(flag_isset(temp_contact->service_notification_options, OPT_DOWNTIME)) { printf("%sDowntime", (options) ? ", " : ""); options = 1; } @@ -1032,23 +986,23 @@ void display_contacts(void) { printf("", bg_class); options = 0; - if(temp_contact->notify_on_host_down == TRUE) { + if(flag_isset(temp_contact->host_notification_options, OPT_DOWN) == TRUE) { options = 1; printf("Down"); } - if(temp_contact->notify_on_host_unreachable == TRUE) { + if(flag_isset(temp_contact->host_notification_options, OPT_UNREACHABLE) == TRUE) { printf("%sUnreachable", (options) ? ", " : ""); options = 1; } - if(temp_contact->notify_on_host_recovery == TRUE) { + if(flag_isset(temp_contact->host_notification_options, OPT_RECOVERY) == TRUE) { printf("%sRecovery", (options) ? ", " : ""); options = 1; } - if(temp_contact->notify_on_host_flapping == TRUE) { + if(flag_isset(temp_contact->host_notification_options, OPT_FLAPPING) == TRUE) { printf("%sFlapping", (options) ? ", " : ""); options = 1; } - if(temp_contact->notify_on_host_downtime == TRUE) { + if(flag_isset(temp_contact->host_notification_options, OPT_DOWNTIME) == TRUE) { printf("%sDowntime", (options) ? ", " : ""); options = 1; } @@ -1132,7 +1086,7 @@ void display_contactgroups(void) { contactgroup *temp_contactgroup; contactsmember *temp_contactsmember; int odd = 0; - char *bg_class = ""; + const char *bg_class = ""; /* see if user is authorized to view contactgroup information... */ if(is_authorized_for_configuration_information(¤t_authdata) == FALSE) { @@ -1201,12 +1155,12 @@ void display_services(void) { contactgroupsmember *temp_contactgroupsmember = NULL; char *processed_string = NULL; char command_line[MAX_INPUT_BUFFER]; - char *command_name = ""; + char *command_name; int options; int odd = 0; char time_string[16]; - char *bg_class; - int contact = 0; + const char *bg_class; + int num_contacts = 0; /* see if user is authorized to view service information... */ @@ -1228,9 +1182,10 @@ void display_services(void) { printf("
HostDescriptionImportanceMax. Check AttemptsNormal Check IntervalRetry Check InteralRetry Check IntervalCheck CommandCheck PeriodParallelizeHigh Flap ThresholdFlap Detection OptionsProcess Performance DataEnable Failure PredictionFailure Prediction OptionsNotesNotes URLAction URL%s%u%d%s%s%s%s%s%s%s%s", bg_class); - contact = 0; + num_contacts = 0; for(temp_contactsmember = temp_service->contacts; temp_contactsmember != NULL; temp_contactsmember = temp_contactsmember->next) { - contact++; - if(contact > 1) + num_contacts++; + if(num_contacts > 1) printf(", "); printf("%s", CONFIG_CGI, url_encode(temp_contactsmember->contact_name), html_encode(temp_contactsmember->contact_name, FALSE)); } for(temp_contactgroupsmember = temp_service->contact_groups; temp_contactgroupsmember != NULL; temp_contactgroupsmember = temp_contactgroupsmember->next) { - contact++; - if(contact > 1) + num_contacts++; + if(num_contacts > 1) printf(", "); printf("%s\n", CONFIG_CGI, url_encode(temp_contactgroupsmember->group_name), html_encode(temp_contactgroupsmember->group_name, FALSE)); } - if(contact == 0) + if(num_contacts == 0) printf(" "); printf("", bg_class); options = 0; - if(temp_service->notify_on_unknown == TRUE) { + if(flag_isset(temp_service->notification_options, OPT_UNKNOWN) == TRUE) { options = 1; printf("Unknown"); } - if(temp_service->notify_on_warning == TRUE) { + if(flag_isset(temp_service->notification_options, OPT_WARNING) == TRUE) { printf("%sWarning", (options) ? ", " : ""); options = 1; } - if(temp_service->notify_on_critical == TRUE) { + if(flag_isset(temp_service->notification_options, OPT_CRITICAL) == TRUE) { printf("%sCritical", (options) ? ", " : ""); options = 1; } - if(temp_service->notify_on_recovery == TRUE) { + if(flag_isset(temp_service->notification_options, OPT_RECOVERY) == TRUE) { printf("%sRecovery", (options) ? ", " : ""); options = 1; } - if(temp_service->notify_on_flapping == TRUE) { + if(flag_isset(temp_service->notification_options, OPT_FLAPPING) == TRUE) { printf("%sFlapping", (options) ? ", " : ""); options = 1; } - if(temp_service->notify_on_downtime == TRUE) { + if(flag_isset(temp_service->notification_options, OPT_DOWNTIME) == TRUE) { printf("%sDowntime", (options) ? ", " : ""); options = 1; } @@ -1405,19 +1359,19 @@ void display_services(void) { printf("", bg_class); options = 0; - if(temp_service->stalk_on_ok == TRUE) { + if(flag_isset(temp_service->stalking_options, OPT_OK) == TRUE) { options = 1; printf("Ok"); } - if(temp_service->stalk_on_warning == TRUE) { + if(flag_isset(temp_service->stalking_options, OPT_WARNING) == TRUE) { printf("%sWarning", (options) ? ", " : ""); options = 1; } - if(temp_service->stalk_on_unknown == TRUE) { + if(flag_isset(temp_service->stalking_options, OPT_UNKNOWN) == TRUE) { printf("%sUnknown", (options) ? ", " : ""); options = 1; } - if(temp_service->stalk_on_critical == TRUE) { + if(flag_isset(temp_service->stalking_options, OPT_CRITICAL) == TRUE) { printf("%sCritical", (options) ? ", " : ""); options = 1; } @@ -1445,19 +1399,19 @@ void display_services(void) { printf("", bg_class); options = 0; - if(temp_service->flap_detection_on_ok == TRUE) { + if(flag_isset(temp_service->flap_detection_options, OPT_OK) == TRUE) { options = 1; printf("Ok"); } - if(temp_service->flap_detection_on_warning == TRUE) { + if(flag_isset(temp_service->flap_detection_options, OPT_WARNING) == TRUE) { printf("%sWarning", (options) ? ", " : ""); options = 1; } - if(temp_service->flap_detection_on_unknown == TRUE) { + if(flag_isset(temp_service->flap_detection_options, OPT_UNKNOWN) == TRUE) { printf("%sUnknown", (options) ? ", " : ""); options = 1; } - if(temp_service->flap_detection_on_critical == TRUE) { + if(flag_isset(temp_service->flap_detection_options, OPT_CRITICAL) == TRUE) { printf("%sCritical", (options) ? ", " : ""); options = 1; } @@ -1469,12 +1423,6 @@ void display_services(void) { printf("%s\n", (temp_service->process_performance_data == TRUE) ? "Yes" : "No"); printf("", bg_class); - printf("%s\n", (temp_service->failure_prediction_enabled == TRUE) ? "Yes" : "No"); - printf("%s%s%s
%s%s%s%s%s", bg_class); + if(temp_sd->dependency_period == NULL) + printf(" "); + else + printf("%s", CONFIG_CGI, url_encode(temp_sd->dependency_period), html_encode(temp_sd->dependency_period, FALSE)); + printf("", bg_class); + options = FALSE; + if(flag_isset(temp_sd->failure_options, OPT_OK) == TRUE) { + printf("Ok"); + options = TRUE; + } + if(flag_isset(temp_sd->failure_options, OPT_WARNING) == TRUE) { + printf("%sWarning", (options == TRUE) ? ", " : ""); + options = TRUE; + } + if(flag_isset(temp_sd->failure_options, OPT_UNKNOWN) == TRUE) { + printf("%sUnknown", (options == TRUE) ? ", " : ""); + options = TRUE; + } + if(flag_isset(temp_sd->failure_options, OPT_CRITICAL) == TRUE) { + printf("%sCritical", (options == TRUE) ? ", " : ""); + options = TRUE; + } + if(flag_isset(temp_sd->failure_options, OPT_PENDING) == TRUE) { + printf("%sPending", (options == TRUE) ? ", " : ""); + options = TRUE; + } + printf("
Dependency Failure Options
%s%s%s%s%s", bg_class); - if(temp_sd->dependency_period == NULL) - printf(" "); - else - printf("%s", CONFIG_CGI, url_encode(temp_sd->dependency_period), html_encode(temp_sd->dependency_period, FALSE)); - printf("", bg_class); - options = FALSE; - if(temp_sd->fail_on_ok == TRUE) { - printf("Ok"); - options = TRUE; - } - if(temp_sd->fail_on_warning == TRUE) { - printf("%sWarning", (options == TRUE) ? ", " : ""); - options = TRUE; - } - if(temp_sd->fail_on_unknown == TRUE) { - printf("%sUnknown", (options == TRUE) ? ", " : ""); - options = TRUE; - } - if(temp_sd->fail_on_critical == TRUE) { - printf("%sCritical", (options == TRUE) ? ", " : ""); - options = TRUE; - } - if(temp_sd->fail_on_pending == TRUE) { - printf("%sPending", (options == TRUE) ? ", " : ""); - options = TRUE; - } - printf("
\n"); printf("\n"); @@ -1871,8 +1820,9 @@ void display_serviceescalations(void) { char time_string[16] = ""; int options = FALSE; int odd = 0; - char *bg_class = ""; - int contact = 0; + const char *bg_class = ""; + int num_contacts = 0; + unsigned int i; /* see if user is authorized to view hostgroup information... */ if(is_authorized_for_configuration_information(¤t_authdata) == FALSE) { @@ -1901,91 +1851,94 @@ void display_serviceescalations(void) { printf("
Escalation Options
%s%s", bg_class); - contact = 0; - for(temp_contactsmember = temp_se->contacts; temp_contactsmember != NULL; temp_contactsmember = temp_contactsmember->next) { - contact++; - if(contact > 1) - printf(", "); - printf("%s\n", CONFIG_CGI, url_encode(temp_contactsmember->contact_name), html_encode(temp_contactsmember->contact_name, FALSE)); - } - for(temp_contactgroupsmember = temp_se->contact_groups; temp_contactgroupsmember != NULL; temp_contactgroupsmember = temp_contactgroupsmember->next) { - contact++; - if(contact > 1) - printf(", "); - printf("%s\n", CONFIG_CGI, url_encode(temp_contactgroupsmember->group_name), html_encode(temp_contactgroupsmember->group_name, FALSE)); - } - if(contact == 0) - printf(" "); - printf("%d", bg_class); - if(temp_se->last_notification == 0) - printf("Infinity"); - else - printf("%d", temp_se->last_notification); - printf("", bg_class); - if(temp_se->notification_interval == 0.0) - printf("Notify Only Once (No Re-notification)"); - else - printf("%s", time_string); - printf("", bg_class); - if(temp_se->escalation_period == NULL) - printf(" "); - else - printf("%s", CONFIG_CGI, url_encode(temp_se->escalation_period), html_encode(temp_se->escalation_period, FALSE)); - printf("", bg_class); - options = FALSE; - if(temp_se->escalate_on_warning == TRUE) { - printf("%sWarning", (options == TRUE) ? ", " : ""); - options = TRUE; - } - if(temp_se->escalate_on_unknown == TRUE) { - printf("%sUnknown", (options == TRUE) ? ", " : ""); - options = TRUE; - } - if(temp_se->escalate_on_critical == TRUE) { - printf("%sCritical", (options == TRUE) ? ", " : ""); - options = TRUE; - } - if(temp_se->escalate_on_recovery == TRUE) { - printf("%sRecovery", (options == TRUE) ? ", " : ""); - options = TRUE; - } - if(options == FALSE) - printf("None"); - printf("
%s%s", bg_class); + num_contacts = 0; + for(temp_contactsmember = temp_se->contacts; temp_contactsmember != NULL; temp_contactsmember = temp_contactsmember->next) { + num_contacts++; + if(num_contacts > 1) + printf(", "); + printf("%s\n", CONFIG_CGI, url_encode(temp_contactsmember->contact_name), html_encode(temp_contactsmember->contact_name, FALSE)); + } + for(temp_contactgroupsmember = temp_se->contact_groups; temp_contactgroupsmember != NULL; temp_contactgroupsmember = temp_contactgroupsmember->next) { + num_contacts++; + if(num_contacts > 1) + printf(", "); + printf("%s\n", CONFIG_CGI, url_encode(temp_contactgroupsmember->group_name), html_encode(temp_contactgroupsmember->group_name, FALSE)); + } + if(num_contacts == 0) + printf(" "); + printf("%d", bg_class); + if(temp_se->last_notification == 0) + printf("Infinity"); + else + printf("%d", temp_se->last_notification); + printf("", bg_class); + if(temp_se->notification_interval == 0.0) + printf("Notify Only Once (No Re-notification)"); + else + printf("%s", time_string); + printf("", bg_class); + if(temp_se->escalation_period == NULL) + printf(" "); + else + printf("%s", CONFIG_CGI, url_encode(temp_se->escalation_period), html_encode(temp_se->escalation_period, FALSE)); + printf("", bg_class); + options = FALSE; + if(flag_isset(temp_se->escalation_options, OPT_WARNING) == TRUE) { + printf("%sWarning", (options == TRUE) ? ", " : ""); + options = TRUE; + } + if(flag_isset(temp_se->escalation_options, OPT_UNKNOWN) == TRUE) { + printf("%sUnknown", (options == TRUE) ? ", " : ""); + options = TRUE; + } + if(flag_isset(temp_se->escalation_options, OPT_CRITICAL) == TRUE) { + printf("%sCritical", (options == TRUE) ? ", " : ""); + options = TRUE; + } + if(flag_isset(temp_se->escalation_options, OPT_RECOVERY) == TRUE) { + printf("%sRecovery", (options == TRUE) ? ", " : ""); + options = TRUE; + } + if(options == FALSE) + printf("None"); + printf("
\n"); printf("\n"); @@ -1994,13 +1947,61 @@ void display_serviceescalations(void) { return; } +static void display_hostdependency(hostdependency *temp_hd) +{ + int options; + const char *bg_class = ""; + static int odd = 0; + if(*to_expand != '\0' && (strcmp(to_expand, temp_hd->dependent_host_name) && !strcmp(to_expand, temp_hd->host_name))) + return; + + if(odd) + bg_class = "dataOdd"; + else + bg_class = "dataEven"; + odd ^= 1; + + printf("\n", bg_class); + + printf("%s", bg_class, CONFIG_CGI, url_encode(temp_hd->dependent_host_name), html_encode(temp_hd->dependent_host_name, FALSE)); + + printf("%s", bg_class, CONFIG_CGI, url_encode(temp_hd->host_name), html_encode(temp_hd->host_name, FALSE)); + + printf("%s", bg_class, (temp_hd->dependency_type == NOTIFICATION_DEPENDENCY) ? "Notification" : "Check Execution"); + + printf("", bg_class); + if(temp_hd->dependency_period == NULL) + printf(" "); + else + printf("%s", CONFIG_CGI, url_encode(temp_hd->dependency_period), html_encode(temp_hd->dependency_period, FALSE)); + printf("\n"); + + printf("", bg_class); + options = FALSE; + if(flag_isset(temp_hd->failure_options, OPT_UP) == TRUE) { + printf("Up"); + options = TRUE; + } + if(flag_isset(temp_hd->failure_options, OPT_DOWN) == TRUE) { + printf("%sDown", (options == TRUE) ? ", " : ""); + options = TRUE; + } + if(flag_isset(temp_hd->failure_options, OPT_UNREACHABLE) == TRUE) { + printf("%sUnreachable", (options == TRUE) ? ", " : ""); + options = TRUE; + } + if(flag_isset(temp_hd->failure_options, OPT_PENDING) == TRUE) { + printf("%sPending", (options == TRUE) ? ", " : ""); + options = TRUE; + } + printf("\n"); + + printf("\n"); + } void display_hostdependencies(void) { - hostdependency *temp_hd; - int odd = 0; - int options; - char *bg_class = ""; + unsigned int i; /* see if user is authorized to view hostdependency information... */ if(is_authorized_for_configuration_information(¤t_authdata) == FALSE) { @@ -2023,56 +2024,9 @@ void display_hostdependencies(void) { printf("Dependency Failure Options"); printf("\n"); - /* check all the host dependencies... */ - for(temp_hd = hostdependency_list; temp_hd != NULL; temp_hd = temp_hd->next) - if(((*to_expand) == '\0') || (!strcmp(to_expand, temp_hd->dependent_host_name)) || (!strcmp(to_expand, temp_hd->host_name))) { - - if(odd) { - odd = 0; - bg_class = "dataOdd"; - } - else { - odd = 1; - bg_class = "dataEven"; - } - - printf("\n", bg_class); - - printf("%s", bg_class, CONFIG_CGI, url_encode(temp_hd->dependent_host_name), html_encode(temp_hd->dependent_host_name, FALSE)); - - printf("%s", bg_class, CONFIG_CGI, url_encode(temp_hd->host_name), html_encode(temp_hd->host_name, FALSE)); - - printf("%s", bg_class, (temp_hd->dependency_type == NOTIFICATION_DEPENDENCY) ? "Notification" : "Check Execution"); - - printf("", bg_class); - if(temp_hd->dependency_period == NULL) - printf(" "); - else - printf("%s", CONFIG_CGI, url_encode(temp_hd->dependency_period), html_encode(temp_hd->dependency_period, FALSE)); - printf("\n"); - - printf("", bg_class); - options = FALSE; - if(temp_hd->fail_on_up == TRUE) { - printf("Up"); - options = TRUE; - } - if(temp_hd->fail_on_down == TRUE) { - printf("%sDown", (options == TRUE) ? ", " : ""); - options = TRUE; - } - if(temp_hd->fail_on_unreachable == TRUE) { - printf("%sUnreachable", (options == TRUE) ? ", " : ""); - options = TRUE; - } - if(temp_hd->fail_on_pending == TRUE) { - printf("%sPending", (options == TRUE) ? ", " : ""); - options = TRUE; - } - printf("\n"); - - printf("\n"); - } + /* print all host dependencies... */ + for(i = 0; i < num_objects.hostdependencies; i++) + display_hostdependency(hostdependency_ary[i]); printf("\n"); printf("\n"); @@ -2090,8 +2044,9 @@ void display_hostescalations(void) { char time_string[16] = ""; int options = FALSE; int odd = 0; - char *bg_class = ""; - int contact = 0; + const char *bg_class = ""; + int num_contacts = 0; + unsigned int i; /* see if user is authorized to view hostgroup information... */ if(is_authorized_for_configuration_information(¤t_authdata) == FALSE) { @@ -2116,84 +2071,87 @@ void display_hostescalations(void) { printf("Escalation Options"); printf("\n"); - /* check all the host escalations... */ - for(temp_he = hostescalation_list; temp_he != NULL; temp_he = temp_he->next) if(((*to_expand) == '\0') || (!strcmp(to_expand, temp_he->host_name))) { + /* print all hostescalations... */ + for(i = 0; i < num_objects.hostescalations; i++) { + temp_he = hostescalation_ary[i]; + if(*to_expand != '\0' && strcmp(to_expand, temp_he->host_name)) + continue; - if(odd) { - odd = 0; - bg_class = "dataOdd"; - } - else { - odd = 1; - bg_class = "dataEven"; - } - - printf("\n", bg_class); - - printf("%s", bg_class, CONFIG_CGI, url_encode(temp_he->host_name), html_encode(temp_he->host_name, FALSE)); - - printf("", bg_class); - contact = 0; - for(temp_contactsmember = temp_he->contacts; temp_contactsmember != NULL; temp_contactsmember = temp_contactsmember->next) { - contact++; - if(contact > 1) - printf(", "); - printf("%s\n", CONFIG_CGI, url_encode(temp_contactsmember->contact_name), html_encode(temp_contactsmember->contact_name, FALSE)); - } - for(temp_contactgroupsmember = temp_he->contact_groups; temp_contactgroupsmember != NULL; temp_contactgroupsmember = temp_contactgroupsmember->next) { - contact++; - if(contact > 1) - printf(", "); - printf("%s\n", CONFIG_CGI, url_encode(temp_contactgroupsmember->group_name), html_encode(temp_contactgroupsmember->group_name, FALSE)); - } - if(contact == 0) - printf(" "); - printf("\n"); - - printf("%d", bg_class, temp_he->first_notification); - - printf("", bg_class); - if(temp_he->last_notification == 0) - printf("Infinity"); - else - printf("%d", temp_he->last_notification); - printf("\n"); - - get_interval_time_string(temp_he->notification_interval, time_string, sizeof(time_string)); - printf("", bg_class); - if(temp_he->notification_interval == 0.0) - printf("Notify Only Once (No Re-notification)"); - else - printf("%s", time_string); - printf("\n"); - - printf("", bg_class); - if(temp_he->escalation_period == NULL) - printf(" "); - else - printf("%s", CONFIG_CGI, url_encode(temp_he->escalation_period), html_encode(temp_he->escalation_period, FALSE)); - printf("\n"); - - printf("", bg_class); - options = FALSE; - if(temp_he->escalate_on_down == TRUE) { - printf("%sDown", (options == TRUE) ? ", " : ""); - options = TRUE; - } - if(temp_he->escalate_on_unreachable == TRUE) { - printf("%sUnreachable", (options == TRUE) ? ", " : ""); - options = TRUE; - } - if(temp_he->escalate_on_recovery == TRUE) { - printf("%sRecovery", (options == TRUE) ? ", " : ""); - options = TRUE; - } - if(options == FALSE) - printf("None"); - printf("\n"); - - printf("\n"); + if(odd) { + odd = 0; + bg_class = "dataOdd"; } + else { + odd = 1; + bg_class = "dataEven"; + } + + printf("\n", bg_class); + + printf("%s", bg_class, CONFIG_CGI, url_encode(temp_he->host_name), html_encode(temp_he->host_name, FALSE)); + + printf("", bg_class); + num_contacts = 0; + for(temp_contactsmember = temp_he->contacts; temp_contactsmember != NULL; temp_contactsmember = temp_contactsmember->next) { + num_contacts++; + if(num_contacts > 1) + printf(", "); + printf("%s\n", CONFIG_CGI, url_encode(temp_contactsmember->contact_name), html_encode(temp_contactsmember->contact_name, FALSE)); + } + for(temp_contactgroupsmember = temp_he->contact_groups; temp_contactgroupsmember != NULL; temp_contactgroupsmember = temp_contactgroupsmember->next) { + num_contacts++; + if(num_contacts > 1) + printf(", "); + printf("%s\n", CONFIG_CGI, url_encode(temp_contactgroupsmember->group_name), html_encode(temp_contactgroupsmember->group_name, FALSE)); + } + if(num_contacts == 0) + printf(" "); + printf("\n"); + + printf("%d", bg_class, temp_he->first_notification); + + printf("", bg_class); + if(temp_he->last_notification == 0) + printf("Infinity"); + else + printf("%d", temp_he->last_notification); + printf("\n"); + + get_interval_time_string(temp_he->notification_interval, time_string, sizeof(time_string)); + printf("", bg_class); + if(temp_he->notification_interval == 0.0) + printf("Notify Only Once (No Re-notification)"); + else + printf("%s", time_string); + printf("\n"); + + printf("", bg_class); + if(temp_he->escalation_period == NULL) + printf(" "); + else + printf("%s", CONFIG_CGI, url_encode(temp_he->escalation_period), html_encode(temp_he->escalation_period, FALSE)); + printf("\n"); + + printf("", bg_class); + options = FALSE; + if(flag_isset(temp_he->escalation_options, OPT_DOWN) == TRUE) { + printf("%sDown", (options == TRUE) ? ", " : ""); + options = TRUE; + } + if(flag_isset(temp_he->escalation_options, OPT_UNREACHABLE) == TRUE) { + printf("%sUnreachable", (options == TRUE) ? ", " : ""); + options = TRUE; + } + if(flag_isset(temp_he->escalation_options, OPT_RECOVERY) == TRUE) { + printf("%sRecovery", (options == TRUE) ? ", " : ""); + options = TRUE; + } + if(options == FALSE) + printf("None"); + printf("\n"); + + printf("\n"); + } printf("\n"); printf("\n"); @@ -2214,9 +2172,7 @@ void unauthorized_message(void) { } - - -char *hash_color(int i) { +static const char *hash_color(int i) { char c; /* This is actually optimized for MAX_COMMAND_ARGUMENTS==32 ... */ @@ -2247,7 +2203,7 @@ char *hash_color(int i) { void display_command_expansion(void) { command *temp_command; int odd = 0; - char *bg_class = ""; + const char *bg_class = ""; int i, j; char *c, *cc; char commandline[MAX_COMMAND_BUFFER]; @@ -2400,7 +2356,7 @@ void display_command_expansion(void) { else if((*c) == '\v') printf("[VT]"); else printf("[0x%x]", *c); printf("", hash_color(i)); - for(; c && ((*c) != '\0') && (j < strlen(command_args[i]) - trail_space[i]); c++, j++) putchar(*c); + for(; c && ((*c) != '\0') && (j < (int)strlen(command_args[i]) - trail_space[i]); c++, j++) putchar(*c); printf(""); for(; c && ((*c) != '\0'); c++) /* TODO: As long as the hyperlinks change all whitespace into actual spaces, diff --git a/cgi/extcmd_list.c b/cgi/extcmd_list.c index 86b0ea3..ba18266 100644 --- a/cgi/extcmd_list.c +++ b/cgi/extcmd_list.c @@ -84,19 +84,8 @@ struct nagios_extcmd in_core_commands[] = { CMD_DEF(DISABLE_HOSTGROUP_HOST_NOTIFICATIONS, 0, NULL), CMD_DEF(ENABLE_HOSTGROUP_SVC_CHECKS, 0, NULL), CMD_DEF(DISABLE_HOSTGROUP_SVC_CHECKS, 0, NULL), - CMD_DEF(CANCEL_HOST_DOWNTIME, 0, NULL), - CMD_DEF(CANCEL_SVC_DOWNTIME, 0, NULL), - CMD_DEF(CANCEL_ACTIVE_HOST_DOWNTIME, 0, NULL), - CMD_DEF(CANCEL_PENDING_HOST_DOWNTIME, 0, NULL), - CMD_DEF(CANCEL_ACTIVE_SVC_DOWNTIME, 0, NULL), - CMD_DEF(CANCEL_PENDING_SVC_DOWNTIME, 0, NULL), - CMD_DEF(CANCEL_ACTIVE_HOST_SVC_DOWNTIME, 0, NULL), - CMD_DEF(CANCEL_PENDING_HOST_SVC_DOWNTIME, 0, NULL), - CMD_DEF(FLUSH_PENDING_COMMANDS, 0, NULL), CMD_DEF(DEL_HOST_DOWNTIME, 0, NULL), CMD_DEF(DEL_SVC_DOWNTIME, 0, NULL), - CMD_DEF(ENABLE_FAILURE_PREDICTION, 0, NULL), - CMD_DEF(DISABLE_FAILURE_PREDICTION, 0, NULL), CMD_DEF(ENABLE_PERFORMANCE_DATA, 0, NULL), CMD_DEF(DISABLE_PERFORMANCE_DATA, 0, NULL), CMD_DEF(SCHEDULE_HOSTGROUP_HOST_DOWNTIME, 0, NULL), @@ -183,7 +172,8 @@ struct nagios_extcmd in_core_commands[] = { CMD_DEF(CHANGE_SVC_MODATTR, 0, NULL), CMD_DEF(CHANGE_CONTACT_MODATTR, 0, NULL), CMD_DEF(CHANGE_CONTACT_MODHATTR, 0, NULL), - CMD_DEF(CHANGE_CONTACT_MODSATTR, 0, NULL), + CMD_DEF(CLEAR_HOST_FLAPPING_STATE, 0, NULL), + CMD_DEF(CLEAR_SVC_FLAPPING_STATE, 0, NULL), }; #undef CMD_DEF @@ -192,7 +182,7 @@ struct nagios_extcmd in_core_commands[] = { #endif const char *extcmd_get_name(int id) { - int i; + unsigned int i; for(i = 0; i < ARRAY_SIZE(in_core_commands); i++) { struct nagios_extcmd *ecmd; diff --git a/cgi/extinfo.c b/cgi/extinfo.c index e2a5fda..dfb09f3 100644 --- a/cgi/extinfo.c +++ b/cgi/extinfo.c @@ -2,8 +2,6 @@ * * EXTINFO.C - Nagios Extended Information CGI * - * Copyright (c) 1999-2009 Ethan Galstad (egalstad@nagios.org) - * Last Modified: 06-17-2009 * * License: * @@ -35,28 +33,10 @@ static nagios_macros *mac; -extern char nagios_check_command[MAX_INPUT_BUFFER]; extern char nagios_process_info[MAX_INPUT_BUFFER]; extern int nagios_process_state; extern int refresh_rate; -extern time_t program_start; -extern int nagios_pid; -extern int daemon_mode; -extern time_t last_command_check; -extern time_t last_log_rotation; -extern int enable_notifications; -extern int execute_service_checks; -extern int accept_passive_service_checks; -extern int execute_host_checks; -extern int accept_passive_host_checks; -extern int enable_event_handlers; -extern int obsess_over_services; -extern int obsess_over_hosts; -extern int enable_flap_detection; -extern int enable_failure_prediction; -extern int process_performance_data; - extern int buffer_stats[1][3]; extern int program_stats[MAX_CHECK_STATS_TYPES][3]; @@ -66,19 +46,15 @@ extern char url_stylesheets_path[MAX_FILENAME_LENGTH]; extern char url_docs_path[MAX_FILENAME_LENGTH]; extern char url_images_path[MAX_FILENAME_LENGTH]; extern char url_logo_images_path[MAX_FILENAME_LENGTH]; -extern char log_file[MAX_FILENAME_LENGTH]; +extern char url_js_path[MAX_FILENAME_LENGTH]; extern int enable_splunk_integration; extern char *notes_url_target; extern char *action_url_target; -extern comment *comment_list; -extern scheduled_downtime *scheduled_downtime_list; extern hoststatus *hoststatus_list; extern servicestatus *servicestatus_list; -extern hostgroup *hostgroup_list; -extern servicegroup *servicegroup_list; #define MAX_MESSAGE_BUFFER 4096 @@ -133,7 +109,6 @@ int display_header = TRUE; int main(void) { - int result = OK; int found = FALSE; char temp_buffer[MAX_INPUT_BUFFER] = ""; char *processed_string = NULL; @@ -151,51 +126,16 @@ int main(void) { /* reset internal variables */ reset_cgi_vars(); - /* read the CGI configuration file */ - result = read_cgi_config_file(get_cgi_config_location()); - if(result == ERROR) { - document_header(FALSE); - cgi_config_file_error(get_cgi_config_location()); - document_footer(); - return ERROR; - } - - /* read the main configuration file */ - result = read_main_config_file(main_config_file); - if(result == ERROR) { - document_header(FALSE); - main_config_file_error(main_config_file); - document_footer(); - return ERROR; - } - - /* read all object configuration data */ - result = read_all_object_configuration_data(main_config_file, READ_ALL_OBJECT_DATA); - if(result == ERROR) { - document_header(FALSE); - object_data_error(); - document_footer(); - return ERROR; - } - - /* read all status data */ - result = read_all_status_data(get_cgi_config_location(), READ_ALL_STATUS_DATA); - if(result == ERROR) { - document_header(FALSE); - status_data_error(); - document_footer(); - free_memory(); - return ERROR; - } + cgi_init(document_header, document_footer, READ_ALL_OBJECT_DATA, READ_ALL_STATUS_DATA); /* initialize macros */ init_macros(); - document_header(TRUE); - /* get authentication information */ get_authentication_information(¤t_authdata); + document_header(TRUE); + if(display_header == TRUE) { @@ -582,6 +522,7 @@ int main(void) { void document_header(int use_stylesheet) { char date_time[MAX_DATETIME_LENGTH]; + char *vidurl = NULL; time_t current_time; time_t expire_time; @@ -597,7 +538,7 @@ void document_header(int use_stylesheet) { get_time_string(&expire_time, date_time, (int)sizeof(date_time), HTTP_DATE_TIME); printf("Expires: %s\r\n", date_time); - printf("Content-type: text/html\r\n\r\n"); + printf("Content-type: text/html; charset=utf-8\r\n\r\n"); if(embedded == TRUE) return; @@ -612,7 +553,30 @@ void document_header(int use_stylesheet) { if(use_stylesheet == TRUE) { printf("", url_stylesheets_path, COMMON_CSS); printf("", url_stylesheets_path, EXTINFO_CSS); + printf("\n", url_stylesheets_path, NAGFUNCS_CSS); } + + if (display_type == DISPLAY_HOST_INFO) + vidurl = "https://www.youtube.com/embed/n3QEAf-MxY4"; + else if(display_type == DISPLAY_SERVICE_INFO) + vidurl = "https://www.youtube.com/embed/f_knwQOS6FI"; + + if (vidurl) { + printf("\n", url_js_path, JQUERY_JS); + printf("\n", url_js_path, NAGFUNCS_JS); + printf("\n"); + } + printf("\n"); printf("\n"); @@ -651,7 +615,6 @@ int process_cgivars(void) { /* do some basic length checking on the variable identifier to prevent buffer overflows */ if(strlen(variables[x]) >= MAX_INPUT_BUFFER - 1) { - x++; continue; } @@ -824,10 +787,6 @@ void show_process_info(void) { sprintf(run_time_string, "%dd %dh %dm %ds", days, hours, minutes, seconds); printf("Total Running Time:%s\n", run_time_string); - /* last external check */ - get_time_string(&last_command_check, date_time, (int)sizeof(date_time), SHORT_DATE_TIME); - printf("Last External Command Check:%s\n", (last_command_check == (time_t)0) ? "N/A" : date_time); - /* last log file rotation */ get_time_string(&last_log_rotation, date_time, (int)sizeof(date_time), SHORT_DATE_TIME); printf("Last Log File Rotation:%s\n", (last_log_rotation == (time_t)0) ? "N/A" : date_time); @@ -862,19 +821,9 @@ void show_process_info(void) { /* flap detection enabled */ printf("Flap Detection Enabled?%s\n", (enable_flap_detection == TRUE) ? "Yes" : "No"); -#ifdef PREDICT_FAILURES - /* failure prediction enabled */ - printf("Failure Prediction Enabled?%s\n", (enable_failure_prediction == TRUE) ? "Yes" : "No"); -#endif - /* process performance data */ printf("Performance Data Being Processed?%s\n", (process_performance_data == TRUE) ? "Yes" : "No"); -#ifdef USE_OLDCRUD - /* daemon mode */ - printf("Running As A Daemon?%s\n", (daemon_mode == TRUE) ? "Yes" : "No"); -#endif - printf("\n"); printf("\n"); printf("\n"); @@ -940,12 +889,6 @@ void show_process_info(void) { else printf("Enable Flap DetectionEnable flap detection\n", url_images_path, ENABLED_ICON, COMMAND_CGI, CMD_ENABLE_FLAP_DETECTION); -#ifdef PREDICT_FAILURES - if(enable_failure_prediction == TRUE) - printf("Disable Failure PredictionDisable failure prediction\n", url_images_path, DISABLED_ICON, COMMAND_CGI, CMD_DISABLE_FAILURE_PREDICTION); - else - printf("Enable Failure PredictionEnable failure prediction\n", url_images_path, ENABLED_ICON, COMMAND_CGI, CMD_ENABLE_FAILURE_PREDICTION); -#endif if(process_performance_data == TRUE) printf("Disable Performance DataDisable performance data\n", url_images_path, DISABLED_ICON, COMMAND_CGI, CMD_DISABLE_PERFORMANCE_DATA); else @@ -955,11 +898,6 @@ void show_process_info(void) { } else { printf("
It appears as though Nagios is not running, so commands are temporarily unavailable...\n"); - if(!strcmp(nagios_check_command, "")) { - printf("

\n"); - printf("Hint: It looks as though you have not defined a command for checking the process state by supplying a value for the nagios_check_command option in the CGI configuration file.
\n"); - printf("Read the documentation for more information on checking the status of the Nagios process in the CGIs.\n"); - } printf("
\n"); } @@ -978,7 +916,7 @@ void show_host_info(void) { char state_duration[48]; char status_age[48]; char state_string[MAX_INPUT_BUFFER]; - char *bg_class = ""; + const char *bg_class = ""; char *buf = NULL; int days; int hours; @@ -1058,15 +996,15 @@ void show_host_info(void) { snprintf(state_duration, sizeof(state_duration) - 1, "%2dd %2dh %2dm %2ds%s", days, hours, minutes, seconds, (temp_hoststatus->last_state_change == (time_t)0) ? "+" : ""); state_duration[sizeof(state_duration) - 1] = '\x0'; - if(temp_hoststatus->status == HOST_UP) { + if(temp_hoststatus->status == SD_HOST_UP) { strcpy(state_string, "UP"); bg_class = "hostUP"; } - else if(temp_hoststatus->status == HOST_DOWN) { + else if(temp_hoststatus->status == SD_HOST_DOWN) { strcpy(state_string, "DOWN"); bg_class = "hostDOWN"; } - else if(temp_hoststatus->status == HOST_UNREACHABLE) { + else if(temp_hoststatus->status == SD_HOST_UNREACHABLE) { strcpy(state_string, "UNREACHABLE"); bg_class = "hostUNREACHABLE"; } @@ -1092,10 +1030,10 @@ void show_host_info(void) { get_time_string(&temp_hoststatus->last_check, date_time, (int)sizeof(date_time), SHORT_DATE_TIME); printf("Last Check Time:%s\n", date_time); - printf("Check Type:%s\n", (temp_hoststatus->check_type == HOST_CHECK_ACTIVE) ? "ACTIVE" : "PASSIVE"); + printf("Check Type:%s\n", (temp_hoststatus->check_type == CHECK_TYPE_ACTIVE) ? "ACTIVE" : "PASSIVE"); printf("Check Latency / Duration:"); - if(temp_hoststatus->check_type == HOST_CHECK_ACTIVE) + if(temp_hoststatus->check_type == CHECK_TYPE_ACTIVE) printf("%.3f", temp_hoststatus->latency); else printf("N/A"); @@ -1152,9 +1090,9 @@ void show_host_info(void) { printf("Active Checks:
  %s  
\n", (temp_hoststatus->checks_enabled == TRUE) ? "ENABLED" : "DISABLED", (temp_hoststatus->checks_enabled == TRUE) ? "ENABLED" : "DISABLED"); - printf("Passive Checks:
  %s  
\n", (temp_hoststatus->accept_passive_host_checks == TRUE) ? "ENABLED" : "DISABLED", (temp_hoststatus->accept_passive_host_checks) ? "ENABLED" : "DISABLED"); + printf("Passive Checks:
  %s  
\n", (temp_hoststatus->accept_passive_checks == TRUE) ? "ENABLED" : "DISABLED", (temp_hoststatus->accept_passive_checks) ? "ENABLED" : "DISABLED"); - printf("Obsessing:
  %s  
\n", (temp_hoststatus->obsess_over_host == TRUE) ? "ENABLED" : "DISABLED", (temp_hoststatus->obsess_over_host) ? "ENABLED" : "DISABLED"); + printf("Obsessing:
  %s  
\n", (temp_hoststatus->obsess == TRUE) ? "ENABLED" : "DISABLED", (temp_hoststatus->obsess) ? "ENABLED" : "DISABLED"); printf("Notifications:
  %s  
\n", (temp_hoststatus->notifications_enabled) ? "ENABLED" : "DISABLED", (temp_hoststatus->notifications_enabled) ? "ENABLED" : "DISABLED"); @@ -1194,19 +1132,19 @@ void show_host_info(void) { printf("Enable Active Checks Of This HostEnable active checks of this host\n", url_images_path, ENABLED_ICON, COMMAND_CGI, CMD_ENABLE_HOST_CHECK, url_encode(host_name)); printf("Re-schedule Next Host CheckRe-schedule the next check of this host\n", url_images_path, DELAY_ICON, COMMAND_CGI, CMD_SCHEDULE_HOST_CHECK, url_encode(host_name), (temp_hoststatus->checks_enabled == TRUE) ? "&force_check" : ""); - if(temp_hoststatus->accept_passive_host_checks == TRUE) { + if(temp_hoststatus->accept_passive_checks == TRUE) { printf("Submit Passive Check Result For This HostSubmit passive check result for this host\n", url_images_path, PASSIVE_ICON, COMMAND_CGI, CMD_PROCESS_HOST_CHECK_RESULT, url_encode(host_name)); printf("Stop Accepting Passive Checks For This HostStop accepting passive checks for this host\n", url_images_path, DISABLED_ICON, COMMAND_CGI, CMD_DISABLE_PASSIVE_HOST_CHECKS, url_encode(host_name)); } else printf("Start Accepting Passive Checks For This HostStart accepting passive checks for this host\n", url_images_path, ENABLED_ICON, COMMAND_CGI, CMD_ENABLE_PASSIVE_HOST_CHECKS, url_encode(host_name)); - if(temp_hoststatus->obsess_over_host == TRUE) + if(temp_hoststatus->obsess == TRUE) printf("Stop Obsessing Over This HostStop obsessing over this host\n", url_images_path, DISABLED_ICON, COMMAND_CGI, CMD_STOP_OBSESSING_OVER_HOST, url_encode(host_name)); else printf("Start Obsessing Over This HostStart obsessing over this host\n", url_images_path, ENABLED_ICON, COMMAND_CGI, CMD_START_OBSESSING_OVER_HOST, url_encode(host_name)); - if(temp_hoststatus->status == HOST_DOWN || temp_hoststatus->status == HOST_UNREACHABLE) { + if(temp_hoststatus->status == SD_HOST_DOWN || temp_hoststatus->status == SD_HOST_UNREACHABLE) { if(temp_hoststatus->problem_has_been_acknowledged == FALSE) printf("Acknowledge This Host ProblemAcknowledge this host problem\n", url_images_path, ACKNOWLEDGEMENT_ICON, COMMAND_CGI, CMD_ACKNOWLEDGE_HOST_PROBLEM, url_encode(host_name)); else @@ -1220,7 +1158,7 @@ void show_host_info(void) { printf("Send Custom NotificationSend custom host notification\n", url_images_path, NOTIFICATION_ICON, COMMAND_CGI, CMD_SEND_CUSTOM_HOST_NOTIFICATION, url_encode(host_name)); - if(temp_hoststatus->status != HOST_UP) + if(temp_hoststatus->status != SD_HOST_UP) printf("Delay Next Host NotificationDelay next host notification\n", url_images_path, DELAY_ICON, COMMAND_CGI, CMD_DELAY_HOST_NOTIFICATION, url_encode(host_name)); printf("Schedule Downtime For This HostSchedule downtime for this host\n", url_images_path, DOWNTIME_ICON, COMMAND_CGI, CMD_SCHEDULE_HOST_DOWNTIME, url_encode(host_name)); @@ -1241,9 +1179,10 @@ void show_host_info(void) { printf("Disable Event Handler For This HostDisable event handler for this host\n", url_images_path, DISABLED_ICON, COMMAND_CGI, CMD_DISABLE_HOST_EVENT_HANDLER, url_encode(host_name)); else printf("Enable Event Handler For This HostEnable event handler for this host\n", url_images_path, ENABLED_ICON, COMMAND_CGI, CMD_ENABLE_HOST_EVENT_HANDLER, url_encode(host_name)); - if(temp_hoststatus->flap_detection_enabled == TRUE) + if(temp_hoststatus->flap_detection_enabled == TRUE) { printf("Disable Flap Detection For This HostDisable flap detection for this host\n", url_images_path, DISABLED_ICON, COMMAND_CGI, CMD_DISABLE_HOST_FLAP_DETECTION, url_encode(host_name)); - else + printf("Clear Flapping State For This HostClear flapping state for this host\n", url_images_path, DISABLED_ICON, COMMAND_CGI, CMD_CLEAR_HOST_FLAPPING_STATE, url_encode(host_name)); + } else printf("Enable Flap Detection For This HostEnable flap detection for this host\n", url_images_path, ENABLED_ICON, COMMAND_CGI, CMD_ENABLE_HOST_FLAP_DETECTION, url_encode(host_name)); printf("\n"); @@ -1266,10 +1205,9 @@ void show_host_info(void) { printf("\n"); - if(is_authorized_for_read_only(¤t_authdata) == FALSE) { - /* display comments */ - display_comments(HOST_COMMENT); - } + /* display comments */ + display_comments(HOST_COMMENT); + printf("\n"); printf("\n"); @@ -1287,7 +1225,7 @@ void show_service_info(void) { char state_duration[48]; servicestatus *temp_svcstatus; char state_string[MAX_INPUT_BUFFER]; - char *bg_class = ""; + const char *bg_class = ""; char *buf = NULL; int days; int hours; @@ -1405,10 +1343,10 @@ void show_service_info(void) { get_time_string(&temp_svcstatus->last_check, date_time, (int)sizeof(date_time), SHORT_DATE_TIME); printf("Last Check Time:%s\n", date_time); - printf("Check Type:%s\n", (temp_svcstatus->check_type == SERVICE_CHECK_ACTIVE) ? "ACTIVE" : "PASSIVE"); + printf("Check Type:%s\n", (temp_svcstatus->check_type == CHECK_TYPE_ACTIVE) ? "ACTIVE" : "PASSIVE"); printf("Check Latency / Duration:"); - if(temp_svcstatus->check_type == SERVICE_CHECK_ACTIVE) + if(temp_svcstatus->check_type == CHECK_TYPE_ACTIVE) printf("%.3f", temp_svcstatus->latency); else printf("N/A"); @@ -1467,9 +1405,9 @@ void show_service_info(void) { printf("Active Checks:
  %s  
\n", (temp_svcstatus->checks_enabled) ? "ENABLED" : "DISABLED", (temp_svcstatus->checks_enabled) ? "ENABLED" : "DISABLED"); - printf("Passive Checks:
  %s  
\n", (temp_svcstatus->accept_passive_service_checks == TRUE) ? "ENABLED" : "DISABLED", (temp_svcstatus->accept_passive_service_checks) ? "ENABLED" : "DISABLED"); + printf("Passive Checks:
  %s  
\n", (temp_svcstatus->accept_passive_checks == TRUE) ? "ENABLED" : "DISABLED", (temp_svcstatus->accept_passive_checks) ? "ENABLED" : "DISABLED"); - printf("Obsessing:
  %s  
\n", (temp_svcstatus->obsess_over_service == TRUE) ? "ENABLED" : "DISABLED", (temp_svcstatus->obsess_over_service) ? "ENABLED" : "DISABLED"); + printf("Obsessing:
  %s  
\n", (temp_svcstatus->obsess == TRUE) ? "ENABLED" : "DISABLED", (temp_svcstatus->obsess) ? "ENABLED" : "DISABLED"); printf("Notifications:
  %s  
\n", (temp_svcstatus->notifications_enabled) ? "ENABLED" : "DISABLED", (temp_svcstatus->notifications_enabled) ? "ENABLED" : "DISABLED"); @@ -1515,7 +1453,7 @@ void show_service_info(void) { printf("Re-schedule Next Service CheckRe-schedule the next check of this service\n", url_encode(service_desc), (temp_svcstatus->checks_enabled == TRUE) ? "&force_check" : ""); - if(temp_svcstatus->accept_passive_service_checks == TRUE) { + if(temp_svcstatus->accept_passive_checks == TRUE) { printf("Submit Passive Check Result For This ServiceSubmit passive check result for this service\n", url_encode(service_desc)); @@ -1527,7 +1465,7 @@ void show_service_info(void) { printf("&service=%s'>Start accepting passive checks for this service\n", url_encode(service_desc)); } - if(temp_svcstatus->obsess_over_service == TRUE) { + if(temp_svcstatus->obsess == TRUE) { printf("Stop Obsessing Over This ServiceStop obsessing over this service\n", url_encode(service_desc)); } @@ -1582,6 +1520,8 @@ void show_service_info(void) { if(temp_svcstatus->flap_detection_enabled == TRUE) { printf("Disable Flap Detection For This ServiceDisable flap detection for this service\n", url_encode(service_desc)); + printf("Clear Flapping State For This ServiceClear flapping state for this service\n", url_encode(service_desc)); } else { printf("Enable Flap Detection For This Service\n"); - if(is_authorized_for_read_only(¤t_authdata) == FALSE) { - /* display comments */ - display_comments(SERVICE_COMMENT); - } + /* display comments */ + display_comments(SERVICE_COMMENT); + printf("\n"); printf("\n"); @@ -1817,22 +1756,15 @@ void show_servicegroup_info() { /* shows all service and host comments */ void show_all_comments(void) { int total_comments = 0; - char *bg_class = ""; + const char *bg_class = ""; int odd = 0; char date_time[MAX_DATETIME_LENGTH]; - comment *temp_comment; + nagios_comment *temp_comment; host *temp_host; service *temp_service; char *comment_type; char expire_time[MAX_DATETIME_LENGTH]; - - if(is_authorized_for_read_only(¤t_authdata) == TRUE) { - printf("
Your account does not have permissions to view comments.
\n"); - return; - } - - printf("
\n"); printf("
\n"); printf("
\n"); @@ -1840,14 +1772,19 @@ void show_all_comments(void) { printf("\n"); printf("
Host Comments
\n"); - printf("\n"); + if(is_authorized_for_read_only(¤t_authdata)==FALSE) { + printf("\n"); + } printf("
\n"); printf("
\n"); printf("\n"); - printf("\n"); + if(is_authorized_for_read_only(¤t_authdata)==FALSE) + printf("\n"); + else + printf("\n"); /* display all the host comments */ for(temp_comment = comment_list, total_comments = 0; temp_comment != NULL; temp_comment = temp_comment->next) { @@ -1894,7 +1831,8 @@ void show_all_comments(void) { printf("", bg_class); printf("", bg_class, EXTINFO_CGI, DISPLAY_HOST_INFO, url_encode(temp_comment->host_name), temp_comment->host_name); printf("", bg_class, date_time, bg_class, temp_comment->author, bg_class, temp_comment->comment_data, bg_class, temp_comment->comment_id, bg_class, (temp_comment->persistent) ? "Yes" : "No", bg_class, comment_type, bg_class, (temp_comment->expires == TRUE) ? expire_time : "N/A"); - printf("", COMMAND_CGI, CMD_DEL_HOST_COMMENT, temp_comment->comment_id, url_images_path, DELETE_ICON); + if(is_authorized_for_read_only(¤t_authdata)==FALSE) + printf("", COMMAND_CGI, CMD_DEL_HOST_COMMENT, temp_comment->comment_id, url_images_path, DELETE_ICON); printf("\n"); } @@ -1910,14 +1848,19 @@ void show_all_comments(void) { printf("\n"); printf("
Service Comments
\n"); - printf("\n"); + if(is_authorized_for_read_only(¤t_authdata)==FALSE){ + printf("\n"); + } printf("
\n"); printf("
\n"); printf("
Host NameEntry TimeAuthorCommentComment IDPersistentTypeExpiresActions
Host NameEntry TimeAuthorCommentComment IDPersistentTypeExpiresActions
Host NameEntry TimeAuthorCommentComment IDPersistentTypeExpires
%s%s%s%s%ld%s%s%sDelete This CommentDelete This Comment
\n"); - printf("\n"); + if(is_authorized_for_read_only(¤t_authdata)==FALSE) + printf("\n"); + else + printf("\n"); /* display all the service comments */ for(temp_comment = comment_list, total_comments = 0; temp_comment != NULL; temp_comment = temp_comment->next) { @@ -1966,7 +1909,8 @@ void show_all_comments(void) { printf("", url_encode(temp_comment->service_description), temp_comment->service_description); printf("", bg_class, date_time, bg_class, temp_comment->author, bg_class, temp_comment->comment_data, bg_class, temp_comment->comment_id, bg_class, (temp_comment->persistent) ? "Yes" : "No", bg_class, comment_type, bg_class, (temp_comment->expires == TRUE) ? expire_time : "N/A"); - printf("", COMMAND_CGI, CMD_DEL_SVC_COMMENT, temp_comment->comment_id, url_images_path, DELETE_ICON); + if(is_authorized_for_read_only(¤t_authdata)==FALSE) + printf("", COMMAND_CGI, CMD_DEL_SVC_COMMENT, temp_comment->comment_id, url_images_path, DELETE_ICON); printf("\n"); } @@ -2070,7 +2014,7 @@ void show_performance_data(void) { continue; /* is this an active or passive check? */ - if(temp_servicestatus->check_type == SERVICE_CHECK_ACTIVE) { + if(temp_servicestatus->check_type == CHECK_TYPE_ACTIVE) { total_active_service_checks++; @@ -2157,7 +2101,7 @@ void show_performance_data(void) { continue; /* is this an active or passive check? */ - if(temp_hoststatus->check_type == HOST_CHECK_ACTIVE) { + if(temp_hoststatus->check_type == CHECK_TYPE_ACTIVE) { total_active_host_checks++; @@ -2498,10 +2442,11 @@ void display_comments(int type) { service *temp_service = NULL; int total_comments = 0; int display_comment = FALSE; - char *bg_class = ""; + const char *bg_class = ""; int odd = 1; char date_time[MAX_DATETIME_LENGTH]; - comment *temp_comment; + nagios_comment *temp_comment; + scheduled_downtime *temp_downtime; char *comment_type; char expire_time[MAX_DATETIME_LENGTH]; @@ -2521,35 +2466,40 @@ void display_comments(int type) { printf("\n"); printf("
%s Comments
\n", (type == HOST_COMMENT) ? "Host" : "Service"); - printf("
Host NameServiceEntry TimeAuthorCommentComment IDPersistentTypeExpiresActions
Host NameServiceEntry TimeAuthorCommentComment IDPersistentTypeExpiresActions
Host NameServiceEntry TimeAuthorCommentComment IDPersistentTypeExpires
%s%s%s%s%ld%s%s%sDelete This CommentDelete This Comment
\n"); - printf("\n"); - printf("\n"); - - printf("\n"); - printf("\n"); - - printf("
", url_images_path, COMMENT_ICON); - if(type == HOST_COMMENT) - printf("", COMMAND_CGI, CMD_ADD_HOST_COMMENT, url_encode(host_name)); - else { - printf("", url_encode(service_desc)); + if(is_authorized_for_read_only(¤t_authdata)==FALSE){ + printf("\n"); + + printf("\n"); + printf("\n"); + + printf("\n"); + printf("\n"); + + printf("
", url_images_path, COMMENT_ICON); + if(type == HOST_COMMENT) + printf("", COMMAND_CGI, CMD_ADD_HOST_COMMENT, url_encode(host_name)); + else { + printf("", url_encode(service_desc)); + } + printf("Add a new comment", url_images_path, DELETE_ICON); + if(type == HOST_COMMENT) + printf("", COMMAND_CGI, CMD_DEL_ALL_HOST_COMMENTS, url_encode(host_name)); + else { + printf("", url_encode(service_desc)); + } + printf("Delete all comments
\n"); } - printf("Add a new comment
", url_images_path, DELETE_ICON); - if(type == HOST_COMMENT) - printf("", COMMAND_CGI, CMD_DEL_ALL_HOST_COMMENTS, url_encode(host_name)); - else { - printf("", url_encode(service_desc)); - } - printf("Delete all comments
\n"); - //printf("
\n"); printf("
\n"); printf("\n"); - printf("\n"); + if(is_authorized_for_read_only(¤t_authdata)==FALSE) + printf("\n"); + else + printf("\n"); /* check all the comments to see if they apply to this host or service */ /* Comments are displayed in the order they are read from the status.dat file */ @@ -2591,14 +2541,31 @@ void display_comments(int type) { comment_type = "?"; } + if (temp_comment->entry_type == DOWNTIME_COMMENT) { + for(temp_downtime = scheduled_downtime_list; temp_downtime != NULL; temp_downtime = temp_downtime->next) { + if (temp_downtime->comment_id == temp_comment->comment_id) + break; + } + } + else + temp_downtime = NULL; + get_time_string(&temp_comment->entry_time, date_time, (int)sizeof(date_time), SHORT_DATE_TIME); get_time_string(&temp_comment->expire_time, expire_time, (int)sizeof(date_time), SHORT_DATE_TIME); printf("", bg_class); - printf("", bg_class, date_time, bg_class, temp_comment->author, bg_class, temp_comment->comment_data, bg_class, temp_comment->comment_id, bg_class, (temp_comment->persistent) ? "Yes" : "No", bg_class, comment_type, bg_class, (temp_comment->expires == TRUE) ? expire_time : "N/A"); - printf("", COMMAND_CGI, (type == HOST_COMMENT) ? CMD_DEL_HOST_COMMENT : CMD_DEL_SVC_COMMENT, temp_comment->comment_id, url_images_path, DELETE_ICON); + printf("", bg_class, date_time, bg_class, temp_comment->author); + printf("", + bg_class, temp_comment->comment_id, bg_class, (temp_comment->persistent) ? "Yes" : "No", + bg_class, comment_type, bg_class, (temp_comment->expires == TRUE) ? expire_time : "N/A"); + if(is_authorized_for_read_only(¤t_authdata)==FALSE) + printf("", COMMAND_CGI, (type == HOST_COMMENT) ? CMD_DEL_HOST_COMMENT : CMD_DEL_SVC_COMMENT, temp_comment->comment_id, url_images_path, DELETE_ICON); printf("\n"); total_comments++; + } } @@ -2617,7 +2584,7 @@ void display_comments(int type) { /* shows all service and host scheduled downtime */ void show_all_downtime(void) { int total_downtime = 0; - char *bg_class = ""; + const char *bg_class = ""; int odd = 0; char date_time[MAX_DATETIME_LENGTH]; scheduled_downtime *temp_downtime; @@ -2781,7 +2748,7 @@ void show_scheduling_queue(void) { char date_time[MAX_DATETIME_LENGTH]; char temp_url[MAX_INPUT_BUFFER]; int odd = 0; - char *bgclass = ""; + const char *bgclass = ""; /* make sure the user has rights to view system information */ @@ -3061,7 +3028,7 @@ int compare_sortdata_entries(int s_type, int s_option, sortdata *new_sortdata, s time_t next_check[2]; int current_attempt[2]; int status[2]; - char *host_name[2]; + char *hname[2]; char *service_description[2]; if(new_sortdata->is_service == TRUE) { @@ -3069,7 +3036,7 @@ int compare_sortdata_entries(int s_type, int s_option, sortdata *new_sortdata, s last_check[0] = temp_svcstatus->last_check; next_check[0] = temp_svcstatus->next_check; status[0] = temp_svcstatus->status; - host_name[0] = temp_svcstatus->host_name; + hname[0] = temp_svcstatus->host_name; service_description[0] = temp_svcstatus->description; current_attempt[0] = temp_svcstatus->current_attempt; } @@ -3078,7 +3045,7 @@ int compare_sortdata_entries(int s_type, int s_option, sortdata *new_sortdata, s last_check[0] = temp_hststatus->last_check; next_check[0] = temp_hststatus->next_check; status[0] = temp_hststatus->status; - host_name[0] = temp_hststatus->host_name; + hname[0] = temp_hststatus->host_name; service_description[0] = ""; current_attempt[0] = temp_hststatus->current_attempt; } @@ -3087,7 +3054,7 @@ int compare_sortdata_entries(int s_type, int s_option, sortdata *new_sortdata, s last_check[1] = temp_svcstatus->last_check; next_check[1] = temp_svcstatus->next_check; status[1] = temp_svcstatus->status; - host_name[1] = temp_svcstatus->host_name; + hname[1] = temp_svcstatus->host_name; service_description[1] = temp_svcstatus->description; current_attempt[1] = temp_svcstatus->current_attempt; } @@ -3096,7 +3063,7 @@ int compare_sortdata_entries(int s_type, int s_option, sortdata *new_sortdata, s last_check[1] = temp_hststatus->last_check; next_check[1] = temp_hststatus->next_check; status[1] = temp_hststatus->status; - host_name[1] = temp_hststatus->host_name; + hname[1] = temp_hststatus->host_name; service_description[1] = ""; current_attempt[1] = temp_hststatus->current_attempt; } @@ -3128,7 +3095,7 @@ int compare_sortdata_entries(int s_type, int s_option, sortdata *new_sortdata, s return FALSE; } else if(s_option == SORT_HOSTNAME) { - if(strcasecmp(host_name[0], host_name[1]) < 0) + if(strcasecmp(hname[0], hname[1]) < 0) return TRUE; else return FALSE; @@ -3166,7 +3133,7 @@ int compare_sortdata_entries(int s_type, int s_option, sortdata *new_sortdata, s return FALSE; } else if(s_option == SORT_HOSTNAME) { - if(strcasecmp(host_name[0], host_name[1]) > 0) + if(strcasecmp(hname[0], hname[1]) > 0) return TRUE; else return FALSE; @@ -3197,4 +3164,3 @@ void free_sortdata_list(void) { return; } - diff --git a/cgi/getcgi.c b/cgi/getcgi.c index 967317e..ce97640 100644 --- a/cgi/getcgi.c +++ b/cgi/getcgi.c @@ -2,7 +2,6 @@ * * GETCGI.C - Nagios CGI Input Routines * - * Last Modified: 05-15-2006 * *****************************************/ @@ -112,7 +111,7 @@ void unescape_cgi_input(char *input) { /* this is a hacked version of a routine I found a long time ago somewhere - can't remember where anymore */ char **getcgivars(void) { register int i; - char *accept_language; + char *accept_lang; char *request_method; char *content_type; char *content_length_string; @@ -123,13 +122,14 @@ char **getcgivars(void) { int paircount; char *nvpair; char *eqpos; + char *cookies, *formid; /* initialize char variable(s) */ cgiinput = ""; /* Attempt to set the locale */ - accept_language = getenv("HTTP_ACCEPT_LANGUAGE"); - process_language(accept_language); + accept_lang = getenv("HTTP_ACCEPT_LANGUAGE"); + process_language(accept_lang); /* depending on the request method, read all CGI input into cgiinput */ @@ -218,7 +218,7 @@ char **getcgivars(void) { /* first, split on ampersands (&) to extract the name-value pairs into pairlist */ /* allocate memory for 256 name-value pairs at a time, increasing by same amount as necessary... */ - pairlist = (char **)malloc(256 * sizeof(char **)); + pairlist = (char **)malloc(256 * sizeof(char *)); if(pairlist == NULL) { printf("getcgivars(): Could not allocate memory for name-value pairlist.\n"); exit(1); @@ -227,13 +227,13 @@ char **getcgivars(void) { nvpair = strtok(cgiinput, "&"); while(nvpair) { pairlist[paircount] = strdup(nvpair); - if(NULL == pairlist[paircount]) { + if( NULL == pairlist[paircount]) { printf("getcgivars(): Could not allocate memory for name-value pair #%d.\n", paircount); exit(1); } paircount++; if(!(paircount % 256)) { - pairlist = (char **)realloc(pairlist, (paircount + 256) * sizeof(char **)); + pairlist = (char **)realloc(pairlist, (paircount + 256) * sizeof(char *)); if(pairlist == NULL) { printf("getcgivars(): Could not re-allocate memory for name-value pairlist.\n"); exit(1); @@ -242,11 +242,43 @@ char **getcgivars(void) { nvpair = strtok(NULL, "&"); } + /* See if there is a NagFormId cookie & get it if it's available */ + + cookies = getenv("HTTP_COOKIE"); + if (cookies && *cookies) { + formid = strstr(cookies, "NagFormId="); + if (formid) { + if(!(paircount % 256)) { + pairlist = (char **)realloc(pairlist, (paircount + 1) * sizeof(char *)); + if(pairlist == NULL) { + printf("getcgivars(): Could not re-allocate memory for name-value pairlist.\n"); + exit(1); + } + } + + formid = strtok(formid, ";"); + if (strlen(formid) > 10 && strlen(formid) < 21) { + for (i = strlen(formid) - 1; i > 9; --i) + if (!isxdigit(formid[i])) + break; + if (i == 9) { + pairlist[paircount] = strdup(formid); + + if (!pairlist[paircount]) { + printf("getcgivars(): Could not allocate memory for name-value pair #%d.\n", paircount); + exit(1); + } + paircount++; + } + } + } + } + /* terminate the list */ pairlist[paircount] = '\x0'; /* extract the names and values from the pairlist */ - cgivars = (char **)malloc((paircount * 2 + 1) * sizeof(char **)); + cgivars = (char **)malloc((paircount * 2 + 1) * sizeof(char *)); if(cgivars == NULL) { printf("getcgivars(): Could not allocate memory for name-value list.\n"); exit(1); @@ -257,7 +289,7 @@ char **getcgivars(void) { if((eqpos = strchr(pairlist[i], '=')) != NULL) { *eqpos = '\0'; cgivars[i * 2 + 1] = strdup(eqpos + 1); - if(NULL == cgivars[ i * 2 + 1]) { + if( NULL == cgivars[ i * 2 + 1]) { printf("getcgivars(): Could not allocate memory for cgi value #%d.\n", i); exit(1); } @@ -265,7 +297,7 @@ char **getcgivars(void) { } else { cgivars[i * 2 + 1] = strdup(""); - if(NULL == cgivars[ i * 2 + 1]) { + if( NULL == cgivars[ i * 2 + 1]) { printf("getcgivars(): Could not allocate memory for empty stringfor variable value #%d.\n", i); exit(1); } @@ -274,7 +306,7 @@ char **getcgivars(void) { /* get the variable value (or name/value of there was no real "pair" in the first place) */ cgivars[i * 2] = strdup(pairlist[i]); - if(NULL == cgivars[ i * 2]) { + if( NULL == cgivars[ i * 2]) { printf("getcgivars(): Could not allocate memory for cgi name #%d.\n", i); exit(1); } @@ -299,43 +331,45 @@ char **getcgivars(void) { /* Set the locale based on the HTTP_ACCEPT_LANGUAGE variable value sent by the browser */ -void process_language(char * accept_language) { +void process_language( char * accept_lang) { accept_languages *accept_langs = NULL; int x; char locale_string[ 64]; char * locale = NULL; char * locale_failsafe[] = { "en_US.utf8", "POSIX", "C" }; - if(accept_language != NULL) { - accept_langs = parse_accept_languages(accept_language); - } - - if(NULL != accept_langs) { - /* Sort the results */ - qsort(accept_langs->languages, accept_langs->count, - sizeof(accept_langs->languages[ 0]), compare_accept_languages); - - /* Try each language in order of priority */ - for(x = 0; ((x < accept_langs->count) && (NULL == locale)); x++) { - snprintf(locale_string, sizeof(locale_string), "%s_%s.%s", - accept_langs->languages[ x]->language, - accept_langs->languages[ x]->locality, "utf8"); - locale = setlocale(LC_CTYPE, locale_string); - if(NULL != locale) break; - } - - free_accept_languages(accept_langs); - } - if(NULL == locale) { /* Still isn't set */ - /* Try the fail safe locales */ - for(x = 0; ((x < (sizeof(locale_failsafe) / sizeof(char *))) && - (NULL == locale)); x++) { - locale = setlocale(LC_CTYPE, locale_failsafe[ x]); - } - } + if( accept_lang != NULL) { + accept_langs = parse_accept_languages( accept_lang); } -accept_languages * parse_accept_languages(char * acceptlang) { + if( NULL != accept_langs) { + /* Sort the results */ + qsort( accept_langs->languages, accept_langs->count, + sizeof( accept_langs->languages[ 0]), compare_accept_languages); + + /* Try each language in order of priority */ + for( x = 0; (( x < accept_langs->count) && ( NULL == locale)); x++) { + accept_language *l; + l = accept_langs->languages[x]; + if (!l || !l->locality || !l->language) + continue; + snprintf( locale_string, sizeof( locale_string), "%s_%s.%s", + l->language, l->locality, "utf8"); + locale = setlocale( LC_ALL, locale_string); + } + + free_accept_languages( accept_langs); + } + if( NULL == locale) { /* Still isn't set */ + /* Try the fail safe locales */ + for( x = 0; (( x < (int)( sizeof( locale_failsafe) / sizeof( char *))) && + ( NULL == locale)); x++) { + locale = setlocale( LC_ALL, locale_failsafe[ x]); + } + } +} + +accept_languages * parse_accept_languages( char * acceptlang) { char * langdup; /* Duplicate of accept language for parsing */ accept_languages *langs = NULL; char * langtok; /* Language token (language + locality + q value) */ @@ -347,164 +381,164 @@ accept_languages * parse_accept_languages(char * acceptlang) { /* If the browser did not pass an HTTP_ACCEPT_LANGUAGE variable, there is not much we can do */ - if(NULL == acceptlang) { + if( NULL == acceptlang) { return NULL; - } + } /* Duplicate the browser supplied HTTP_ACCEPT_LANGUAGE variable */ - if(NULL == (langdup = strdup(acceptlang))) { - printf("Unable to allocate memory for langdup\n"); + if( NULL == ( langdup = strdup( acceptlang))) { + printf( "Unable to allocate memory for langdup\n"); return NULL; - } + } /* Initialize the structure to contain the parsed HTTP_ACCEPT_LANGUAGE information */ - if(NULL == (langs = malloc(sizeof(accept_languages)))) { - printf("Unable to allocate memory for langs\n"); - free(langdup); + if( NULL == ( langs = malloc( sizeof( accept_languages)))) { + printf( "Unable to allocate memory for langs\n"); + free( langdup); return NULL; - } + } langs->count = 0; - langs->languages = (accept_language **)NULL; + langs->languages = ( accept_language **)NULL; /* Tokenize the HTTP_ACCEPT_LANGUAGE string */ - langtok = strtok_r(langdup, ",", &saveptr); - while(langtok != NULL) { + langtok = strtok_r( langdup, ",", &saveptr); + while( langtok != NULL) { /* Bump the count and allocate memory for structures */ langs->count++; - if(NULL == langs->languages) { + if( NULL == langs->languages) { /* Adding first language */ - if(NULL == (langs->languages = - malloc(langs->count * sizeof(accept_language *)))) { - printf("Unable to allocate memory for first language\n"); + if( NULL == ( langs->languages = + malloc( langs->count * sizeof( accept_language *)))) { + printf( "Unable to allocate memory for first language\n"); langs->count--; - free_accept_languages(langs); - free(langdup); + free_accept_languages( langs); + free( langdup); return NULL; - } } + } else { /* Adding additional language */ - if(NULL == (langs->languages = realloc(langs->languages, - langs->count * sizeof(accept_language *)))) { - printf("Unable to allocate memory for additional language\n"); + if( NULL == ( langs->languages = realloc( langs->languages, + langs->count * sizeof( accept_language *)))) { + printf( "Unable to allocate memory for additional language\n"); langs->count--; - free_accept_languages(langs); - free(langdup); + free_accept_languages( langs); + free( langdup); return NULL; - } } - if(NULL == (langs->languages[ langs->count - 1] = - malloc(sizeof(accept_language)))) { - printf("Unable to allocate memory for language\n"); + } + if( NULL == ( langs->languages[ langs->count - 1] = + malloc( sizeof( accept_language)))) { + printf( "Unable to allocate memory for language\n"); langs->count--; - free_accept_languages(langs); - free(langdup); + free_accept_languages( langs); + free( langdup); return NULL; - } - langs->languages[ langs->count - 1]->language = (char *)NULL; - langs->languages[ langs->count - 1]->locality = (char *)NULL; + } + langs->languages[ langs->count - 1]->language = ( char *)NULL; + langs->languages[ langs->count - 1]->locality = ( char *)NULL; langs->languages[ langs->count - 1]->q = 1.0; /* Check to see if there is a q value */ - qdelim = strstr(langtok, ACCEPT_LANGUAGE_Q_DELIMITER); + qdelim = strstr( langtok, ACCEPT_LANGUAGE_Q_DELIMITER); - if(NULL != qdelim) { /* found a q value */ + if( NULL != qdelim) { /* found a q value */ langs->languages[ langs->count - 1]->q = - strtod(qdelim + strlen(ACCEPT_LANGUAGE_Q_DELIMITER), NULL); + strtod( qdelim + strlen( ACCEPT_LANGUAGE_Q_DELIMITER), NULL); langtok[ qdelim - langtok] = '\0'; - } + } /* Check to see if there is a locality specifier */ - if(NULL == (localitydelim = strchr(langtok, '-'))) { - localitydelim = strchr(langtok, '_'); + if( NULL == ( localitydelim = strchr( langtok, '-'))) { + localitydelim = strchr( langtok, '_'); + } + + if( NULL != localitydelim) { + /* We have a locality delimiter, so copy it */ + if( NULL == ( langs->languages[ langs->count - 1]->locality = + strdup( localitydelim + 1))) { + printf( "Unable to allocate memory for locality '%s'\n", + langtok); + free_accept_languages( langs); + free( langdup); + return NULL; } - if(NULL != localitydelim) { - /* We have a locality delimiter, so copy it */ - if(NULL == (langs->languages[ langs->count - 1]->locality = - strdup(localitydelim + 1))) { - printf("Unable to allocate memory for locality '%s'\n", - langtok); - free_accept_languages(langs); - free(langdup); - return NULL; - } - /* Ensure it is upper case */ - for(x = 0, stp = langs->languages[ langs->count - 1]->locality; - x < strlen(langs->languages[ langs->count - 1]->locality); - x++, stp++) { - *stp = toupper(*stp); - } + for( x = 0, stp = langs->languages[ langs->count - 1]->locality; + x < (int)strlen( langs->languages[ langs->count - 1]->locality); + x++, stp++) { + *stp = toupper( *stp); + } /* Then null out the delimiter so the language copy works */ *localitydelim = '\0'; - } - if(NULL == (langs->languages[ langs->count - 1]->language = - strdup(langtok))) { - printf("Unable to allocate memory for language '%s'\n", - langtok); - free_accept_languages(langs); - free(langdup); + } + if( NULL == ( langs->languages[ langs->count - 1]->language = + strdup( langtok))) { + printf( "Unable to allocate memory for language '%s'\n", + langtok); + free_accept_languages( langs); + free( langdup); return NULL; - } + } /* Get the next language token */ - langtok = strtok_r(NULL, ",", &saveptr); - } - - free(langdup); - return langs; + langtok = strtok_r( NULL, ",", &saveptr); } -int compare_accept_languages(const void *p1, const void *p2) { - accept_language * lang1 = *(accept_language **)p1; - accept_language * lang2 = *(accept_language **)p2; + free( langdup); + return langs; +} - if(lang1->q == lang2->q) { - if(((NULL == lang1->locality) && (NULL == lang2->locality)) || - ((NULL != lang1->locality) && (NULL != lang2->locality))) { +int compare_accept_languages( const void *p1, const void *p2) { + accept_language * lang1 = *( accept_language **)p1; + accept_language * lang2 = *( accept_language **)p2; + + if( lang1->q == lang2->q) { + if((( NULL == lang1->locality) && ( NULL == lang2->locality)) || + (( NULL != lang1->locality) && ( NULL != lang2->locality))) { return 0; - } - else if(NULL != lang1->locality) { + } + else if( NULL != lang1->locality) { return -1; - } + } else { /* NULL != lang2->locality */ return 1; - } - } - else { - return(lang2->q > lang1->q); } } + else { + return( lang2->q > lang1->q); + } +} -void free_accept_languages(accept_languages * langs) { +void free_accept_languages( accept_languages * langs) { int x; - if(NULL == langs) { + if( NULL == langs) { return; - } + } - for(x = 0; x < langs->count; x++) { - if(NULL != langs->languages[ x]) { - if(langs->languages[ x]->language != NULL) { - free(langs->languages[ x]->language); - } - if(langs->languages[ x]->locality != NULL) { - free(langs->languages[ x]->locality); - } - free(langs->languages[ x]); + for( x = 0; x < langs->count; x++) { + if( NULL != langs->languages[ x]) { + if( langs->languages[ x]->language != NULL) { + free( langs->languages[ x]->language); } + if( langs->languages[ x]->locality != NULL) { + free( langs->languages[ x]->locality); + } + free( langs->languages[ x]); } - if(langs->languages != NULL) { - free(langs->languages); - } - free(langs); + } + if( langs->languages != NULL) { + free( langs->languages); + } + free( langs); return; - } +} /* free() memory allocated to storing the CGI variables */ void free_cgivars(char **cgivars) { diff --git a/cgi/histogram.c b/cgi/histogram.c index 1095314..736dfae 100644 --- a/cgi/histogram.c +++ b/cgi/histogram.c @@ -2,8 +2,6 @@ * * HISTOGRAM.C - Nagios Alert Histogram CGI * - * Copyright (c) 2001-2008 Ethan Galstad (egalstad@nagios.org) - * Last Modified: 10-15-2008 * * License: * @@ -129,13 +127,7 @@ extern char url_html_path[MAX_FILENAME_LENGTH]; extern char url_images_path[MAX_FILENAME_LENGTH]; extern char url_stylesheets_path[MAX_FILENAME_LENGTH]; extern char physical_images_path[MAX_FILENAME_LENGTH]; - -extern int log_rotation_method; - -extern host *host_list; -extern service *service_list; - - +extern char *status_file; authdata current_authdata; @@ -257,6 +249,9 @@ int main(int argc, char **argv) { /* reset internal CGI variables */ reset_cgi_vars(); + /* Initialize shared configuration variables */ + init_shared_cfg_vars(1); + /* read the CGI configuration file */ result = read_cgi_config_file(get_cgi_config_location()); if(result == ERROR) { @@ -291,7 +286,7 @@ int main(int argc, char **argv) { } /* read all status data */ - result = read_all_status_data(get_cgi_config_location(), READ_ALL_STATUS_DATA); + result = read_all_status_data(status_file, READ_ALL_STATUS_DATA); if(result == ERROR) { if(mode == CREATE_HTML) { document_header(FALSE); @@ -400,7 +395,11 @@ int main(int argc, char **argv) { /* right hand column of top row */ printf("
Entry TimeAuthorCommentComment IDPersistentTypeExpiresActions
Entry TimeAuthorCommentComment IDPersistentTypeExpiresActions
Entry TimeAuthorCommentComment IDPersistentTypeExpires
%s%s%s%lu%s%s%sDelete This Comment%s%s%s", bg_class, temp_comment->comment_data); + if (temp_downtime) + printf("
%s", temp_downtime->comment); + printf("
%lu%s%s%sDelete This Comment
\n"); +#ifdef LEGACY_GRAPHICAL_CGIS printf("\n", HISTOGRAM_CGI); +#else + printf("\n", LEGACY_HISTOGRAM_CGI); +#endif printf("\n"); if(display_type != DISPLAY_NO_HISTOGRAM && input_type == GET_INPUT_NONE) { @@ -548,7 +547,11 @@ int main(int argc, char **argv) { printf("

\n"); printf("
\n"); +#ifdef LEGACY_GRAPHICAL_CGIS printf("
\n"); +#ifdef LEGACY_GRAPHICAL_CGIS printf("\n", HISTOGRAM_CGI); +#else + printf("\n", LEGACY_HISTOGRAM_CGI); +#endif printf("\n"); printf("
\n"); @@ -742,7 +749,11 @@ int main(int argc, char **argv) { printf("

\n"); +#ifdef LEGACY_GRAPHICAL_CGIS printf("\n", HISTOGRAM_CGI); +#else + printf("\n", LEGACY_HISTOGRAM_CGI); +#endif printf("\n"); printf("\n", (first_service == NULL) ? "unknown" : (char *)escape_string(first_service)); @@ -786,7 +797,11 @@ int main(int argc, char **argv) { printf("

\n"); +#ifdef LEGACY_GRAPHICAL_CGIS printf("\n", HISTOGRAM_CGI); +#else + printf("\n", LEGACY_HISTOGRAM_CGI); +#endif printf("\n", escape_string(host_name)); if(display_type == DISPLAY_SERVICE_HISTOGRAM) printf("\n", escape_string(svc_description)); @@ -944,7 +959,11 @@ int main(int argc, char **argv) { printf("

\n"); +#ifdef LEGACY_GRAPHICAL_CGIS printf("\n", HISTOGRAM_CGI); +#else + printf("\n", LEGACY_HISTOGRAM_CGI); +#endif printf("
\n"); printf("\n"); printf("\n"); printf("\n"); @@ -303,7 +274,7 @@ void document_header(int use_stylesheet) { get_time_string(&expire_time, date_time, (int)sizeof(date_time), HTTP_DATE_TIME); printf("Expires: %s\r\n", date_time); - printf("Content-type: text/html\r\n\r\n"); + printf("Content-type: text/html; charset=utf-8\r\n\r\n"); if(embedded == TRUE) return; @@ -358,7 +329,6 @@ int process_cgivars(void) { /* do some basic length checking on the variable identifier to prevent buffer overflows */ if(strlen(variables[x]) >= MAX_INPUT_BUFFER - 1) { - x++; continue; } @@ -619,6 +589,10 @@ void display_notifications(void) { notification_detail_type = NOTIFICATION_SERVICE_FLAP; strcpy(alert_level_class, "UNKNOWN"); } + else if(strstr(alert_level, "DOWNTIME")) { + notification_detail_type = NOTIFICATION_SERVICE_DOWNTIME; + strcpy(alert_level_class, "DOWNTIME"); + } else { strcpy(alert_level, "UNKNOWN"); notification_detail_type = NOTIFICATION_SERVICE_UNKNOWN; @@ -661,6 +635,10 @@ void display_notifications(void) { strcpy(alert_level_class, "UNKNOWN"); notification_detail_type = NOTIFICATION_HOST_FLAP; } + else if(strstr(alert_level, "DOWNTIME")) { + strcpy(alert_level_class, "DOWNTIME"); + notification_detail_type = NOTIFICATION_HOST_DOWNTIME; + } } /* get the method name */ diff --git a/cgi/objectjson.c b/cgi/objectjson.c new file mode 100644 index 0000000..86ead5d --- /dev/null +++ b/cgi/objectjson.c @@ -0,0 +1,6027 @@ +/************************************************************************** + * + * OBJECTJSON.C - Nagios CGI for returning JSON-formatted object data + * + * Copyright (c) 2013 Nagios Enterprises, LLC + * Last Modified: 04-13-2013 + * + * License: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + *************************************************************************/ + +/* + TODO: + Add code to display customvariables + Add sort criteria for *list queries + Add core3 flag for backward compatible display of flags that were + combined into a single variable in core4 + Implement internationalized day of week, month names, and formats + for timeperiod details + Implement raw numbers for day of week, month for timeperiod details +*/ + +#include "../include/config.h" +#include "../include/common.h" +#include "../include/objects.h" +#include "../include/statusdata.h" + +#include "../include/cgiutils.h" +#include "../include/getcgi.h" +#include "../include/cgiauth.h" +#include "../include/jsonutils.h" +#include "../include/objectjson.h" + +#define THISCGI "objectjson.cgi" + +extern char main_config_file[MAX_FILENAME_LENGTH]; +extern char *status_file; + +extern host *host_list; +extern hostgroup *hostgroup_list; +extern service *service_list; +extern servicegroup *servicegroup_list; +extern contact *contact_list; +extern contactgroup *contactgroup_list; +extern timeperiod *timeperiod_list; +extern command *command_list; +extern servicedependency *servicedependency_list; +extern serviceescalation *serviceescalation_list; +extern hostdependency *hostdependency_list; +extern hostescalation *hostescalation_list; + +void document_header(int); +void document_footer(void); +void init_cgi_data(object_json_cgi_data *); +int process_cgivars(json_object *, object_json_cgi_data *, time_t); +void free_cgi_data(object_json_cgi_data *); +int validate_arguments(json_object *, object_json_cgi_data *, time_t); + +authdata current_authdata; + +const string_value_mapping valid_queries[] = { + { "hostcount", OBJECT_QUERY_HOSTCOUNT, + "Return the number of hosts" }, + { "hostlist", OBJECT_QUERY_HOSTLIST, + "Return a list of hosts" }, + { "host", OBJECT_QUERY_HOST, + "Return the configuration for a single host" }, + { "hostgroupcount", OBJECT_QUERY_HOSTGROUPCOUNT, + "Return the number of host groups" }, + { "hostgrouplist", OBJECT_QUERY_HOSTGROUPLIST, + "Return a list of host groups" }, + { "hostgroup", OBJECT_QUERY_HOSTGROUP, + "Return the configuration for a single hostgroup" }, + { "servicecount", OBJECT_QUERY_SERVICECOUNT, + "Return a list of services" }, + { "servicelist", OBJECT_QUERY_SERVICELIST, + "Return a list of services" }, + { "service", OBJECT_QUERY_SERVICE, + "Return the configuration for a single service" }, + { "servicegroupcount", OBJECT_QUERY_SERVICEGROUPCOUNT, + "Return the number of service groups" }, + { "servicegrouplist", OBJECT_QUERY_SERVICEGROUPLIST, + "Return a list of service groups" }, + { "servicegroup", OBJECT_QUERY_SERVICEGROUP, + "Return the configuration for a single servicegroup" }, + { "contactcount", OBJECT_QUERY_CONTACTCOUNT, + "Return the number of contacts" }, + { "contactlist", OBJECT_QUERY_CONTACTLIST, + "Return a list of contacts" }, + { "contact", OBJECT_QUERY_CONTACT, + "Return the configuration for a single contact" }, + { "contactgroupcount", OBJECT_QUERY_CONTACTGROUPCOUNT, + "Return the number of contact groups" }, + { "contactgrouplist", OBJECT_QUERY_CONTACTGROUPLIST, + "Return a list of contact groups" }, + { "contactgroup", OBJECT_QUERY_CONTACTGROUP, + "Return the configuration for a single contactgroup" }, + { "timeperiodcount", OBJECT_QUERY_TIMEPERIODCOUNT, + "Return the number of time periods" }, + { "timeperiodlist", OBJECT_QUERY_TIMEPERIODLIST, + "Return a list of time periods" }, + { "timeperiod", OBJECT_QUERY_TIMEPERIOD, + "Return the configuration for a single timeperiod" }, + { "commandcount", OBJECT_QUERY_COMMANDCOUNT, + "Return the number of commands" }, + { "commandlist", OBJECT_QUERY_COMMANDLIST, + "Return a list of commands" }, + { "command", OBJECT_QUERY_COMMAND, + "Return the configuration for a single command" }, + { "servicedependencycount", OBJECT_QUERY_SERVICEDEPENDENCYCOUNT, + "Return the number of service dependencies" }, + { "servicedependencylist", OBJECT_QUERY_SERVICEDEPENDENCYLIST, + "Return a list of service dependencies" }, + { "serviceescalationcount", OBJECT_QUERY_SERVICEESCALATIONCOUNT, + "Return the number of service escalations" }, + { "serviceescalationlist", OBJECT_QUERY_SERVICEESCALATIONLIST, + "Return a list of service escalations" }, + { "hostdependencycount", OBJECT_QUERY_HOSTDEPENDENCYCOUNT, + "Return the number of host dependencies" }, + { "hostdependencylist", OBJECT_QUERY_HOSTDEPENDENCYLIST, + "Return a list of host dependencies" }, + { "hostescalationcount", OBJECT_QUERY_HOSTESCALATIONCOUNT, + "Return the number of host escalations" }, + { "hostescalationlist", OBJECT_QUERY_HOSTESCALATIONLIST, + "Return a list of host escalations" }, + { "help", OBJECT_QUERY_HELP, + "Display help for this CGI" }, + { NULL, -1, NULL }, + }; + +static const int query_status[][2] = { + { OBJECT_QUERY_HOSTCOUNT, QUERY_STATUS_RELEASED }, + { OBJECT_QUERY_HOSTLIST, QUERY_STATUS_RELEASED }, + { OBJECT_QUERY_HOST, QUERY_STATUS_RELEASED }, + { OBJECT_QUERY_HOSTGROUPCOUNT, QUERY_STATUS_RELEASED }, + { OBJECT_QUERY_HOSTGROUPLIST, QUERY_STATUS_RELEASED }, + { OBJECT_QUERY_HOSTGROUP, QUERY_STATUS_RELEASED }, + { OBJECT_QUERY_SERVICECOUNT, QUERY_STATUS_RELEASED }, + { OBJECT_QUERY_SERVICELIST, QUERY_STATUS_RELEASED }, + { OBJECT_QUERY_SERVICE, QUERY_STATUS_RELEASED }, + { OBJECT_QUERY_SERVICEGROUPCOUNT, QUERY_STATUS_RELEASED }, + { OBJECT_QUERY_SERVICEGROUPLIST, QUERY_STATUS_RELEASED }, + { OBJECT_QUERY_SERVICEGROUP, QUERY_STATUS_RELEASED }, + { OBJECT_QUERY_CONTACTCOUNT, QUERY_STATUS_RELEASED }, + { OBJECT_QUERY_CONTACTLIST, QUERY_STATUS_RELEASED }, + { OBJECT_QUERY_CONTACT, QUERY_STATUS_RELEASED }, + { OBJECT_QUERY_CONTACTGROUPCOUNT, QUERY_STATUS_RELEASED }, + { OBJECT_QUERY_CONTACTGROUPLIST, QUERY_STATUS_RELEASED }, + { OBJECT_QUERY_CONTACTGROUP, QUERY_STATUS_RELEASED }, + { OBJECT_QUERY_TIMEPERIODCOUNT, QUERY_STATUS_RELEASED }, + { OBJECT_QUERY_TIMEPERIODLIST, QUERY_STATUS_RELEASED }, + { OBJECT_QUERY_TIMEPERIOD, QUERY_STATUS_RELEASED }, + { OBJECT_QUERY_COMMANDCOUNT, QUERY_STATUS_RELEASED }, + { OBJECT_QUERY_COMMANDLIST, QUERY_STATUS_RELEASED }, + { OBJECT_QUERY_COMMAND, QUERY_STATUS_RELEASED }, + { OBJECT_QUERY_SERVICEDEPENDENCYCOUNT, QUERY_STATUS_RELEASED }, + { OBJECT_QUERY_SERVICEDEPENDENCYLIST, QUERY_STATUS_RELEASED }, + { OBJECT_QUERY_SERVICEESCALATIONCOUNT, QUERY_STATUS_RELEASED }, + { OBJECT_QUERY_SERVICEESCALATIONLIST, QUERY_STATUS_RELEASED }, + { OBJECT_QUERY_HOSTDEPENDENCYCOUNT, QUERY_STATUS_RELEASED }, + { OBJECT_QUERY_HOSTDEPENDENCYLIST, QUERY_STATUS_RELEASED }, + { OBJECT_QUERY_HOSTESCALATIONCOUNT, QUERY_STATUS_RELEASED }, + { OBJECT_QUERY_HOSTESCALATIONLIST, QUERY_STATUS_RELEASED }, + { OBJECT_QUERY_HELP, QUERY_STATUS_RELEASED }, + { -1, -1 }, +}; + +option_help object_json_help[] = { + { + "query", + "Query", + "enumeration", + { "all", NULL }, + { NULL }, + NULL, + "Specifies the type of query to be executed.", + valid_queries + }, + { + "formatoptions", + "Format Options", + "list", + { NULL }, + { "all", NULL }, + NULL, + "Specifies the formatting options to be used when displaying the results. Multiple options are allowed and are separated by a plus (+) sign..", + svm_format_options + }, + { + "start", + "Start", + "integer", + { NULL }, + { "hostlist", "hostgrouplist", "servicelist", "servicegrouplist", "contactlist", "contactgrouplist", "timeperiodlist", "commandlist", "servicedependencylist", "serviceescalationlist", "hostdependencylist", "hostescalationlist", NULL }, + NULL, + "Specifies the index (zero-based) of the first object in the list to be returned.", + NULL + }, + { + "count", + "Count", + "integer", + { NULL }, + { "hostlist", "hostgrouplist", "servicelist", "servicegrouplist", "contactlist", "contactgrouplist", "timeperiodlist", "commandlist", "servicedependencylist", "serviceescalationlist", "hostdependencylist", "hostescalationlist", NULL }, + NULL, + "Specifies the number of objects in the list to be returned.", + NULL + }, + { + "dateformat", + "Date Format", + "string", + { NULL }, + { "all", NULL }, + NULL, + "strftime format string for values of type time_t. In the absence of a format, the Javascript default format of the number of milliseconds since the beginning of the Unix epoch is used. Because of URL encoding, percent signs must be encoded as %25 and a space must be encoded as a plus (+) sign.", + NULL + }, + { + "parenthost", + "Parent Host", + "nagios:objectjson/hostlist", + { NULL }, + { "hostcount", "hostlist", "servicecount", "servicelist", NULL }, + NULL, + "Limits the hosts or services returned to those whose host parent is specified. A value of 'none' returns all hosts or services reachable directly by the Nagios core host.", + parent_host_extras + }, + { + "childhost", + "Child Host", + "nagios:objectjson/hostlist", + { NULL }, + { "hostcount", "hostlist", "servicecount", "servicelist", NULL }, + NULL, + "Limits the hosts or services returned to those whose having the host specified as a child host. A value of 'none' returns all hosts or services with no child hosts.", + child_host_extras + }, + { + "details", + "Show Details", + "boolean", + { NULL }, + { "hostlist", "hostgrouplist", "servicelist", "servicegrouplist", "contactlist", "contactgrouplist", "timeperiodlist", "commandlist", NULL }, + NULL, + "If true, return the details for all entities in the list.", + NULL + }, + { + "hostname", + "Host Name", + "nagios:objectjson/hostlist", + { "host", "service", NULL }, + { "servicecount", "servicelist", "hostescalationlist", "serviceescalationlist", NULL }, + NULL, + "Name for the host requested.", + NULL + }, + { + "hostgroupmember", + "Host Group Member", + "nagios:objectjson/hostlist", + { NULL }, + { "hostgroupcount", "hostgrouplist", NULL }, + NULL, + "Limits the hostgroups returned to those containing the hostgroupmember.", + NULL + }, + { + "hostgroup", + "Host Group", + "nagios:objectjson/hostgrouplist", + { "hostgroup", NULL }, + { "hostcount", "hostlist", "servicecount", "servicelist", "hostescalationcount", "hostescalationlist", "serviceescalationcount", "serviceescalationlist", NULL }, + NULL, + "Returns information applicable to the hostgroup or the hosts in the hostgroup depending on the query.", + NULL + }, + { + "servicegroup", + "Service Group", + "nagios:objectjson/servicegrouplist", + { "servicegroup", NULL }, + { "servicecount", "servicelist", "serviceescalationcount", "serviceescalationlist", NULL }, + NULL, + "Returns information applicable to the servicegroup or the services in the servicegroup depending on the query.", + NULL + }, + { + "parentservice", + "Parent Service", + "nagios:objectjson/servicelist", + { NULL }, + { "servicecount", "servicelist", NULL }, + NULL, + "Limits the services returned to those whose service parent has the name specified. A value of 'none' returns all services with no service parent.", + parent_service_extras + }, + { + "childservice", + "Child Service", + "nagios:objectjson/servicelist", + { NULL }, + { "servicecount", "servicelist", NULL }, + NULL, + "Limits the services returned to those whose having the named service as a child service. A value of 'none' returns all services with no child services.", + child_service_extras + }, + { + "contactgroup", + "Contact Group", + "nagios:objectjson/contactgrouplist", + { "contactgroup", NULL }, + { "hostcount", "hostlist", "servicecount", "servicelist", "contactcount", "contactlist", "serviceescalationcount", "serviceescalationlist", "hostescalationcount", "hostescalationlist", NULL }, + NULL, + "Returns information applicable to the contactgroup or the contacts in the contactgroup depending on the query.", + NULL + }, + { + "servicedescription", + "Service Description", + "nagios:objectjson/servicelist", + { "service", NULL }, + { "servicecount", "servicelist", "serviceescalationcount", "serviceescalationlist", NULL }, + "hostname", + "Description for the service requested.", + NULL + }, + { + "servicegroupmemberhost", + "Service Group Member Host", + "nagios:objectjson/hostlist", + { NULL }, + { "servicegroupcount", "servicegrouplist", NULL }, + NULL, + "Limits the servicegroups returned to those containing the servicegroupmemberhost (and servicegroupmemberservice).", + NULL + }, + { + "servicegroupmemberservice", + "Service Group Member Service", + "nagios:objectjson/servicelist", + { NULL }, + { "servicegroupcount", "servicegrouplist", NULL }, + "servicegroupmemberhost", + "Limits the servicegroups returned to those containing the servicegroupmemberservice (and servicegroupmemberhost).", + NULL + }, + { + "contactname", + "Contact Name", + "nagios:objectjson/contactlist", + { "contact", NULL }, + { "hostcount", "hostlist", "servicecount", "servicelist", "serviceescalationcount", "serviceescalationlist", "hostescalationcount", "hostescalationlist", NULL }, + NULL, + "Name for the contact requested.", + NULL + }, + { + "contactgroupmember", + "Contact Group Member", + "nagios:objectjson/contactlist", + { NULL }, + { "contactgroupcount", "contactgrouplist", NULL }, + NULL, + "Limits the contactgroups returned to those containing the contactgroupmember.", + NULL + }, + { + "timeperiod", + "Timeperiod Name", + "nagios:objectjson/timeperiodlist", + { "timeperiod", NULL }, + { NULL }, + NULL, + "Name for the timeperiod requested.", + NULL + }, + { + "checktimeperiod", + "Check Timeperiod Name", + "nagios:objectjson/timeperiodlist", + { NULL }, + { "hostcount","hostlist", "servicecount", "servicelist", NULL }, + NULL, + "Name of a check timeperiod to be used as selection criteria.", + NULL + }, + { + "hostnotificationtimeperiod", + "Host Notification Timeperiod Name", + "nagios:objectjson/timeperiodlist", + { NULL }, + { "hostcount","hostlist", "contactcount", "contactlist", NULL }, + NULL, + "Name of a host notification timeperiod to be used as selection criteria.", + NULL + }, + { + "servicenotificationtimeperiod", + "Service Notification Timeperiod Name", + "nagios:objectjson/timeperiodlist", + { NULL }, + { "servicecount", "servicelist", "contactcount", "contactlist", NULL }, + NULL, + "Name of a service notification timeperiod to be used as selection criteria.", + NULL + }, + { + "command", + "Command Name", + "nagios:objectjson/commandlist", + { "command", NULL }, + { NULL }, + NULL, + "Name for the command requested.", + NULL + }, + { + "checkcommand", + "Check Command Name", + "nagios:objectjson/commandlist", + { NULL }, + { "hostcount", "hostlist", "servicecount", "servicelist", NULL }, + NULL, + "Name of a check command to be be used as a selector.", + NULL + }, + { + "eventhandler", + "Event Handler Name", + "nagios:objectjson/commandlist", + { NULL }, + { "hostcount", "hostlist", "servicecount", "servicelist", NULL }, + NULL, + "Name of an event handler to be be used as a selector.", + NULL + }, + { + "masterhostname", + "Master Host Name", + "nagios:objectjson/hostlist", + { NULL }, + { "hostdependencycount", "hostdependencylist", "servicedependencycount", "servicedependencylist", NULL }, + NULL, + "Name for a master host to be used as a selector.", + NULL + }, + { + "masterhostgroupname", + "Master Hostgroup Name", + "nagios:objectjson/hostgrouplist", + { NULL }, + { "hostdependencycount", "hostdependencylist", "servicedependencycount", "servicedependencylist", NULL }, + NULL, + "Name for a master hostgroup to be used as a selector.", + NULL + }, + { + "masterservicedescription", + "Master Service Description", + "nagios:objectjson/servicelist", + { NULL }, + { "servicedependencycount", "servicedependencylist", NULL }, + "masterhostname", + "Description for a master service to be used as a selector.", + NULL + }, + { + "masterservicegroupname", + "Master Servicegroup Name", + "nagios:objectjson/servicegrouplist", + { NULL }, + { "servicedependencycount", "servicedependencylist", NULL }, + NULL, + "Name for a master servicegroup to be used as a selector.", + NULL + }, + { + "dependenthostname", + "Dependent Host Name", + "nagios:objectjson/hostlist", + { NULL }, + { "hostdependencycount", "hostdependencylist", "servicedependencycount", "servicedependencylist", NULL }, + NULL, + "Name for a dependent host to be used as a selector.", + NULL + }, + { + "dependenthostgroupname", + "Dependent Hostgroup Name", + "nagios:objectjson/hostgrouplist", + { NULL }, + { "hostdependencycount", "hostdependencylist", "servicedependencycount", "servicedependencylist", NULL }, + NULL, + "Name for a dependent hostgroup to be used as a selector.", + NULL + }, + { + "dependentservicedescription", + "Dependent Service Description", + "nagios:objectjson/servicelist", + { NULL }, + { "servicedependencycount", "servicedependencylist", NULL }, + "dependenthostname", + "Description for a dependent service to be used as a selector.", + NULL + }, + { + "dependentservicegroupname", + "Dependent Servicegroup Name", + "nagios:objectjson/servicegrouplist", + { NULL }, + { "servicedependencycount", "servicedependencylist", NULL }, + NULL, + "Name for a dependent servicegroup to be used as a selector.", + NULL + }, + { /* The last entry must contain all NULL entries */ + NULL, + NULL, + NULL, + { NULL }, + { NULL }, + NULL, + NULL, + NULL + }, + }; + +extern const json_escape percent_escapes; + +int json_object_host_passes_selection(host *, int, host *, int, host *, + hostgroup *, contact *, contactgroup *, timeperiod *, timeperiod *, + command *, command *); +json_object *json_object_host_selectors(int, int, int, host *, int, host *, + hostgroup *, contact *, contactgroup *, timeperiod *, timeperiod *, + command *, command *); + +int json_object_hostgroup_passes_selection(hostgroup *, host *); +json_object *json_object_hostgroup_selectors(int, int, host *); + +int json_object_service_passes_host_selection(host *, int, host *, int, host *, + hostgroup *, host *); +int json_object_service_passes_service_selection(service *, servicegroup *, + contact *, char *, char *, char *, contactgroup *, timeperiod *, + timeperiod *, command *, command *); +json_object *json_object_service_selectors(int, int, int, host *, int, host *, + hostgroup *, host *, servicegroup *, contact *, char *, char *, char *, + contactgroup *, timeperiod *, timeperiod *, command *, command *); + +int json_object_servicegroup_passes_selection(servicegroup *, service *); +json_object *json_object_servicegroup_display_selectors(int, int, service *); + +int json_object_contact_passes_selection(contact *, contactgroup *, + timeperiod *, timeperiod *); +json_object *json_object_contact_selectors(int, int, contactgroup *, + timeperiod *, timeperiod *); + +int json_object_contactgroup_passes_selection(contactgroup *, contact *); +json_object *json_object_contactgroup_display_selectors(int, int, contact *); + +json_object *json_object_timeperiod_selectors(int, int); + +json_object *json_object_command_selectors(int, int); + +int json_object_servicedependency_passes_selection(servicedependency *, host *, + hostgroup *, char *, servicegroup *, host *, hostgroup *, char *, + servicegroup *); +json_object *json_object_servicedependency_selectors(int, int, host *, + hostgroup *, char *, servicegroup *, host *, hostgroup *, char *, + servicegroup *); + +int json_object_serviceescalation_passes_selection(serviceescalation *, host *, + char *, hostgroup *, servicegroup *, contact *, contactgroup *); +json_object *json_object_serviceescalation_selectors(int, int, host *, char *, + hostgroup *, servicegroup *, contact *, contactgroup *); + +int json_object_hostdependency_passes_selection(hostdependency *, host *, + hostgroup *, host *, hostgroup *); +json_object *json_object_hostdependency_selectors(int, int, host *, + hostgroup *, host *, hostgroup *); + +int json_object_hostescalation_passes_selection(hostescalation *, host *, + hostgroup *, contact *, contactgroup *); +json_object *json_object_hostescalation_selectors(int, int, host *, + hostgroup *, contact *, contactgroup *); + +int main(void) { + int result = OK; + time_t query_time; + object_json_cgi_data cgi_data; + json_object *json_root; + struct stat ocstat; + time_t last_object_cache_update = (time_t)0; + + /* The official time of the query */ + time(&query_time); + + json_root = json_new_object(); + if(NULL == json_root) { + printf( "Failed to create new json object\n"); + exit( 1); + } + json_object_append_integer(json_root, "format_version", + OUTPUT_FORMAT_VERSION); + + /* Initialize shared configuration variables */ + init_shared_cfg_vars(1); + + init_cgi_data(&cgi_data); + + document_header(cgi_data.format_options & JSON_FORMAT_WHITESPACE); + + /* get the arguments passed in the URL */ + result = process_cgivars(json_root, &cgi_data, query_time); + if(result != RESULT_SUCCESS) { + json_object_append_object(json_root, "data", + json_help(object_json_help)); + json_object_print(json_root, 0, 1, cgi_data.strftime_format, + cgi_data.format_options); + document_footer(); + return result; + } + + /* reset internal variables */ + reset_cgi_vars(); + + /* read the CGI configuration file */ + result = read_cgi_config_file(get_cgi_config_location()); + if(result == ERROR) { + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + (time_t)-1, NULL, RESULT_FILE_OPEN_READ_ERROR, + "Error: Could not open CGI configuration file '%s' for reading!", + get_cgi_config_location())); + json_object_append_object(json_root, "data", json_help(object_json_help)); + json_object_print(json_root, 0, 1, cgi_data.strftime_format, + cgi_data.format_options); + document_footer(); + return ERROR; + } + + /* read the main configuration file */ + result = read_main_config_file(main_config_file); + if(result == ERROR) { + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + (time_t)-1, NULL, RESULT_FILE_OPEN_READ_ERROR, + "Error: Could not open main configuration file '%s' for reading!", + main_config_file)); + json_object_append_object(json_root, "data", json_help(object_json_help)); + document_footer(); + return ERROR; + } + + /* read all object configuration data */ + result = read_all_object_configuration_data(main_config_file, + READ_ALL_OBJECT_DATA); + if(result == ERROR) { + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + (time_t)-1, NULL, RESULT_FILE_OPEN_READ_ERROR, + "Error: Could not read some or all object configuration data!")); + json_object_append_object(json_root, "data", json_help(object_json_help)); + document_footer(); + return ERROR; + } + + /* Get the update time on the object cache file */ + if(stat(object_cache_file, &ocstat) < 0) { + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + (time_t)-1, NULL, RESULT_FILE_OPEN_READ_ERROR, + "Error: Could not obtain object cache file status: %s!", + strerror(errno))); + json_object_append_object(json_root, "data", json_help(object_json_help)); + document_footer(); + return ERROR; + } + last_object_cache_update = ocstat.st_mtime; + + /* read all status data */ + result = read_all_status_data(status_file, READ_ALL_STATUS_DATA); + if(result == ERROR) { + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + (time_t)-1, NULL, RESULT_FILE_OPEN_READ_ERROR, + "Error: Could not read host and service status information!")); + json_object_append_object(json_root, "data", json_help(object_json_help)); + + document_footer(); + return ERROR; + } + + /* validate arguments in URL */ + result = validate_arguments(json_root, &cgi_data, query_time); + if(result != RESULT_SUCCESS) { + json_object_append_object(json_root, "data", json_help(object_json_help)); + json_object_print(json_root, 0, 1, cgi_data.strftime_format, + cgi_data.format_options); + document_footer(); + return ERROR; + } + + /* get authentication information */ + get_authentication_information(¤t_authdata); + + /* For most locales, floats get output with a comma instead of a + * decimal point, which messes up the JSON data structure. */ + setlocale(LC_NUMERIC, "C"); + + /* Return something to the user */ + switch( cgi_data.query) { + case OBJECT_QUERY_HOSTCOUNT: + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + last_object_cache_update, ¤t_authdata, + RESULT_SUCCESS, "")); + json_object_append_object(json_root, "data", + json_object_hostcount(cgi_data.use_parent_host, + cgi_data.parent_host, cgi_data.use_child_host, + cgi_data.child_host, cgi_data.hostgroup, cgi_data.contact, + cgi_data.contactgroup, cgi_data.check_timeperiod, + cgi_data.host_notification_timeperiod, cgi_data.check_command, + cgi_data.event_handler)); + break; + case OBJECT_QUERY_HOSTLIST: + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + last_object_cache_update, ¤t_authdata, + RESULT_SUCCESS, "")); + json_object_append_object(json_root, "data", + json_object_hostlist(cgi_data.format_options, cgi_data.start, + cgi_data.count, cgi_data.details, cgi_data.use_parent_host, + cgi_data.parent_host, cgi_data.use_child_host, + cgi_data.child_host, cgi_data.hostgroup, cgi_data.contact, + cgi_data.contactgroup, cgi_data.check_timeperiod, + cgi_data.host_notification_timeperiod, cgi_data.check_command, + cgi_data.event_handler)); + break; + case OBJECT_QUERY_HOST: + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + last_object_cache_update, ¤t_authdata, + RESULT_SUCCESS, "")); + json_object_append_object(json_root, "data", + json_object_host(cgi_data.format_options, cgi_data.host)); + break; + case OBJECT_QUERY_HOSTGROUPCOUNT: + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + last_object_cache_update, ¤t_authdata, + RESULT_SUCCESS, "")); + json_object_append_object(json_root, "data", + json_object_hostgroupcount(cgi_data.format_options, + cgi_data.hostgroup_member)); + break; + case OBJECT_QUERY_HOSTGROUPLIST: + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + last_object_cache_update, ¤t_authdata, + RESULT_SUCCESS, "")); + json_object_append_object(json_root, "data", + json_object_hostgrouplist(cgi_data.format_options, + cgi_data.start, cgi_data.count, cgi_data.details, + cgi_data.hostgroup_member)); + break; + case OBJECT_QUERY_HOSTGROUP: + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + last_object_cache_update, ¤t_authdata, + RESULT_SUCCESS, "")); + json_object_append_object(json_root, "data", + json_object_hostgroup(cgi_data.format_options, + cgi_data.hostgroup)); + break; + case OBJECT_QUERY_SERVICECOUNT: + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + last_object_cache_update, ¤t_authdata, + RESULT_SUCCESS, "")); + json_object_append_object(json_root, "data", + json_object_servicecount(cgi_data.host, + cgi_data.use_parent_host, cgi_data.parent_host, + cgi_data.use_child_host, cgi_data.child_host, + cgi_data.hostgroup, cgi_data.servicegroup, cgi_data.contact, + cgi_data.service_description, cgi_data.parent_service_name, + cgi_data.child_service_name, cgi_data.contactgroup, + cgi_data.check_timeperiod, + cgi_data.service_notification_timeperiod, + cgi_data.check_command, cgi_data.event_handler)); + break; + case OBJECT_QUERY_SERVICELIST: + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + last_object_cache_update, ¤t_authdata, + RESULT_SUCCESS, "")); + json_object_append_object(json_root, "data", + json_object_servicelist(cgi_data.format_options, cgi_data.start, + cgi_data.count, cgi_data.details, cgi_data.host, + cgi_data.use_parent_host, cgi_data.parent_host, + cgi_data.use_child_host, cgi_data.child_host, + cgi_data.hostgroup, cgi_data.servicegroup, cgi_data.contact, + cgi_data.service_description, cgi_data.parent_service_name, + cgi_data.child_service_name, cgi_data.contactgroup, + cgi_data.check_timeperiod, + cgi_data.service_notification_timeperiod, + cgi_data.check_command, cgi_data.event_handler)); + break; + case OBJECT_QUERY_SERVICE: + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + last_object_cache_update, ¤t_authdata, + RESULT_SUCCESS, "")); + json_object_append_object(json_root, "data", + json_object_service(cgi_data.format_options, cgi_data.service)); + break; + case OBJECT_QUERY_SERVICEGROUPCOUNT: + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + last_object_cache_update, ¤t_authdata, + RESULT_SUCCESS, "")); + json_object_append_object(json_root, "data", + json_object_servicegroupcount(cgi_data.servicegroup_member)); + break; + case OBJECT_QUERY_SERVICEGROUPLIST: + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + last_object_cache_update, ¤t_authdata, + RESULT_SUCCESS, "")); + json_object_append_object(json_root, "data", + json_object_servicegrouplist(cgi_data.format_options, + cgi_data.start, cgi_data.count, cgi_data.details, + cgi_data.servicegroup_member)); + break; + case OBJECT_QUERY_SERVICEGROUP: + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + last_object_cache_update, ¤t_authdata, + RESULT_SUCCESS, "")); + json_object_append_object(json_root, "data", + json_object_servicegroup(cgi_data.format_options, + cgi_data.servicegroup)); + break; + case OBJECT_QUERY_CONTACTCOUNT: + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + last_object_cache_update, ¤t_authdata, + RESULT_SUCCESS, "")); + json_object_append_object(json_root, "data", + json_object_contactcount(cgi_data.contactgroup, + cgi_data.host_notification_timeperiod, + cgi_data.service_notification_timeperiod)); + break; + case OBJECT_QUERY_CONTACTLIST: + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + last_object_cache_update, ¤t_authdata, + RESULT_SUCCESS, "")); + json_object_append_object(json_root, "data", + json_object_contactlist(cgi_data.format_options, cgi_data.start, + cgi_data.count, cgi_data.details, cgi_data.contactgroup, + cgi_data.host_notification_timeperiod, + cgi_data.service_notification_timeperiod)); + break; + case OBJECT_QUERY_CONTACT: + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + last_object_cache_update, ¤t_authdata, + RESULT_SUCCESS, "")); + json_object_append_object(json_root, "data", + json_object_contact(cgi_data.format_options, cgi_data.contact)); + break; + case OBJECT_QUERY_CONTACTGROUPCOUNT: + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + last_object_cache_update, ¤t_authdata, + RESULT_SUCCESS, "")); + json_object_append_object(json_root, "data", + json_object_contactgroupcount(cgi_data.contactgroup_member)); + break; + case OBJECT_QUERY_CONTACTGROUPLIST: + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + last_object_cache_update, ¤t_authdata, + RESULT_SUCCESS, "")); + json_object_append_object(json_root, "data", + json_object_contactgrouplist(cgi_data.format_options, + cgi_data.start, cgi_data.count, cgi_data.details, + cgi_data.contactgroup_member)); + break; + case OBJECT_QUERY_CONTACTGROUP: + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + last_object_cache_update, ¤t_authdata, + RESULT_SUCCESS, "")); + json_object_append_object(json_root, "data", + json_object_contactgroup(cgi_data.format_options, + cgi_data.contactgroup)); + break; + case OBJECT_QUERY_TIMEPERIODCOUNT: + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + last_object_cache_update, ¤t_authdata, + RESULT_SUCCESS, "")); + json_object_append_object(json_root, "data", + json_object_timeperiodcount()); + break; + case OBJECT_QUERY_TIMEPERIODLIST: + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + last_object_cache_update, ¤t_authdata, + RESULT_SUCCESS, "")); + json_object_append_object(json_root, "data", + json_object_timeperiodlist(cgi_data.format_options, + cgi_data.start, cgi_data.count, cgi_data.details)); + break; + case OBJECT_QUERY_TIMEPERIOD: + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + last_object_cache_update, ¤t_authdata, + RESULT_SUCCESS, "")); + json_object_append_object(json_root, "data", + json_object_timeperiod(cgi_data.format_options, + cgi_data.timeperiod)); + break; + case OBJECT_QUERY_COMMANDCOUNT: + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + last_object_cache_update, ¤t_authdata, + RESULT_SUCCESS, "")); + json_object_append_object(json_root, "data", json_object_commandcount()); + break; + case OBJECT_QUERY_COMMANDLIST: + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + last_object_cache_update, ¤t_authdata, + RESULT_SUCCESS, "")); + json_object_append_object(json_root, "data", + json_object_commandlist(cgi_data.format_options, cgi_data.start, + cgi_data.count, cgi_data.details)); + break; + case OBJECT_QUERY_COMMAND: + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + last_object_cache_update, ¤t_authdata, + RESULT_SUCCESS, "")); + json_object_append_object(json_root, "data", + json_object_command(cgi_data.format_options, cgi_data.command)); + break; + case OBJECT_QUERY_SERVICEDEPENDENCYCOUNT: + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + last_object_cache_update, ¤t_authdata, + RESULT_SUCCESS, "")); + json_object_append_object(json_root, "data", + json_object_servicedependencycount(cgi_data.master_host, + cgi_data.master_hostgroup, cgi_data.master_service_description, + cgi_data.master_servicegroup, cgi_data.dependent_host, + cgi_data.dependent_hostgroup, + cgi_data.dependent_service_description, + cgi_data.dependent_servicegroup)); + break; + case OBJECT_QUERY_SERVICEDEPENDENCYLIST: + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + last_object_cache_update, ¤t_authdata, + RESULT_SUCCESS, "")); + json_object_append_object(json_root, "data", + json_object_servicedependencylist(cgi_data.format_options, + cgi_data.start, cgi_data.count, cgi_data.master_host, + cgi_data.master_hostgroup, cgi_data.master_service_description, + cgi_data.master_servicegroup, cgi_data.dependent_host, + cgi_data.dependent_hostgroup, + cgi_data.dependent_service_description, + cgi_data.dependent_servicegroup)); + break; + case OBJECT_QUERY_SERVICEESCALATIONCOUNT: + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + last_object_cache_update, ¤t_authdata, + RESULT_SUCCESS, "")); + json_object_append_object(json_root, "data", + json_object_serviceescalationcount(cgi_data.host, + cgi_data.service_description, cgi_data.hostgroup, + cgi_data.servicegroup, cgi_data.contact, + cgi_data.contactgroup)); + break; + case OBJECT_QUERY_SERVICEESCALATIONLIST: + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + last_object_cache_update, ¤t_authdata, + RESULT_SUCCESS, "")); + json_object_append_object(json_root, "data", + json_object_serviceescalationlist(cgi_data.format_options, + cgi_data.start, cgi_data.count, cgi_data.host, + cgi_data.service_description, cgi_data.hostgroup, + cgi_data.servicegroup, cgi_data.contact, + cgi_data.contactgroup)); + break; + case OBJECT_QUERY_HOSTDEPENDENCYCOUNT: + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + last_object_cache_update, ¤t_authdata, + RESULT_SUCCESS, "")); + json_object_append_object(json_root, "data", + json_object_hostdependencycount(cgi_data.master_host, + cgi_data.master_hostgroup, cgi_data.dependent_host, + cgi_data.dependent_hostgroup)); + break; + case OBJECT_QUERY_HOSTDEPENDENCYLIST: + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + last_object_cache_update, ¤t_authdata, + RESULT_SUCCESS, "")); + json_object_append_object(json_root, "data", + json_object_hostdependencylist(cgi_data.format_options, + cgi_data.start, cgi_data.count, cgi_data.master_host, + cgi_data.master_hostgroup, cgi_data.dependent_host, + cgi_data.dependent_hostgroup)); + break; + case OBJECT_QUERY_HOSTESCALATIONCOUNT: + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + last_object_cache_update, ¤t_authdata, + RESULT_SUCCESS, "")); + json_object_append_object(json_root, "data", + json_object_hostescalationcount(cgi_data.host, + cgi_data.hostgroup, cgi_data.contact, cgi_data.contactgroup)); + break; + case OBJECT_QUERY_HOSTESCALATIONLIST: + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + last_object_cache_update, ¤t_authdata, + RESULT_SUCCESS, "")); + json_object_append_object(json_root, "data", + json_object_hostescalationlist(cgi_data.format_options, + cgi_data.start, cgi_data.count, cgi_data.host, + cgi_data.hostgroup, cgi_data.contact, cgi_data.contactgroup)); + break; + case OBJECT_QUERY_HELP: + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + compile_time(__DATE__, __TIME__), ¤t_authdata, + RESULT_SUCCESS, "")); + json_object_append_object(json_root, "data", json_help(object_json_help)); + break; + default: + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + (time_t)-1, ¤t_authdata, RESULT_OPTION_MISSING, + "Error: Object Type not specified. See data for help.")); + json_object_append_object(json_root, "data", json_help(object_json_help)); + break; + } + + json_object_print(json_root, 0, 1, cgi_data.strftime_format, + cgi_data.format_options); + document_footer(); + + /* free all allocated memory */ + free_cgi_data( &cgi_data); + json_free_object(json_root, 1); + free_memory(); + + return OK; + } + +void document_header(int whitespace) { + char date_time[MAX_DATETIME_LENGTH]; + time_t expire_time; + time_t current_time; + + time(¤t_time); + + printf("Cache-Control: no-store\r\n"); + printf("Pragma: no-cache\r\n"); + + get_time_string(¤t_time, date_time, (int)sizeof(date_time), HTTP_DATE_TIME); + printf("Last-Modified: %s\r\n", date_time); + + expire_time = (time_t)0L; + get_time_string(&expire_time, date_time, (int)sizeof(date_time), HTTP_DATE_TIME); + printf("Expires: %s\r\n", date_time); + + printf("Content-type: application/json; charset=utf-8\r\n\r\n"); + + return; + } + + +void document_footer(void) { + + printf( "\n"); + + return; + } + + +void init_cgi_data(object_json_cgi_data *cgi_data) { + cgi_data->format_options = 0; + cgi_data->query = OBJECT_QUERY_INVALID; + cgi_data->start = 0; + cgi_data->count = 0; + cgi_data->details = 0; + cgi_data->strftime_format = NULL; + cgi_data->parent_host_name = NULL; + cgi_data->use_parent_host = 0; + cgi_data->parent_host = NULL; + cgi_data->child_host_name = NULL; + cgi_data->use_child_host = 0; + cgi_data->child_host = NULL; + cgi_data->host_name = NULL; + cgi_data->host = NULL; + cgi_data->hostgroup_member_name = NULL; + cgi_data->hostgroup_member = NULL; + cgi_data->hostgroup_name = NULL; + cgi_data->hostgroup = NULL; + cgi_data->servicegroup_name = NULL; + cgi_data->servicegroup = NULL; + cgi_data->service_description = NULL; + cgi_data->service = NULL; + cgi_data->servicegroup_member_host_name = NULL; + cgi_data->servicegroup_member_service_description = NULL; + cgi_data->servicegroup_member = NULL; + cgi_data->parent_service_name = NULL; + cgi_data->child_service_name = NULL; + cgi_data->contactgroup_name = NULL; + cgi_data->contactgroup = NULL; + cgi_data->contact_name = NULL; + cgi_data->contact = NULL; + cgi_data->contactgroup_member_name = NULL; + cgi_data->contactgroup_member = NULL; + cgi_data->timeperiod_name = NULL; + cgi_data->timeperiod = NULL; + cgi_data->check_timeperiod_name = NULL; + cgi_data->check_timeperiod = NULL; + cgi_data->host_notification_timeperiod_name = NULL; + cgi_data->host_notification_timeperiod = NULL; + cgi_data->service_notification_timeperiod_name = NULL; + cgi_data->service_notification_timeperiod = NULL; + cgi_data->command_name = NULL; + cgi_data->command = NULL; + cgi_data->check_command_name = NULL; + cgi_data->check_command = NULL; + cgi_data->event_handler_name = NULL; + cgi_data->event_handler = NULL; + cgi_data->master_host_name = NULL; + cgi_data->master_host = NULL; + cgi_data->master_hostgroup_name = NULL; + cgi_data->master_hostgroup = NULL; + cgi_data->master_service_description = NULL; + cgi_data->master_service = NULL; + cgi_data->master_servicegroup_name = NULL; + cgi_data->master_servicegroup = NULL; + cgi_data->dependent_host_name = NULL; + cgi_data->dependent_host = NULL; + cgi_data->dependent_hostgroup_name = NULL; + cgi_data->dependent_hostgroup = NULL; + cgi_data->dependent_service_description = NULL; + cgi_data->dependent_service = NULL; + cgi_data->dependent_servicegroup_name = NULL; + cgi_data->dependent_servicegroup = NULL; +} + +void free_cgi_data( object_json_cgi_data *cgi_data) { + if( NULL != cgi_data->strftime_format) free( cgi_data->strftime_format); + if( NULL != cgi_data->parent_host_name) free( cgi_data->parent_host_name); + if( NULL != cgi_data->child_host_name) free( cgi_data->child_host_name); + if( NULL != cgi_data->host_name) free( cgi_data->host_name); + if( NULL != cgi_data->hostgroup_member_name) free( cgi_data->hostgroup_member_name); + if( NULL != cgi_data->hostgroup_name) free( cgi_data->hostgroup_name); + if( NULL != cgi_data->servicegroup_name) free(cgi_data->servicegroup_name); + if( NULL != cgi_data->service_description) free(cgi_data->service_description); + if( NULL != cgi_data->servicegroup_member_host_name) free(cgi_data->servicegroup_member_host_name); + if( NULL != cgi_data->servicegroup_member_service_description) free(cgi_data->servicegroup_member_service_description); + if( NULL != cgi_data->parent_service_name) free( cgi_data->parent_service_name); + if( NULL != cgi_data->child_service_name) free( cgi_data->child_service_name); + if( NULL != cgi_data->contactgroup_name) free(cgi_data->contactgroup_name); + if( NULL != cgi_data->contact_name) free(cgi_data->contact_name); + if( NULL != cgi_data->contactgroup_member_name) free(cgi_data->contactgroup_member_name); + if( NULL != cgi_data->timeperiod_name) free(cgi_data->timeperiod_name); + if( NULL != cgi_data->check_timeperiod_name) free(cgi_data->check_timeperiod_name); + if( NULL != cgi_data->host_notification_timeperiod_name) free(cgi_data->host_notification_timeperiod_name); + if( NULL != cgi_data->service_notification_timeperiod_name) free(cgi_data->service_notification_timeperiod_name); + if( NULL != cgi_data->command_name) free(cgi_data->command_name); + if( NULL != cgi_data->check_command_name) free(cgi_data->check_command_name); + if( NULL != cgi_data->event_handler_name) free(cgi_data->event_handler_name); + if( NULL != cgi_data->master_host_name) free(cgi_data->master_host_name); + if( NULL != cgi_data->master_hostgroup_name) free(cgi_data->master_hostgroup_name); + if( NULL != cgi_data->master_service_description) free(cgi_data->master_service_description); + if( NULL != cgi_data->master_servicegroup_name) free(cgi_data->master_servicegroup_name); + if( NULL != cgi_data->dependent_host_name) free(cgi_data->dependent_host_name); + if( NULL != cgi_data->dependent_hostgroup_name) free(cgi_data->dependent_hostgroup_name); + if( NULL != cgi_data->dependent_service_description) free(cgi_data->dependent_service_description); + if( NULL != cgi_data->dependent_servicegroup_name) free(cgi_data->dependent_servicegroup_name); + } + + +int process_cgivars(json_object *json_root, object_json_cgi_data *cgi_data, + time_t query_time) { + char **variables; + int result = RESULT_SUCCESS; + int x; + authdata *authinfo = NULL; /* Currently always NULL because + get_authentication_information() hasn't + been called yet, but in case we want to + use it in the future... */ + + variables = getcgivars(); + + for(x = 0; variables[x] != NULL; x++) { + /* We set these each iteration because they could change with each + iteration */ + + if(!strcmp(variables[x], "query")) { + if((result = parse_enumeration_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], valid_queries, &(cgi_data->query))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "formatoptions")) { + cgi_data->format_options = 0; + if((result = parse_bitmask_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], svm_format_options, + &(cgi_data->format_options))) != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "start")) { + if((result = parse_int_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->start))) != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "count")) { + if((result = parse_int_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->count))) != RESULT_SUCCESS) { + break; + } + + if(cgi_data->count == 0) { + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, + valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, RESULT_OPTION_VALUE_INVALID, + "The count option value is invalid. " + "It must be an integer greater than zero")); + result = RESULT_OPTION_VALUE_INVALID; + break; + } + x++; + } + + else if(!strcmp(variables[x], "parenthost")) { + if((result = parse_string_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->parent_host_name))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "childhost")) { + if((result = parse_string_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->child_host_name))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "hostname")) { + if((result = parse_string_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->host_name))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "hostgroupmember")) { + if((result = parse_string_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->hostgroup_member_name))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "hostgroup")) { + if((result = parse_string_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->hostgroup_name))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "servicegroup")) { + if((result = parse_string_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->servicegroup_name))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "parentservice")) { + if((result = parse_string_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->parent_service_name))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "childservice")) { + if((result = parse_string_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->child_service_name))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "contactgroup")) { + if((result = parse_string_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->contactgroup_name))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "servicedescription")) { + if((result = parse_string_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->service_description))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "servicegroupmemberhost")) { + if((result = parse_string_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->servicegroup_member_host_name))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "servicegroupmemberservice")) { + if((result = parse_string_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], + &(cgi_data->servicegroup_member_service_description))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "contactname")) { + if((result = parse_string_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->contact_name))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "contactgroupmember")) { + if((result = parse_string_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->contactgroup_member_name))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "timeperiod")) { + if((result = parse_string_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->timeperiod_name))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "checktimeperiod")) { + if((result = parse_string_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->check_timeperiod_name))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "hostnotificationtimeperiod")) { + if((result = parse_string_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], + &(cgi_data->host_notification_timeperiod_name))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "servicenotificationtimeperiod")) { + if((result = parse_string_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], + &(cgi_data->service_notification_timeperiod_name))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "command")) { + if((result = parse_string_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->command_name))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "checkcommand")) { + if((result = parse_string_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->check_command_name))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "eventhandler")) { + if((result = parse_string_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->event_handler_name))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "masterhostname")) { + if((result = parse_string_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->master_host_name))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "masterhostgroupname")) { + if((result = parse_string_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->master_hostgroup_name))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "masterservicedescription")) { + if((result = parse_string_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->master_service_description))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "masterservicegroupname")) { + if((result = parse_string_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->master_servicegroup_name))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "dependenthostname")) { + if((result = parse_string_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->dependent_host_name))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "dependenthostgroupname")) { + if((result = parse_string_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->dependent_hostgroup_name))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "dependentservicedescription")) { + if((result = parse_string_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->dependent_service_description))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "dependentservicegroupname")) { + if((result = parse_string_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->dependent_servicegroup_name))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "details")) { + if((result = parse_boolean_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->details))) != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "dateformat")) { + if((result = parse_string_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->strftime_format))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "NagFormId")) + ++x; + + else if(!strcmp(variables[x], "")); + + else { + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, RESULT_OPTION_INVALID, + "Invalid option: '%s'.", variables[x])); + result = RESULT_OPTION_INVALID; + break; + } + } + + /* free memory allocated to the CGI variables */ + free_cgivars(variables); + + return result; + } + +int validate_arguments(json_object *json_root, object_json_cgi_data *cgi_data, + time_t query_time) { + int result = RESULT_SUCCESS; + host *temp_host = NULL; + hostgroup *temp_hostgroup = NULL; + servicegroup *temp_servicegroup = NULL; + service *temp_service = NULL; + contactgroup *temp_contactgroup = NULL; + contact *temp_contact = NULL; + timeperiod *temp_timeperiod = NULL; + command *temp_command = NULL; + authdata *authinfo = NULL; /* Currently always NULL because + get_authentication_information() hasn't + been called yet, but in case we want to + use it in the future... */ + + /* Validate that required parameters were supplied */ + switch(cgi_data->query) { + case OBJECT_QUERY_HOSTCOUNT: + break; + case OBJECT_QUERY_HOSTLIST: + break; + case OBJECT_QUERY_HOST: + if( NULL == cgi_data->host_name) { + result = RESULT_OPTION_MISSING; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "Host information requested, but no host name specified.")); + } + break; + case OBJECT_QUERY_HOSTGROUPCOUNT: + break; + case OBJECT_QUERY_HOSTGROUPLIST: + break; + case OBJECT_QUERY_HOSTGROUP: + if( NULL == cgi_data->hostgroup_name) { + result = RESULT_OPTION_MISSING; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "Hostgroup information requested, but no hostgroup name specified.")); + } + break; + case OBJECT_QUERY_SERVICECOUNT: + break; + case OBJECT_QUERY_SERVICELIST: + break; + case OBJECT_QUERY_SERVICE: + if( NULL == cgi_data->host_name) { + result = RESULT_OPTION_MISSING; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "Service information requested, but no host name specified.")); + } + if( NULL == cgi_data->service_description) { + result = RESULT_OPTION_MISSING; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "Service information requested, but no service description specified.")); + } + break; + case OBJECT_QUERY_SERVICEGROUPCOUNT: + break; + case OBJECT_QUERY_SERVICEGROUPLIST: + break; + case OBJECT_QUERY_SERVICEGROUP: + if( NULL == cgi_data->servicegroup_name) { + result = RESULT_OPTION_MISSING; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "Service group information requested, but no service group name specified.")); + } + break; + case OBJECT_QUERY_CONTACTCOUNT: + break; + case OBJECT_QUERY_CONTACTLIST: + break; + case OBJECT_QUERY_CONTACT: + if( NULL == cgi_data->contact_name) { + result = RESULT_OPTION_MISSING; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "Contact information requested, but no contact name specified.")); + } + break; + case OBJECT_QUERY_CONTACTGROUPCOUNT: + break; + case OBJECT_QUERY_CONTACTGROUPLIST: + break; + case OBJECT_QUERY_CONTACTGROUP: + if( NULL == cgi_data->contactgroup_name) { + result = RESULT_OPTION_MISSING; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "Contactgroup information requested, but no contactgroup name specified.")); + } + break; + case OBJECT_QUERY_TIMEPERIODCOUNT: + break; + case OBJECT_QUERY_TIMEPERIODLIST: + break; + case OBJECT_QUERY_TIMEPERIOD: + if( NULL == cgi_data->timeperiod_name) { + result = RESULT_OPTION_MISSING; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "Timeperiod information requested, but no timeperiod name specified.")); + } + break; + case OBJECT_QUERY_COMMANDCOUNT: + break; + case OBJECT_QUERY_COMMANDLIST: + break; + case OBJECT_QUERY_COMMAND: + if( NULL == cgi_data->command_name) { + result = RESULT_OPTION_MISSING; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "Command information requested, but no command name specified.")); + } + break; + case OBJECT_QUERY_SERVICEDEPENDENCYCOUNT: + break; + case OBJECT_QUERY_SERVICEDEPENDENCYLIST: + break; + case OBJECT_QUERY_SERVICEESCALATIONCOUNT: + break; + case OBJECT_QUERY_SERVICEESCALATIONLIST: + break; + case OBJECT_QUERY_HOSTDEPENDENCYCOUNT: + break; + case OBJECT_QUERY_HOSTDEPENDENCYLIST: + break; + case OBJECT_QUERY_HOSTESCALATIONCOUNT: + break; + case OBJECT_QUERY_HOSTESCALATIONLIST: + break; + case OBJECT_QUERY_HELP: + break; + default: + result = RESULT_OPTION_MISSING; + json_object_append_object(json_root, "result", json_result(query_time, + THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "Missing validation for object type %u.", cgi_data->query)); + break; + } + + /* Validate the requested parent host */ + if( NULL != cgi_data->parent_host_name) { + cgi_data->use_parent_host = 1; + cgi_data->parent_host = NULL; + if(strcmp(cgi_data->parent_host_name, "none")) { + temp_host = find_host(cgi_data->parent_host_name); + if( NULL == temp_host) { + cgi_data->use_parent_host = 0; + result = RESULT_OPTION_VALUE_INVALID; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, + valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "The parenthost '%s' could not be found.", + cgi_data->parent_host_name)); + } + else { + cgi_data->parent_host = temp_host; + } + } + } + + /* Validate the requested child host */ + if( NULL != cgi_data->child_host_name) { + cgi_data->use_child_host = 1; + cgi_data->child_host = NULL; + if(strcmp(cgi_data->child_host_name, "none")) { + temp_host = find_host(cgi_data->child_host_name); + if( NULL == temp_host) { + cgi_data->use_child_host = 0; + result = RESULT_OPTION_VALUE_INVALID; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, + valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "The childhost '%s' could not be found.", + cgi_data->child_host_name)); + } + else { + cgi_data->child_host = temp_host; + } + } + } + + /* Validate the requested host */ + if( NULL != cgi_data->host_name) { + temp_host = find_host(cgi_data->host_name); + if( NULL == temp_host) { + result = RESULT_OPTION_VALUE_INVALID; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "The host '%s' could not be found.", cgi_data->host_name)); + } + else { + cgi_data->host = temp_host; + } + } + + /* Validate the requested hostgroup member */ + if( NULL != cgi_data->hostgroup_member_name) { + temp_host = find_host(cgi_data->hostgroup_member_name); + if( NULL == temp_host) { + result = RESULT_OPTION_VALUE_INVALID; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "The hostgroup member '%s' could not be found.", + cgi_data->hostgroup_member_name)); + } + else { + cgi_data->hostgroup_member = temp_host; + } + } + + /* Validate the requested hostgroup */ + if( NULL != cgi_data->hostgroup_name) { + temp_hostgroup = find_hostgroup(cgi_data->hostgroup_name); + if( NULL == temp_hostgroup) { + result = RESULT_OPTION_VALUE_INVALID; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "The hostgroup '%s' could not be found.", + cgi_data->hostgroup_name)); + } + else { + cgi_data->hostgroup = temp_hostgroup; + } + } + + /* Validate the requested servicegroup */ + if( NULL != cgi_data->servicegroup_name) { + temp_servicegroup = find_servicegroup(cgi_data->servicegroup_name); + if( NULL == temp_servicegroup) { + result = RESULT_OPTION_VALUE_INVALID; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "The servicegroup '%s' could not be found.", + cgi_data->servicegroup_name)); + } + else { + cgi_data->servicegroup = temp_servicegroup; + } + } + + /* Validate the requested contactgroup */ + if( NULL != cgi_data->contactgroup_name) { + temp_contactgroup = find_contactgroup(cgi_data->contactgroup_name); + if( NULL == temp_contactgroup) { + result = RESULT_OPTION_VALUE_INVALID; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "The contactgroup '%s' could not be found.", + cgi_data->contactgroup_name)); + } + else { + cgi_data->contactgroup = temp_contactgroup; + } + } + + /* Validate the requested service. Note that the host name is not a + required parameter for all queries and so it may not make sense to + try to obtain the service associated with a service description */ + if((NULL != cgi_data->service_description) && + (NULL != cgi_data->host_name)) { + temp_service = find_service(cgi_data->host_name, + cgi_data->service_description); + if( NULL == temp_service) { + result = RESULT_OPTION_VALUE_INVALID; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "The service '%s' on host '%s' could not be found.", + cgi_data->service_description, cgi_data->host_name)); + } + else { + cgi_data->service = temp_service; + } + } + + /* Validate the requested servicegroup member host name and service + description */ + if( NULL != cgi_data->servicegroup_member_host_name || + NULL != cgi_data->servicegroup_member_service_description) { + if( NULL == cgi_data->servicegroup_member_host_name || + NULL == cgi_data->servicegroup_member_service_description) { + result = RESULT_OPTION_VALUE_MISSING; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "If either the servicegroupmemberhost or servicegroupmemberservice is specified, both must be specified.")); + } + else { + temp_service = find_service( cgi_data->servicegroup_member_host_name, + cgi_data->servicegroup_member_service_description); + if( NULL == temp_service) { + result = RESULT_OPTION_VALUE_INVALID; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, + valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "The servicegroup member service '%s' on host '%s' could not be found.", + cgi_data->servicegroup_member_service_description, + cgi_data->servicegroup_member_host_name)); + } + else { + cgi_data->servicegroup_member = temp_service; + } + } + } + + /* Validate the requested contact */ + if( NULL != cgi_data->contact_name) { + temp_contact = find_contact(cgi_data->contact_name); + if( NULL == temp_contact) { + result = RESULT_OPTION_VALUE_INVALID; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "The contact '%s' could not be found.", + cgi_data->contact_name)); + } + else { + cgi_data->contact = temp_contact; + } + } + + /* Validate the requested contactgroup member */ + if( NULL != cgi_data->contactgroup_member_name) { + temp_contact = find_contact(cgi_data->contactgroup_member_name); + if( NULL == temp_contact) { + result = RESULT_OPTION_VALUE_INVALID; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "The contactgroup member '%s' could not be found.", + cgi_data->contactgroup_member_name)); + } + else { + cgi_data->contactgroup_member = temp_contact; + } + } + + /* Validate the requested timeperiod */ + if( NULL != cgi_data->timeperiod_name) { + temp_timeperiod = find_timeperiod(cgi_data->timeperiod_name); + if( NULL == temp_timeperiod) { + result = RESULT_OPTION_VALUE_INVALID; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "The timeperiod '%s' could not be found.", + cgi_data->timeperiod_name)); + } + else { + cgi_data->timeperiod = temp_timeperiod; + } + } + + /* Validate the requested check timeperiod */ + if( NULL != cgi_data->check_timeperiod_name) { + temp_timeperiod = find_timeperiod(cgi_data->check_timeperiod_name); + if( NULL == temp_timeperiod) { + result = RESULT_OPTION_VALUE_INVALID; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "The check timeperiod '%s' could not be found.", + cgi_data->check_timeperiod_name)); + } + else { + cgi_data->check_timeperiod = temp_timeperiod; + } + } + + /* Validate the requested host notification timeperiod */ + if( NULL != cgi_data->host_notification_timeperiod_name) { + temp_timeperiod = + find_timeperiod(cgi_data->host_notification_timeperiod_name); + if( NULL == temp_timeperiod) { + result = RESULT_OPTION_VALUE_INVALID; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "The host notification timeperiod '%s' could not be found.", + cgi_data->host_notification_timeperiod_name)); + } + else { + cgi_data->host_notification_timeperiod = temp_timeperiod; + } + } + + /* Validate the requested service notification timeperiod */ + if( NULL != cgi_data->service_notification_timeperiod_name) { + temp_timeperiod = + find_timeperiod(cgi_data->service_notification_timeperiod_name); + if( NULL == temp_timeperiod) { + result = RESULT_OPTION_VALUE_INVALID; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "The service notification timeperiod '%s' could not be found.", + cgi_data->service_notification_timeperiod_name)); + } + else { + cgi_data->service_notification_timeperiod = temp_timeperiod; + } + } + + /* Validate the requested command */ + if( NULL != cgi_data->command_name) { + temp_command = find_command(cgi_data->command_name); + if( NULL == temp_command) { + result = RESULT_OPTION_VALUE_INVALID; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, "The command '%s' could not be found.", + cgi_data->command_name)); + } + else { + cgi_data->command = temp_command; + } + } + + /* Validate the requested check command */ + if( NULL != cgi_data->check_command_name) { + temp_command = find_command(cgi_data->check_command_name); + if( NULL == temp_command) { + result = RESULT_OPTION_VALUE_INVALID; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "The check command '%s' could not be found.", + cgi_data->check_command_name)); + } + else { + cgi_data->check_command = temp_command; + } + } + + /* Validate the requested event handler */ + if( NULL != cgi_data->event_handler_name) { + temp_command = find_command(cgi_data->event_handler_name); + if( NULL == temp_command) { + result = RESULT_OPTION_VALUE_INVALID; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "The event handler '%s' could not be found.", + cgi_data->event_handler_name)); + } + else { + cgi_data->event_handler = temp_command; + } + } + + /* Validate the requested master host */ + if( NULL != cgi_data->master_host_name) { + temp_host = find_host(cgi_data->master_host_name); + if( NULL == temp_host) { + result = RESULT_OPTION_VALUE_INVALID; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "The master host '%s' could not be found.", + cgi_data->master_host_name)); + } + else { + cgi_data->master_host = temp_host; + } + } + + /* Validate the requested master hostgroup */ + if( NULL != cgi_data->master_hostgroup_name) { + temp_hostgroup = find_hostgroup(cgi_data->master_hostgroup_name); + if( NULL == temp_hostgroup) { + result = RESULT_OPTION_VALUE_INVALID; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "The master hostgroup '%s' could not be found.", + cgi_data->master_hostgroup_name)); + } + else { + cgi_data->master_hostgroup = temp_hostgroup; + } + } + + /* Validate the requested master servicegroup */ + if( NULL != cgi_data->master_servicegroup_name) { + temp_servicegroup = + find_servicegroup(cgi_data->master_servicegroup_name); + if( NULL == temp_servicegroup) { + result = RESULT_OPTION_VALUE_INVALID; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "The master servicegroup '%s' could not be found.", + cgi_data->master_servicegroup_name)); + } + else { + cgi_data->master_servicegroup = temp_servicegroup; + } + } + + /* Validate the requested dependent host */ + if( NULL != cgi_data->dependent_host_name) { + temp_host = find_host(cgi_data->dependent_host_name); + if( NULL == temp_host) { + result = RESULT_OPTION_VALUE_INVALID; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "The dependent host '%s' could not be found.", + cgi_data->dependent_host_name)); + } + else { + cgi_data->dependent_host = temp_host; + } + } + + /* Validate the requested dependent hostgroup */ + if( NULL != cgi_data->dependent_hostgroup_name) { + temp_hostgroup = find_hostgroup(cgi_data->dependent_hostgroup_name); + if( NULL == temp_hostgroup) { + result = RESULT_OPTION_VALUE_INVALID; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "The dependent hostgroup '%s' could not be found.", + cgi_data->dependent_hostgroup_name)); + } + else { + cgi_data->dependent_hostgroup = temp_hostgroup; + } + } + + /* Validate the requested dependent servicegroup */ + if( NULL != cgi_data->dependent_servicegroup_name) { + temp_servicegroup = + find_servicegroup(cgi_data->dependent_servicegroup_name); + if( NULL == temp_servicegroup) { + result = RESULT_OPTION_VALUE_INVALID; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "The dependent servicegroup '%s' could not be found.", + cgi_data->dependent_servicegroup_name)); + } + else { + cgi_data->dependent_servicegroup = temp_servicegroup; + } + } + + return result; + } + +json_object * json_object_custom_variables(struct customvariablesmember *custom_variables) { + + json_object *json_custom_variables; + customvariablesmember *temp_custom_variablesmember; + + json_custom_variables = json_new_object(); + + for(temp_custom_variablesmember = custom_variables; + temp_custom_variablesmember != NULL; + temp_custom_variablesmember = temp_custom_variablesmember->next) { + json_object_append_string(json_custom_variables, + temp_custom_variablesmember->variable_name, &percent_escapes, + temp_custom_variablesmember->variable_value); + } + + return json_custom_variables; + } + +int json_object_host_passes_selection(host *temp_host, int use_parent_host, + host *parent_host, int use_child_host, host *child_host, + hostgroup *temp_hostgroup, contact *temp_contact, + contactgroup *temp_contactgroup, timeperiod *check_timeperiod, + timeperiod *notification_timeperiod, command *check_command, + command *event_handler) { + + host *temp_host2; + + /* Skip if user is not authorized for this host */ + if(FALSE == is_authorized_for_host(temp_host, ¤t_authdata)) { + return 0; + } + + /* If the host parent was specified, skip this host if it's parent is + not the parent host specified */ + if( 1 == use_parent_host && + FALSE == is_host_immediate_child_of_host(parent_host, temp_host)) { + return 0; + } + + /* If the hostgroup was specified, skip this host if it is not a member + of the hostgroup specified */ + if( NULL != temp_hostgroup && + ( FALSE == is_host_member_of_hostgroup(temp_hostgroup, + temp_host))) { + return 0; + } + + /* If the contact was specified, skip this host if it does not have + the contact specified */ + if( NULL != temp_contact && + ( FALSE == is_contact_for_host(temp_host, temp_contact))) { + return 0; + } + + /* If a contactgroup was specified, skip this host if it does not have + the contactgroup specified */ + if(NULL != temp_contactgroup && + (FALSE == is_contactgroup_for_host(temp_host, temp_contactgroup))) { + return 0; + } + + /* If a check timeperiod was specified, skip this host if it does not have + the check timeperiod specified */ + if(NULL != check_timeperiod && + (check_timeperiod != temp_host->check_period_ptr)) { + return 0; + } + + /* If a notification timeperiod was specified, skip this host if it + does not have the notification timeperiod specified */ + if(NULL != notification_timeperiod && + (notification_timeperiod != temp_host->notification_period_ptr)) { + return 0; + } + + /* If a check command was specified, skip this host if it does not + have the check command specified */ + if(NULL != check_command && + (check_command != temp_host->check_command_ptr)) { + return 0; + } + + /* If an event handler was specified, skip this host if it does not + have the event handler specified */ + if(NULL != event_handler && + (event_handler != temp_host->event_handler_ptr)) { + return 0; + } + + /* If a child host was specified... */ + if(1 == use_child_host) { + /* If the child host is "none", skip this host if it has children */ + if(NULL == child_host) { + for(temp_host2 = host_list; temp_host2 != NULL; + temp_host2 = temp_host2->next) { + if(TRUE == is_host_immediate_child_of_host(temp_host, + temp_host2)) { + return 0; + } + } + } + /* Otherwise, skip this host if it does not have the specified host + as a child */ + else if(FALSE == is_host_immediate_child_of_host(temp_host, child_host)) { + return 0; + } + } + + return 1; + } + +json_object * json_object_host_selectors(int start, int count, + int use_parent_host, host *parent_host, int use_child_host, + host *child_host, hostgroup *temp_hostgroup, contact *temp_contact, + contactgroup *temp_contactgroup, timeperiod *check_timeperiod, + timeperiod *notification_timeperiod, command *check_command, + command *event_handler) { + + json_object *json_selectors; + + json_selectors = json_new_object(); + if( start > 0) { + json_object_append_integer(json_selectors, "start", start); + } + if( count > 0) { + json_object_append_integer(json_selectors, "count", count); + } + if( 1 == use_parent_host) { + json_object_append_string(json_selectors, "parenthost", + &percent_escapes, + ( NULL == parent_host ? "none" : parent_host->name)); + } + if( 1 == use_child_host) { + json_object_append_string(json_selectors, "childhost", &percent_escapes, + ( NULL == child_host ? "none" : child_host->name)); + } + if( NULL != temp_hostgroup) { + json_object_append_string(json_selectors, "hostgroup", &percent_escapes, + temp_hostgroup->group_name); + } + if( NULL != temp_contact) { + json_object_append_string(json_selectors, "contact", &percent_escapes, + temp_contact->name); + } + if( NULL != temp_contactgroup) { + json_object_append_string(json_selectors, "contactgroup", + &percent_escapes, temp_contactgroup->group_name); + } + if( NULL != check_timeperiod) { + json_object_append_string(json_selectors, "checktimeperiod", + &percent_escapes, check_timeperiod->name); + } + if( NULL != notification_timeperiod) { + json_object_append_string(json_selectors, "hostnotificationtimeperiod", + &percent_escapes, notification_timeperiod->name); + } + if( NULL != check_command) { + json_object_append_string(json_selectors, "checkcommand", + &percent_escapes, check_command->name); + } + if( NULL != event_handler) { + json_object_append_string(json_selectors, "eventhandler", + &percent_escapes, event_handler->name); + } + + return json_selectors; + } + +json_object * json_object_hostcount(int use_parent_host, host *parent_host, + int use_child_host, host *child_host, hostgroup *temp_hostgroup, + contact *temp_contact, contactgroup *temp_contactgroup, + timeperiod *check_timeperiod, timeperiod *notification_timeperiod, + command *check_command, command *event_handler) { + + json_object *json_data; + host *temp_host; + int count = 0; + + json_data = json_new_object(); + json_object_append_object(json_data, "selectors", + json_object_host_selectors(0, 0, use_parent_host, parent_host, + use_child_host, child_host, temp_hostgroup, temp_contact, + temp_contactgroup, check_timeperiod, notification_timeperiod, + check_command, event_handler)); + + for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) { + + if(json_object_host_passes_selection(temp_host, use_parent_host, + parent_host, use_child_host, child_host, temp_hostgroup, + temp_contact, temp_contactgroup, check_timeperiod, + notification_timeperiod, check_command, event_handler) == 0) { + continue; + } + + count++; + } + json_object_append_integer(json_data, "count", count); + + return json_data; + } + +json_object * json_object_hostlist(unsigned format_options, int start, + int count, int details, int use_parent_host, host *parent_host, + int use_child_host, host *child_host, hostgroup *temp_hostgroup, + contact *temp_contact, contactgroup *temp_contactgroup, + timeperiod *check_timeperiod, timeperiod *notification_timeperiod, + command *check_command, command *event_handler) { + + json_object *json_data; + json_object *json_hostlist_object = NULL; + json_array *json_hostlist_array = NULL; + json_object *json_host_details; + host *temp_host; + int current = 0; + int counted = 0; + + json_data = json_new_object(); + json_object_append_object(json_data, "selectors", + json_object_host_selectors(start, count, use_parent_host, + parent_host, use_child_host, child_host, temp_hostgroup, + temp_contact, temp_contactgroup, check_timeperiod, + notification_timeperiod, check_command, event_handler)); + + if(details > 0) { + json_hostlist_object = json_new_object(); + } + else { + json_hostlist_array = json_new_array(); + } + + for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) { + + if(json_object_host_passes_selection(temp_host, use_parent_host, + parent_host, use_child_host, child_host, temp_hostgroup, + temp_contact, temp_contactgroup, check_timeperiod, + notification_timeperiod, check_command, event_handler) == 0) { + continue; + } + + /* If the current item passes the start and limit tests, display it */ + if( passes_start_and_count_limits(start, count, current, counted)) { + if( details > 0) { + json_host_details = json_new_object(); + json_object_host_details(json_host_details, format_options, + temp_host); + json_object_append_object(json_hostlist_object, temp_host->name, + json_host_details); + } + else { + json_array_append_string(json_hostlist_array, &percent_escapes, + temp_host->name); + } + counted++; + } + current++; + } + + if(details > 0) { + json_object_append_object(json_data, "hostlist", json_hostlist_object); + } + else { + json_object_append_array(json_data, "hostlist", json_hostlist_array); + } + + return json_data; + } + +json_object *json_object_host(unsigned format_options, host *temp_host) { + + json_object *json_host = json_new_object(); + json_object *json_details = json_new_object(); + + json_object_append_string(json_details, "name", &percent_escapes, + temp_host->name); + json_object_host_details(json_details, format_options, temp_host); + json_object_append_object(json_host, "host", json_details); + + return json_host; +} + +void json_object_host_details(json_object *json_details, unsigned format_options, + host *temp_host) { + + json_array *json_parent_hosts; + json_array *json_child_hosts; + json_array *json_services; + json_array *json_contactgroups; + json_array *json_contacts; + hostsmember *temp_hostsmember; + servicesmember *temp_servicesmember; + contactgroupsmember *temp_contact_groupsmember; +#ifdef NSCORE + contactsmember *temp_contactsmember; +#else + contact *temp_contact; +#endif + + json_object_append_string(json_details, "name", &percent_escapes, + temp_host->name); + json_object_append_string(json_details, "display_name", &percent_escapes, + temp_host->display_name); + json_object_append_string(json_details, "alias", &percent_escapes, + temp_host->alias); + json_object_append_string(json_details, "address", &percent_escapes, + temp_host->address); + + json_parent_hosts = json_new_array(); + for(temp_hostsmember = temp_host->parent_hosts; temp_hostsmember != NULL; + temp_hostsmember = temp_hostsmember->next) { + json_array_append_string(json_parent_hosts, &percent_escapes, + temp_hostsmember->host_name); + } + json_object_append_array(json_details, "parent_hosts", json_parent_hosts); + + json_child_hosts = json_new_array(); + for(temp_hostsmember = temp_host->child_hosts; temp_hostsmember != NULL; + temp_hostsmember = temp_hostsmember->next) { + json_array_append_string(json_child_hosts, &percent_escapes, + temp_hostsmember->host_name); + } + json_object_append_array(json_details, "child_hosts", json_child_hosts); + + json_services = json_new_array(); + for(temp_servicesmember = temp_host->services; temp_servicesmember != NULL; + temp_servicesmember = temp_servicesmember->next) { + json_array_append_string(json_services, &percent_escapes, + temp_servicesmember->service_description); + } + json_object_append_array(json_details, "services", json_services); + +#ifdef JSON_NAGIOS_4X + json_object_append_string(json_details, "check_command", &percent_escapes, + temp_host->check_command); +#else + json_object_append_string(json_details, "host_check_command", + &percent_escapes, temp_host->host_check_command); +#endif + + json_enumeration(json_details, format_options, "initial_state", + temp_host->initial_state, svm_host_states); + json_object_append_real(json_details, "check_interval", + temp_host->check_interval); + json_object_append_real(json_details, "retry_interval", + temp_host->retry_interval); + json_object_append_integer(json_details, "max_attempts", + temp_host->max_attempts); + json_object_append_string(json_details, "event_handler", &percent_escapes, + temp_host->event_handler); + + json_contactgroups = json_new_array(); + for(temp_contact_groupsmember = temp_host->contact_groups; + temp_contact_groupsmember != NULL; + temp_contact_groupsmember = temp_contact_groupsmember->next) { + json_array_append_string(json_contactgroups, &percent_escapes, + temp_contact_groupsmember->group_name); + } + json_object_append_array(json_details, "contact_groups", json_contactgroups); + + json_contacts = json_new_array(); +#ifdef NSCORE + for(temp_contactsmember = temp_host->contacts; + temp_contactsmember != NULL; + temp_contactsmember = temp_contactsmember->next) { + json_array_append_string(json_contacts, &percent_escapes, + temp_contactsmember->contact_name); + } +#else + for(temp_contact = contact_list; temp_contact != NULL; + temp_contact = temp_contact->next) { + if(TRUE == is_contact_for_host(temp_host, temp_contact)) { + json_array_append_string(json_contacts, &percent_escapes, + temp_contact->name); + } + } +#endif + json_object_append_array(json_details, "contacts", json_contacts); + + json_object_append_real(json_details, "notification_interval", + temp_host->notification_interval); + json_object_append_real(json_details, "first_notification_delay", + temp_host->first_notification_delay); +#ifdef JSON_NAGIOS_4X +#if 0 + if( CORE3_COMPATIBLE) { + json_object_append_boolean(json_details, "notify_on_down", + flag_isset(temp_host->notification_options, OPT_DOWN)); + json_object_append_boolean(json_details, "notify_on_unreachable", + flag_isset(temp_host->notification_options, OPT_UNREACHABLE)); + json_object_append_boolean(json_details, "notify_on_recovery", + flag_isset(temp_host->notification_options, OPT_RECOVERY)); + json_object_append_boolean(json_details, "notify_on_flapping", + flag_isset(temp_host->notification_options, OPT_FLAPPING)); + json_object_append_boolean(json_details, "notify_on_downtime", + flag_isset(temp_host->notification_options, OPT_DOWNTIME)); + } + else { +#endif + json_bitmask(json_details, format_options, "notifications_options", + temp_host->notification_options, svm_option_types); +#if 0 + } +#endif +#else + json_object_append_boolean(json_details, "notify_on_down", + temp_host->notify_on_down); + json_object_append_boolean(json_details, "notify_on_unreachable", + temp_host->notify_on_unreachable); + json_object_append_boolean(json_details, "notify_on_recovery", + temp_host->notify_on_recovery); + json_object_append_boolean(json_details, "notify_on_flapping", + temp_host->notify_on_flapping); + json_object_append_boolean(json_details, "notify_on_downtime", + temp_host->notify_on_downtime); +#endif + json_object_append_string(json_details, "notification_period", + &percent_escapes, temp_host->notification_period); + json_object_append_string(json_details, "check_period", &percent_escapes, + temp_host->check_period); + json_object_append_boolean(json_details, "flap_detection_enabled", + temp_host->flap_detection_enabled); + json_object_append_real(json_details, "low_flap_threshold", + temp_host->low_flap_threshold); + json_object_append_real(json_details, "high_flap_threshold", + temp_host->high_flap_threshold); +#ifdef JSON_NAGIOS_4X +#if 0 + if( CORE3_COMPATIBLE) { + json_object_append_boolean(json_details "flap_detection_on_up", + flag_isset(temp_host->flap_detection_options, OPT_UP)); + json_object_append_boolean(json_details "flap_detection_on_down", + flag_isset(temp_host->flap_detection_options, OPT_DOWN)); + json_object_append_boolean(json_details "flap_detection_on_unreachable", + flag_isset(temp_host->flap_detection_options, OPT_UNREACHABLE)); + } + else { +#endif + json_bitmask(json_details, format_options, "flap_detection_options", + temp_host->flap_detection_options, svm_option_types); +#if 0 + } +#endif +#else + json_object_append_boolean(json_details, "flap_detection_on_up", + temp_host->flap_detection_on_up); + json_object_append_boolean(json_details, "flap_detection_on_down", + temp_host->flap_detection_on_down); + json_object_append_boolean(json_details, "flap_detection_on_unreachable", + temp_host->flap_detection_on_unreachable); +#endif + +#ifdef JSON_NAGIOS_4X +#if 0 + if( CORE3_COMPATIBLE) { + json_object_append_boolean(json_details, "stalk_on_up", + flag_isset(temp_host->stalking_options, OPT_UP)); + json_object_append_boolean(json_details, "stalk_on_down", + flag_isset(temp_host->stalking_options, OPT_DOWN)); + json_object_append_boolean(json_details, "stalk_on_unreachable", + flag_isset(temp_host->stalking_options, OPT_UNREACHABLE)); + } + else { +#endif + json_bitmask(json_details, format_options, "stalking_options", + temp_host->stalking_options, svm_option_types); +#if 0 + } +#endif +#else + json_object_append_boolean(json_details, "stalk_on_up", + temp_host->stalk_on_up); + json_object_append_boolean(json_details, "stalk_on_down", + temp_host->stalk_on_down); + json_object_append_boolean(json_details, "stalk_on_unreachable", + temp_host->stalk_on_unreachable); +#endif + + json_object_append_boolean(json_details, "check_freshness", + temp_host->check_freshness); + json_object_append_integer(json_details, "freshness_threshold", + temp_host->freshness_threshold); + json_object_append_boolean(json_details, "process_performance_data", + temp_host->process_performance_data); + json_object_append_boolean(json_details, "checks_enabled", + temp_host->checks_enabled); +#ifdef JSON_NAGIOS_4X +#if 0 + if( CORE3_COMPATIBLE) { + json_object_append_boolean(json_details, "accept_passive_host_checks", + temp_host->accept_passive_checks); + } + else { +#endif + json_object_append_boolean(json_details, "accept_passive_checks", + temp_host->accept_passive_checks); +#if 0 + } +#endif +#else + json_object_append_boolean(json_details, "accept_passive_host_checks", + temp_host->accept_passive_host_checks); +#endif + json_object_append_boolean(json_details, "event_handler_enabled", + temp_host->event_handler_enabled); + json_object_append_boolean(json_details, "retain_status_information", + temp_host->retain_status_information); + json_object_append_boolean(json_details, "retain_nonstatus_information", + temp_host->retain_nonstatus_information); +#ifndef JSON_NAGIOS_4X + json_object_append_boolean(json_details, "failure_prediction_enabled", + temp_host->failure_prediction_enabled); + json_object_append_string(json_details, "failure_prediction_options", + NULL, temp_host->failure_prediction_options); +#endif +#ifdef JSON_NAGIOS_4X +#if 0 + if( CORE3_COMPATIBLE) { + json_object_append_boolean(json_details, "obsess_over_host", + temp_host->obsess); + } + else { +#endif + json_object_append_boolean(json_details, "obsess", temp_host->obsess); +#if 0 + } +#endif +#else + json_object_append_boolean(json_details, "obsess_over_host", + temp_host->obsess_over_host); +#endif +#ifdef JSON_NAGIOS_4X + json_object_append_integer(json_details, "hourly_value", + temp_host->hourly_value); +#endif + json_object_append_string(json_details, "notes", &percent_escapes, + temp_host->notes); + json_object_append_string(json_details, "notes_url", &percent_escapes, + temp_host->notes_url); + json_object_append_string(json_details, "action_url", &percent_escapes, + temp_host->action_url); + json_object_append_string(json_details, "icon_image", &percent_escapes, + temp_host->icon_image); + json_object_append_string(json_details, "icon_image_alt", &percent_escapes, + temp_host->icon_image_alt); + json_object_append_string(json_details, "vrml_image", &percent_escapes, + temp_host->vrml_image); + json_object_append_string(json_details, "statusmap_image", &percent_escapes, + temp_host->statusmap_image); + json_object_append_boolean(json_details, "have_2d_coords", + temp_host->have_2d_coords); + json_object_append_integer(json_details, "x_2d", temp_host->x_2d); + json_object_append_integer(json_details, "y_2d", temp_host->y_2d); + json_object_append_boolean(json_details, "have_3d_coords", + temp_host->have_3d_coords); + json_object_append_real(json_details, "x_3d", temp_host->x_3d); + json_object_append_real(json_details, "y_3d", temp_host->y_3d); + json_object_append_real(json_details, "z_3d", temp_host->z_3d); + json_object_append_boolean(json_details, "should_be_drawn", + temp_host->should_be_drawn); + json_object_append_object(json_details, "custom_variables", + json_object_custom_variables(temp_host->custom_variables)); + } + +int json_object_hostgroup_passes_selection(hostgroup *temp_hostgroup, + host *temp_hostgroup_member) { + + /* Skip if user is not authorized for this hostgroup */ + if(FALSE == is_authorized_for_hostgroup(temp_hostgroup, + ¤t_authdata)) { + return 0; + } + + /* Skip if a hostgroup member is specified and the hostgroup member + host is not a member of the hostgroup */ + if( NULL != temp_hostgroup_member && + ( FALSE == is_host_member_of_hostgroup(temp_hostgroup, + temp_hostgroup_member))) { + return 0; + } + + return 1; + } + +json_object *json_object_hostgroup_selectors(int start, int count, + host *temp_hostgroup_member) { + + json_object *json_selectors; + + json_selectors = json_new_object(); + + if( start > 0) { + json_object_append_integer(json_selectors, "start", start); + } + if( count > 0) { + json_object_append_integer(json_selectors, "count", count); + } + if( NULL != temp_hostgroup_member) { + json_object_append_string(json_selectors, "hostgroupmember", + &percent_escapes, temp_hostgroup_member->name); + } + + return json_selectors; + } + +json_object *json_object_hostgroupcount(unsigned format_options, + host *temp_hostgroup_member) { + + json_object *json_data; + hostgroup *temp_hostgroup; + int count = 0; + + json_data = json_new_object(); + json_object_append_object(json_data, "selectors", + json_object_hostgroup_selectors(0, 0, temp_hostgroup_member)); + + for(temp_hostgroup = hostgroup_list; temp_hostgroup != NULL; + temp_hostgroup = temp_hostgroup->next) { + + if(json_object_hostgroup_passes_selection(temp_hostgroup, + temp_hostgroup_member) == 0) { + continue; + } + + count++; + } + + json_object_append_integer(json_data, "count", count); + + return json_data; + } + +json_object *json_object_hostgrouplist(unsigned format_options, int start, + int count, int details, host *temp_hostgroup_member) { + + json_object *json_data; + json_object *json_hostgrouplist_object = NULL; + json_array *json_hostgrouplist_array = NULL; + json_object *json_hostgroup_details; + hostgroup *temp_hostgroup; + int current = 0; + int counted = 0; + + json_data = json_new_object(); + json_object_append_object(json_data, "selectors", + json_object_hostgroup_selectors(start, count, + temp_hostgroup_member)); + + if(details > 0) { + json_hostgrouplist_object = json_new_object(); + } + else { + json_hostgrouplist_array = json_new_array(); + } + + for(temp_hostgroup = hostgroup_list; temp_hostgroup != NULL; + temp_hostgroup = temp_hostgroup->next) { + + if(json_object_hostgroup_passes_selection(temp_hostgroup, + temp_hostgroup_member) == 0) { + continue; + } + + /* If the current item passes the start and limit tests, display it */ + if( passes_start_and_count_limits(start, count, current, counted)) { + if( details > 0) { + json_hostgroup_details = json_new_object(); + json_object_hostgroup_details(json_hostgroup_details, + format_options, temp_hostgroup); + json_object_append_object(json_hostgrouplist_object, + temp_hostgroup->group_name, json_hostgroup_details); + } + else { + json_array_append_string(json_hostgrouplist_array, + &percent_escapes, temp_hostgroup->group_name); + } + counted++; + } + current++; + } + + if(details > 0) { + json_object_append_object(json_data, "hostgrouplist", + json_hostgrouplist_object); + } + else { + json_object_append_array(json_data, "hostgrouplist", + json_hostgrouplist_array); + } + + return json_data; + } + +json_object *json_object_hostgroup(unsigned format_options, + hostgroup *temp_hostgroup) { + + json_object *json_hostgroup = json_new_object(); + json_object *json_details = json_new_object(); + + json_object_append_string(json_details, "group_name", &percent_escapes, + temp_hostgroup->group_name); + json_object_hostgroup_details(json_details, format_options, temp_hostgroup); + json_object_append_object(json_hostgroup, "hostgroup", json_details); + + return json_hostgroup; +} + +void json_object_hostgroup_details(json_object *json_details, + unsigned format_options, hostgroup *temp_hostgroup) { + + json_array *json_members; + hostsmember *temp_member; + + json_object_append_string(json_details, "group_name", &percent_escapes, + temp_hostgroup->group_name); + json_object_append_string(json_details, "alias", &percent_escapes, + temp_hostgroup->alias); + + json_members = json_new_array(); + for(temp_member = temp_hostgroup->members; temp_member != NULL; + temp_member = temp_member->next) { + json_array_append_string(json_members, &percent_escapes, + temp_member->host_name); + } + json_object_append_array(json_details, "members", json_members); + + json_object_append_string(json_details, "notes", &percent_escapes, + temp_hostgroup->notes); + json_object_append_string(json_details, "notes_url", &percent_escapes, + temp_hostgroup->notes_url); + json_object_append_string(json_details, "action_url", &percent_escapes, + temp_hostgroup->action_url); + } + +int json_object_service_passes_host_selection(host *temp_host, + int use_parent_host, host *parent_host, int use_child_host, + host *child_host, hostgroup *temp_hostgroup, host *match_host) { + + host *temp_host2; + + /* Skip if user is not authorized for this host */ + if(FALSE == is_authorized_for_host(temp_host, ¤t_authdata)) { + return 0; + } + + /* If the host parent was specified, skip the services whose host is + not a child of the parent host specified */ + if( 1 == use_parent_host && NULL != temp_host && + FALSE == is_host_immediate_child_of_host(parent_host, temp_host)) { + return 0; + } + + /* If the hostgroup was specified, skip the services on hosts that + are not members of the hostgroup specified */ + if( NULL != temp_hostgroup && NULL != temp_host && + ( FALSE == is_host_member_of_hostgroup(temp_hostgroup, + temp_host))) { + return 0; + } + + /* If the host was specified, skip the services not on the host + specified */ + if( NULL != match_host && NULL != temp_host && temp_host != match_host) { + return 0; + } + + /* If a child host was specified... */ + if(1 == use_child_host) { + /* If the child host is "none", skip this host if it has children */ + if(NULL == child_host) { + for(temp_host2 = host_list; temp_host2 != NULL; + temp_host2 = temp_host2->next) { + if(TRUE == is_host_immediate_child_of_host(temp_host, + temp_host2)) { + return 0; + } + } + } + /* Otherwise, skip this host if it does not have the specified host + as a child */ + else if(FALSE == is_host_immediate_child_of_host(temp_host, child_host)) { + return 0; + } + } + + return 1; + } + +int json_object_service_passes_service_selection(service *temp_service, + servicegroup *temp_servicegroup, contact *temp_contact, + char *service_description, char *parent_service_name, + char *child_service_name, contactgroup *temp_contactgroup, + timeperiod *check_timeperiod, timeperiod *notification_timeperiod, + command *check_command, command *event_handler) { + + servicesmember *temp_servicesmember; + + /* Skip if user is not authorized for this service */ + if(FALSE == is_authorized_for_service(temp_service, ¤t_authdata)) { + return 0; + } + + /* If the servicegroup was specified, skip the services that are not + members of the servicegroup specified */ + if( NULL != temp_servicegroup && + ( FALSE == is_service_member_of_servicegroup(temp_servicegroup, + temp_service))) { + return 0; + } + + /* If the contact was specified, skip the services that do not have + the contact specified */ + if( NULL != temp_contact && + ( FALSE == is_contact_for_service(temp_service, temp_contact))) { + return 0; + } + + /* If a contactgroup was specified, skip the services that do not have + the contactgroup specified */ + if(NULL != temp_contactgroup && + (FALSE == is_contactgroup_for_service(temp_service, + temp_contactgroup))) { + return 0; + } + + /* If the service description was supplied, skip the services that do not + have this service description */ + if((NULL != service_description) && + strcmp(temp_service->description, service_description)) { + return 0; + } + + /* If a check timeperiod was specified, skip this service if it does + not have the check timeperiod specified */ + if(NULL != check_timeperiod && + (check_timeperiod != temp_service->check_period_ptr)) { + return 0; + } + + /* If a notification timeperiod was specified, skip this service if it does + not have the notification timeperiod specified */ + if(NULL != notification_timeperiod && (notification_timeperiod != + temp_service->notification_period_ptr)) { + return 0; + } + + /* If a check command was specified, skip this service if it does not + have the check command specified */ + if(NULL != check_command && + (check_command != temp_service->check_command_ptr)) { + return 0; + } + + /* If an event handler was specified, skip this service if it does not + have the event handler specified */ + if(NULL != event_handler && + (event_handler != temp_service->event_handler_ptr)) { + return 0; + } + + /* If a parent service was specified... */ + if(NULL != parent_service_name) { + /* If the parent service is "none", skip this service if it has + parentren */ + if(!strcmp(parent_service_name,"none")) { + if(NULL != temp_service->parents) { + return 0; + } + } + /* Otherwise, skip this service if it does not have the specified + service as a parent */ + else { + int found = 0; + for(temp_servicesmember = temp_service->parents; + temp_servicesmember != NULL; + temp_servicesmember = temp_servicesmember->next) { + if(!strcmp(temp_servicesmember->service_description, + parent_service_name)) { + found = 1; + } + } + if(0 == found) { + return 0; + } + } + } + + /* If a child service was specified... */ + if(NULL != child_service_name) { + /* If the child service is "none", skip this service if it has + children */ + if(!strcmp(child_service_name,"none")) { + if(NULL != temp_service->children) { + return 0; + } + } + /* Otherwise, skip this service if it does not have the specified + service as a child */ + else { + int found = 0; + for(temp_servicesmember = temp_service->children; + temp_servicesmember != NULL; + temp_servicesmember = temp_servicesmember->next) { + if(!strcmp(temp_servicesmember->service_description, + child_service_name)) { + found = 1; + } + } + if(0 == found) { + return 0; + } + } + } + + return 1; + } + +json_object *json_object_service_selectors(int start, int count, + int use_parent_host, host *parent_host, int use_child_host, + host *child_host, hostgroup *temp_hostgroup, host *match_host, + servicegroup *temp_servicegroup, contact *temp_contact, + char *service_description, char *parent_service_name, + char *child_service_name, contactgroup *temp_contactgroup, + timeperiod *check_timeperiod, timeperiod *notification_timeperiod, + command *check_command, command *event_handler) { + + json_object *json_selectors; + + json_selectors = json_new_object(); + + if( start > 0) { + json_object_append_integer(json_selectors, "start", start); + } + if( count > 0) { + json_object_append_integer(json_selectors, "count", count); + } + if( NULL != match_host) { + json_object_append_string(json_selectors, "host", &percent_escapes, + match_host->name); + } + if( 1 == use_parent_host) { + json_object_append_string(json_selectors, "parenthost", + &percent_escapes, + ( NULL == parent_host ? "none" : parent_host->name)); + } + if( 1 == use_child_host) { + json_object_append_string(json_selectors, "childhost", &percent_escapes, + ( NULL == child_host ? "none" : child_host->name)); + } + if( NULL != temp_hostgroup) { + json_object_append_string(json_selectors, "hostgroup", &percent_escapes, + temp_hostgroup->group_name); + } + if( NULL != temp_servicegroup) { + json_object_append_string(json_selectors, "servicegroup", &percent_escapes, + temp_servicegroup->group_name); + } + if(NULL != temp_contact) { + json_object_append_string(json_selectors, "contact",&percent_escapes, + temp_contact->name); + } + if(NULL != temp_contactgroup) { + json_object_append_string(json_selectors, "contactgroup", + &percent_escapes, temp_contactgroup->group_name); + } + if( NULL != service_description) { + json_object_append_string(json_selectors, "servicedescription", + &percent_escapes, service_description); + } + if( NULL != parent_service_name) { + json_object_append_string(json_selectors, "parentservice", + &percent_escapes, parent_service_name); + } + if( NULL != child_service_name) { + json_object_append_string(json_selectors, "childservice", + &percent_escapes, child_service_name); + } + if( NULL != check_timeperiod) { + json_object_append_string(json_selectors, "checktimeperiod", + &percent_escapes, check_timeperiod->name); + } + if( NULL != notification_timeperiod) { + json_object_append_string(json_selectors, + "servicenotificationtimeperiod", &percent_escapes, + notification_timeperiod->name); + } + if( NULL != check_command) { + json_object_append_string(json_selectors, "checkcommand", + &percent_escapes, check_command->name); + } + if( NULL != event_handler) { + json_object_append_string(json_selectors, "eventhandler", + &percent_escapes, event_handler->name); + } + + return json_selectors; + } + +json_object *json_object_servicecount(host *match_host, int use_parent_host, + host *parent_host, int use_child_host, host *child_host, + hostgroup *temp_hostgroup, servicegroup *temp_servicegroup, + contact *temp_contact, char *service_description, + char *parent_service_name, char *child_service_name, + contactgroup *temp_contactgroup, timeperiod *check_timeperiod, + timeperiod *notification_timeperiod, command *check_command, + command *event_handler) { + + json_object *json_data; + host *temp_host; + service *temp_service; + int count = 0; + + json_data = json_new_object(); + json_object_append_object(json_data, "selectors", + json_object_service_selectors(0, 0, use_parent_host, parent_host, + use_child_host, child_host, temp_hostgroup, match_host, + temp_servicegroup, temp_contact, service_description, + parent_service_name, child_service_name, temp_contactgroup, + check_timeperiod, notification_timeperiod, check_command, + event_handler)); + + for(temp_service = service_list; temp_service != NULL; + temp_service = temp_service->next) { + + temp_host = find_host(temp_service->host_name); + if(NULL == temp_host) { + continue; + } + + if(json_object_service_passes_host_selection(temp_host, + use_parent_host, parent_host, use_child_host, child_host, + temp_hostgroup, match_host) == 0) { + continue; + } + + if(json_object_service_passes_service_selection(temp_service, + temp_servicegroup, temp_contact, service_description, + parent_service_name, child_service_name, + temp_contactgroup, check_timeperiod, + notification_timeperiod, check_command, event_handler) == 0) { + continue; + } + + count++; + } + + json_object_append_integer(json_data, "count", count); + + return json_data; + } + +json_object *json_object_servicelist(unsigned format_options, int start, + int count, int details, host *match_host, int use_parent_host, + host *parent_host, int use_child_host, host *child_host, + hostgroup *temp_hostgroup, servicegroup *temp_servicegroup, + contact *temp_contact, char *service_description, + char *parent_service_name, char *child_service_name, + contactgroup *temp_contactgroup, timeperiod *check_timeperiod, + timeperiod *notification_timeperiod, command *check_command, + command *event_handler) { + + json_object *json_data; + json_object *json_hostlist; + json_object *json_servicelist_object = NULL; + json_array *json_servicelist_array = NULL; + json_object *json_service_details; + host *temp_host; + service *temp_service; + int current = 0; + int counted = 0; + int service_count; + char *buf; + + json_data = json_new_object(); + json_object_append_object(json_data, "selectors", + json_object_service_selectors(start, count, use_parent_host, + parent_host, use_child_host, child_host, temp_hostgroup, match_host, + temp_servicegroup, temp_contact, service_description, + parent_service_name, child_service_name, temp_contactgroup, + check_timeperiod, notification_timeperiod, check_command, + event_handler)); + + json_hostlist = json_new_object(); + + for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) { + if(json_object_service_passes_host_selection(temp_host, use_parent_host, + parent_host, use_child_host, child_host, temp_hostgroup, + match_host) == 0) { + continue; + } + + service_count = 0; + if(details > 0) { + json_servicelist_object = json_new_object(); + } + else { + json_servicelist_array = json_new_array(); + } + + for(temp_service = service_list; temp_service != NULL; + temp_service = temp_service->next) { + + if(json_object_service_passes_service_selection(temp_service, + temp_servicegroup, temp_contact, + service_description, parent_service_name, + child_service_name, temp_contactgroup, + check_timeperiod, notification_timeperiod, + check_command, event_handler) == 0) { + continue; + } + + /* If this service isn't on the host we're currently working with, + skip it */ + if( strcmp( temp_host->name, temp_service->host_name)) continue; + + /* If the current item passes the start and limit tests, display it */ + if( passes_start_and_count_limits(start, count, current, counted)) { + if( details > 0) { + json_service_details = json_new_object(); + json_object_service_details(json_service_details, + format_options, temp_service); + asprintf(&buf, "%s", + temp_service->description); + json_object_append_object(json_servicelist_object, buf, + json_service_details); + } + else { + json_array_append_string(json_servicelist_array, + &percent_escapes, temp_service->description); + } + counted++; + service_count++; + } + current++; + } + + if(service_count > 0) { + if(details > 0) { + json_object_append_object(json_hostlist, temp_host->name, + json_servicelist_object); + } + else { + json_object_append_array(json_hostlist, temp_host->name, + json_servicelist_array); + } + } + } + + json_object_append_object(json_data, "servicelist", json_hostlist); + return json_data; + } + +json_object *json_object_service(unsigned format_options, service *temp_service) { + + json_object *json_service = json_new_object(); + json_object *json_details = json_new_object(); + +/* host_name and description are included when json_object_service_details() + is called, so we don't need them here */ +/* + json_object_append_string(json_details, "host_name", &percent_escapes, + temp_service->host_name); + json_object_append_string(json_details, "description", &percent_escapes, + temp_service->description); + */ + json_object_service_details(json_details, format_options, temp_service); + json_object_append_object(json_service, "service", json_details); + + return json_service; +} + +void json_object_service_details(json_object *json_details, + unsigned format_options, service *temp_service) { + + json_array *json_contactgroups; + json_array *json_contacts; + contactgroupsmember *temp_contact_groupsmember; +#ifdef NSCORE + contactsmember *temp_contactsmember; +#else + contact *temp_contact; +#endif +#ifdef JSON_NAGIOS_4X + servicesmember *temp_servicesmember; + json_object *json_parent_service; + json_array *json_parent_services; + json_object *json_child_service; + json_array *json_child_services; +#endif + + json_object_append_string(json_details, "host_name", &percent_escapes, + temp_service->host_name); + json_object_append_string(json_details, "description", &percent_escapes, + temp_service->description); + json_object_append_string(json_details, "display_name", &percent_escapes, + temp_service->display_name); +#ifdef JSON_NAGIOS_4X +#if 0 + if( CORE3_COMPATIBLE) { + json_object_append_string(json_details, "service_check_command", + &percent_escapes, temp_service->check_command); + } + else { +#endif + json_object_append_string(json_details, "check_command", + &percent_escapes, temp_service->check_command); +#if 0 + } +#endif +#else + json_object_append_string(json_details, "service_check_command", + &percent_escapes, temp_service->service_check_command); +#endif + json_object_append_string(json_details, "event_handler", &percent_escapes, + temp_service->event_handler); + + json_enumeration(json_details, format_options, "initial_state", + temp_service->initial_state, svm_service_states); + + json_object_append_real(json_details, "check_interval", + temp_service->check_interval); + json_object_append_real(json_details, "retry_interval", + temp_service->retry_interval); + json_object_append_integer(json_details, "max_attempts", + temp_service->max_attempts); + json_object_append_boolean(json_details, "parallelize", + temp_service->parallelize); + + json_contactgroups = json_new_array(); + for(temp_contact_groupsmember = temp_service->contact_groups; + temp_contact_groupsmember != NULL; + temp_contact_groupsmember = temp_contact_groupsmember->next) { + json_array_append_string(json_contactgroups, &percent_escapes, + temp_contact_groupsmember->group_name); + } + json_object_append_array(json_details, "contact_groups", json_contactgroups); + + json_contacts = json_new_array(); +#ifdef NSCORE + for(temp_contactsmember = temp_service->contacts; + temp_contactsmember != NULL; + temp_contactsmember = temp_contactsmember->next) { + json_array_append_string(json_contacts, &percent_escapes, + temp_contactsmember->contact_name); + } +#else + for(temp_contact = contact_list; temp_contact != NULL; + temp_contact = temp_contact->next) { + if(TRUE == is_contact_for_service(temp_service, temp_contact)) { + json_array_append_string(json_contacts, &percent_escapes, + temp_contact->name); + } + } +#endif + json_object_append_array(json_details, "contacts", json_contacts); + + json_object_append_real(json_details, "notification_interval", + temp_service->notification_interval); + json_object_append_real(json_details, "first_notification_delay", + temp_service->first_notification_delay); + +#ifdef JSON_NAGIOS_4X +#if 0 + if( CORE3_COMPATIBLE) { + json_object_append_boolean(json_details, "notify_on_unknown", + flag_isset(temp_service->notification_options, OPT_UNKNOWN)); + json_object_append_boolean(json_details, "notify_on_warning", + flag_isset(temp_service->notification_options, OPT_WARNING)); + json_object_append_boolean(json_details, "notify_on_critical", + flag_isset(temp_service->notification_options, OPT_CRITICAL)); + json_object_append_boolean(json_details, "notify_on_recovery", + flag_isset(temp_service->notification_options, OPT_RECOVERY)); + json_object_append_boolean(json_details, "notify_on_flapping", + flag_isset(temp_service->notification_options, OPT_FLAPPING)); + json_object_append_boolean(json_details, "notify_on_downtime", + flag_isset(temp_service->notification_options, OPT_DOWNTIME)); + } + else { +#endif + json_bitmask(json_details, format_options, "notifications_options", + temp_service->notification_options, svm_option_types); +#if 0 + } +#endif +#else + json_object_append_boolean(json_details, "notify_on_unknown", + temp_service->notify_on_unknown); + json_object_append_boolean(json_details, "notify_on_warning", + temp_service->notify_on_warning); + json_object_append_boolean(json_details, "notify_on_critical", + temp_service->notify_on_critical); + json_object_append_boolean(json_details, "notify_on_recovery", + temp_service->notify_on_recovery); + json_object_append_boolean(json_details, "notify_on_flapping", + temp_service->notify_on_flapping); + json_object_append_boolean(json_details, "notify_on_downtime", + temp_service->notify_on_downtime); +#endif + +#ifdef JSON_NAGIOS_4X +#if 0 + if( CORE3_COMPATIBLE) { + json_object_append_boolean(json_details, "stalk_on_ok", + flag_isset(temp_service->stalking_options, OPT_OK)); + json_object_append_boolean(json_details, "stalk_on_warning", + flag_isset(temp_service->stalking_options, OPT_WARNING)); + json_object_append_boolean(json_details, "stalk_on_unknown", + flag_isset(temp_service->stalking_options, OPT_UNKNOWN)); + json_object_append_boolean(json_details, "stalk_on_critical", + flag_isset(temp_service->stalking_options, OPT_CRITICAL)); + } + else { +#endif + json_bitmask(json_details, format_options, "stalking_options", + temp_service->stalking_options, svm_option_types); +#if 0 + } +#endif +#else + json_object_append_boolean(json_details, "stalk_on_ok", + temp_service->stalk_on_ok); + json_object_append_boolean(json_details, "stalk_on_warning", + temp_service->stalk_on_warning); + json_object_append_boolean(json_details, "stalk_on_unknown", + temp_service->stalk_on_unknown); + json_object_append_boolean(json_details, "stalk_on_critical", + temp_service->stalk_on_critical); +#endif + + json_object_append_boolean(json_details, "is_volatile", + temp_service->is_volatile); + json_object_append_string(json_details, "notification_period", + &percent_escapes, temp_service->notification_period); + json_object_append_string(json_details, "check_period", &percent_escapes, + temp_service->check_period); + json_object_append_boolean(json_details, "flap_detection_enabled", + temp_service->flap_detection_enabled); + json_object_append_real(json_details, "low_flap_threshold", + temp_service->low_flap_threshold); + json_object_append_real(json_details, "high_flap_threshold", + temp_service->high_flap_threshold); + +#ifdef JSON_NAGIOS_4X +#if 0 + if( CORE3_COMPATIBLE) { + json_object_append_boolean(json_details, "flap_detection_on_ok", + flag_isset(temp_service->flap_detection_options, OPT_OK)); + json_object_append_boolean(json_details, "flap_detection_on_warning", + flag_isset(temp_service->flap_detection_options, OPT_WARNING)); + json_object_append_boolean(json_details, "flap_detection_on_unknown", + flag_isset(temp_service->flap_detection_options, OPT_UNKNOWN)); + json_object_append_boolean(json_details, "flap_detection_on_critical", + flag_isset(temp_service->flap_detection_options, OPT_CRITICAL)); + } + else { +#endif + json_bitmask(json_details, format_options, "flap_detection_options", + temp_service->flap_detection_options, svm_option_types); +#if 0 + } +#endif +#else + json_object_append_boolean(json_details, "flap_detection_on_ok", + temp_service->flap_detection_on_ok); + json_object_append_boolean(json_details, "flap_detection_on_warning", + temp_service->flap_detection_on_warning); + json_object_append_boolean(json_details, "flap_detection_on_unknown", + temp_service->flap_detection_on_unknown); + json_object_append_boolean(json_details, "flap_detection_on_critical", + temp_service->flap_detection_on_critical); +#endif + + json_object_append_boolean(json_details, "process_performance_data", + temp_service->process_performance_data); + json_object_append_boolean(json_details, "check_freshness", + temp_service->check_freshness); + json_object_append_integer(json_details, "freshness_threshold", + temp_service->freshness_threshold); +#ifdef JSON_NAGIOS_4X +#if 0 + if( CORE3_COMPATIBLE) { + json_object_append_boolean(json_details, + "accept_passive_service_checks", + temp_service->accept_passive_checks); + } + else { +#endif + json_object_append_boolean(json_details, "accept_passive_checks", + temp_service->accept_passive_checks); +#if 0 + } +#endif +#else + json_object_append_boolean(json_details, "accept_passive_service_checks", + temp_service->accept_passive_service_checks); +#endif + json_object_append_boolean(json_details, "event_handler_enabled", + temp_service->event_handler_enabled); + json_object_append_boolean(json_details, "checks_enabled", + temp_service->checks_enabled); + json_object_append_boolean(json_details, "retain_status_information", + temp_service->retain_status_information); + json_object_append_boolean(json_details, "retain_nonstatus_information", + temp_service->retain_nonstatus_information); + json_object_append_boolean(json_details, "notifications_enabled", + temp_service->notifications_enabled); +#ifdef JSON_NAGIOS_4X +#if 0 + if( CORE3_COMPATIBLE) { + json_object_append_boolean(json_details, "obsess_over_service", + temp_service->obsess); + } + else { +#endif + json_object_append_boolean(json_details, "obsess", temp_service->obsess); +#if 0 + } +#endif +#else + json_object_append_boolean(json_details, "obsess_over_service", + temp_service->obsess_over_service); +#endif +#ifndef JSON_NAGIOS_4X + json_object_append_boolean(json_details, "failure_prediction_enabled", + temp_service->failure_prediction_enabled); + json_object_append_string(json_details, "failure_prediction_options", + NULL, temp_service->failure_prediction_options); +#endif +#ifdef JSON_NAGIOS_4X + json_object_append_integer(json_details, "hourly_value", + temp_service->hourly_value); +#endif + +#ifdef JSON_NAGIOS_4X + json_parent_services = json_new_array(); + for(temp_servicesmember = temp_service->parents; + temp_servicesmember != NULL; + temp_servicesmember = temp_servicesmember->next) { + json_parent_service = json_new_object(); + json_object_append_string(json_parent_service, "host_name", + &percent_escapes, temp_servicesmember->host_name); + json_object_append_string(json_parent_service, "service_description", + &percent_escapes, temp_servicesmember->service_description); + json_array_append_object(json_parent_services, json_parent_service); + } + json_object_append_array(json_details, "parents", json_parent_services); + + json_child_services = json_new_array(); + for(temp_servicesmember = temp_service->children; + temp_servicesmember != NULL; + temp_servicesmember = temp_servicesmember->next) { + json_child_service = json_new_object(); + json_object_append_string(json_child_service, "host_name", + &percent_escapes, temp_servicesmember->host_name); + json_object_append_string(json_child_service, "service_description", + &percent_escapes, temp_servicesmember->service_description); + json_array_append_object(json_child_services, json_child_service); + } + json_object_append_array(json_details, "children", json_child_services); +#endif + + json_object_append_string(json_details, "notes", &percent_escapes, + temp_service->notes); + json_object_append_string(json_details, "notes_url", &percent_escapes, + temp_service->notes_url); + json_object_append_string(json_details, "action_url", &percent_escapes, + temp_service->action_url); + json_object_append_string(json_details, "icon_image", &percent_escapes, + temp_service->icon_image); + json_object_append_string(json_details, "icon_image_alt", &percent_escapes, + temp_service->icon_image_alt); + json_object_append_object(json_details, "custom_variables", + json_object_custom_variables(temp_service->custom_variables)); + } + +int json_object_servicegroup_passes_selection(servicegroup *temp_servicegroup, + service *temp_servicegroup_member) { + + /* Skip if user is not authorized for this hostgroup */ + if(FALSE == is_authorized_for_servicegroup(temp_servicegroup, + ¤t_authdata)) { + return 0; + } + + /* Skip if a servicegroup member is specified and the servicegroup + member service is not a member of the servicegroup */ + if( NULL != temp_servicegroup_member && + ( FALSE == is_service_member_of_servicegroup(temp_servicegroup, + temp_servicegroup_member))) { + return 0; + } + + return 1; + } + +json_object * json_object_servicegroup_selectors(int start, int count, + service *temp_servicegroup_member) { + + json_object *json_selectors; + + json_selectors = json_new_object(); + + if( start > 0) { + json_object_append_integer(json_selectors, "start", start); + } + if( count > 0) { + json_object_append_integer(json_selectors, "count", count); + } + if( NULL != temp_servicegroup_member) { + json_object_append_string(json_selectors, "servicegroupmemberhost", + &percent_escapes, temp_servicegroup_member->host_name); + json_object_append_string(json_selectors, "servicegroupmemberservice", + &percent_escapes, temp_servicegroup_member->description); + } + + return json_selectors; + } + +json_object *json_object_servicegroupcount(service *temp_servicegroup_member) { + + json_object *json_data; + servicegroup *temp_servicegroup; + int count = 0; + + json_data = json_new_object(); + json_object_append_object(json_data, "selectors", + json_object_servicegroup_selectors(0, 0, + temp_servicegroup_member)); + + for(temp_servicegroup = servicegroup_list; temp_servicegroup != NULL; + temp_servicegroup = temp_servicegroup->next) { + + if(json_object_servicegroup_passes_selection(temp_servicegroup, + temp_servicegroup_member) == 0) { + continue; + } + + count++; + } + + json_object_append_integer(json_data, "count", count); + + return json_data; + } + +json_object *json_object_servicegrouplist(unsigned format_options, int start, + int count, int details, service *temp_servicegroup_member) { + + json_object *json_data; + json_object *json_servicegrouplist_object = NULL; + json_array *json_servicegrouplist_array = NULL; + json_object *json_servicegroup_details; + servicegroup *temp_servicegroup; + int current = 0; + int counted = 0; + + json_data = json_new_object(); + json_object_append_object(json_data, "selectors", + json_object_servicegroup_selectors(start, count, + temp_servicegroup_member)); + + if(details > 0) { + json_servicegrouplist_object = json_new_object(); + } + else { + json_servicegrouplist_array = json_new_array(); + } + + for(temp_servicegroup = servicegroup_list; temp_servicegroup != NULL; + temp_servicegroup = temp_servicegroup->next) { + + if(json_object_servicegroup_passes_selection(temp_servicegroup, + temp_servicegroup_member) == 0) { + continue; + } + + /* If the current item passes the start and limit tests, display it */ + if( passes_start_and_count_limits(start, count, current, counted)) { + if( details > 0) { + json_servicegroup_details = json_new_object(); + json_object_servicegroup_details(json_servicegroup_details, + format_options, temp_servicegroup); + json_object_append_object(json_servicegrouplist_object, + temp_servicegroup->group_name, + json_servicegroup_details); + } + else { + json_object_append_string(json_servicegrouplist_array, NULL, + &percent_escapes, temp_servicegroup->group_name); + } + counted++; + } + current++; + } + + if(details > 0) { + json_object_append_object(json_data, "servicegrouplist", + json_servicegrouplist_object); + } + else { + json_object_append_array(json_data, "servicegrouplist", + json_servicegrouplist_array); + } + + return json_data; + } + +json_object * json_object_servicegroup(unsigned format_options, + servicegroup *temp_servicegroup) { + + json_object *json_servicegroup = json_new_object(); + json_object *json_details = json_new_object(); + + json_object_append_string(json_details, "group_name", + &percent_escapes, temp_servicegroup->group_name); + json_object_servicegroup_details(json_details, format_options, + temp_servicegroup); + json_object_append_object(json_servicegroup, "servicegroup", json_details); + + return json_servicegroup; +} + +void json_object_servicegroup_details(json_object *json_details, + unsigned format_options, servicegroup *temp_servicegroup) { + + json_array *json_members; + servicesmember *temp_member; + json_object *json_member; + + json_object_append_string(json_details, "group_name", &percent_escapes, + temp_servicegroup->group_name); + json_object_append_string(json_details, "alias", &percent_escapes, + temp_servicegroup->alias); + + json_members = json_new_array(); + for(temp_member = temp_servicegroup->members; temp_member != NULL; + temp_member = temp_member->next) { + json_member = json_new_object(); + json_object_append_string(json_member, "host_name", &percent_escapes, + temp_member->host_name); + json_object_append_string(json_member, "service_description", + &percent_escapes, temp_member->service_description); + json_array_append_object(json_members, json_member); + } + json_object_append_array(json_details, "members", json_members); + + json_object_append_string(json_details, "notes", &percent_escapes, + temp_servicegroup->notes); + json_object_append_string(json_details, "notes_url", &percent_escapes, + temp_servicegroup->notes_url); + json_object_append_string(json_details, "action_url", &percent_escapes, + temp_servicegroup->action_url); + } + +int json_object_contact_passes_selection(contact *temp_contact, + contactgroup *temp_contactgroup, + timeperiod *host_notification_timeperiod, + timeperiod *service_notification_timeperiod) { + + /* If the contactgroup was specified, skip the contacts that are not + members of the contactgroup specified */ + if( NULL != temp_contactgroup && + ( FALSE == is_contact_member_of_contactgroup(temp_contactgroup, + temp_contact))) { + return 0; + } + + /* If a host notification timeperiod was specified, skip this contact + if it does not have the host notification timeperiod specified */ + if(NULL != host_notification_timeperiod && (host_notification_timeperiod != + temp_contact->host_notification_period_ptr)) { + return 0; + } + + /* If a service notification timeperiod was specified, skip this contact + if it does not have the service notification timeperiod specified */ + if(NULL != service_notification_timeperiod && + (service_notification_timeperiod != + temp_contact->service_notification_period_ptr)) { + return 0; + } + + return 1; + } + +json_object *json_object_contact_display_selectors(int start, int count, + contactgroup *temp_contactgroup, + timeperiod *host_notification_timeperiod, + timeperiod *service_notification_timeperiod) { + + json_object *json_selectors; + + json_selectors = json_new_object(); + + if( start > 0) { + json_object_append_integer(json_selectors, "start", start); + } + if( count > 0) { + json_object_append_integer(json_selectors, "count", count); + } + if( NULL != temp_contactgroup) { + json_object_append_string(json_selectors, "contactgroup", + &percent_escapes, temp_contactgroup->group_name); + } + if( NULL != host_notification_timeperiod) { + json_object_append_string(json_selectors, "hostnotificationtimeperiod", + &percent_escapes, host_notification_timeperiod->name); + } + if( NULL != service_notification_timeperiod) { + json_object_append_string(json_selectors, + "servicenotificationtimeperiod", &percent_escapes, + service_notification_timeperiod->name); + } + + return json_selectors; + } + +json_object *json_object_contactcount(contactgroup *temp_contactgroup, + timeperiod *host_notification_timeperiod, + timeperiod *service_notification_timeperiod) { + + json_object *json_data; + contact *temp_contact; + int count = 0; + + json_data = json_new_object(); + json_object_append_object(json_data, "selectors", + json_object_contact_display_selectors(0, 0, temp_contactgroup, + host_notification_timeperiod, service_notification_timeperiod)); + + for(temp_contact = contact_list; temp_contact != NULL; + temp_contact = temp_contact->next) { + + if(json_object_contact_passes_selection(temp_contact, + temp_contactgroup, host_notification_timeperiod, + service_notification_timeperiod) == 0) { + continue; + } + + count++; + } + + json_object_append_integer(json_data, "count", count); + + return json_data; + } + +json_object *json_object_contactlist(unsigned format_options, int start, + int count, int details, contactgroup *temp_contactgroup, + timeperiod *host_notification_timeperiod, + timeperiod *service_notification_timeperiod) { + + json_object *json_data; + json_object *json_contactlist_object = NULL; + json_array *json_contactlist_array = NULL; + json_object *json_contact_details; + contact *temp_contact; + int current = 0; + int counted = 0; + + json_data = json_new_object(); + json_object_append_object(json_data, "selectors", + json_object_contact_display_selectors(start, count, + temp_contactgroup, host_notification_timeperiod, + service_notification_timeperiod)); + + if(details > 0) { + json_contactlist_object = json_new_object(); + } + else { + json_contactlist_array = json_new_array(); + } + + for(temp_contact = contact_list; temp_contact != NULL; + temp_contact = temp_contact->next) { + + if(json_object_contact_passes_selection(temp_contact, + temp_contactgroup, host_notification_timeperiod, + service_notification_timeperiod) == 0) { + continue; + } + + /* If the current item passes the start and limit tests, display it */ + if( passes_start_and_count_limits(start, count, current, counted)) { + if( details > 0) { + json_contact_details = json_new_object(); + json_object_contact_details(json_contact_details, + format_options, temp_contact); + json_object_append_object(json_contactlist_object, + temp_contact->name, json_contact_details); + } + else { + json_array_append_string(json_contactlist_array, + &percent_escapes, temp_contact->name); + } + counted++; + } + current++; + } + + if(details > 0) { + json_object_append_object(json_data, "contactlist", + json_contactlist_object); + } + else { + json_object_append_array(json_data, "contactlist", + json_contactlist_array); + } + + return json_data; + } + +json_object *json_object_contact(unsigned format_options, contact *temp_contact) { + + json_object *json_contact = json_new_object(); + json_object *json_details = json_new_object(); + + json_object_append_string(json_details, "name", &percent_escapes, + temp_contact->name); + json_object_contact_details(json_details, format_options, temp_contact); + json_object_append_object(json_contact, "contact", json_details); + + return json_contact; +} + +void json_object_contact_details(json_object *json_details, + unsigned format_options, contact *temp_contact) { + + json_array *json_addresses; + json_array *json_host_commands; + json_array *json_service_commands; + int x; + commandsmember *temp_commandsmember; + + json_object_append_string(json_details, "name", &percent_escapes, + temp_contact->name); + json_object_append_string(json_details, "alias", &percent_escapes, + temp_contact->alias); + json_object_append_string(json_details, "email", &percent_escapes, + temp_contact->email); + json_object_append_string(json_details, "pager", &percent_escapes, + temp_contact->pager); + + json_addresses = json_new_array(); + for( x = 0; x < MAX_CONTACT_ADDRESSES; x++) { + if( NULL != temp_contact->address[ x]) { + json_array_append_string(json_addresses, &percent_escapes, + temp_contact->address[ x]); + } + } + json_object_append_array(json_details, "addresses", json_addresses); + + json_host_commands = json_new_array(); + for(temp_commandsmember = temp_contact->host_notification_commands; + temp_commandsmember != NULL; + temp_commandsmember = temp_commandsmember->next) { + json_array_append_string(json_host_commands, &percent_escapes, + temp_commandsmember->command); + } + json_object_append_array(json_details, "host_notification_commands", + json_host_commands); + + json_service_commands = json_new_array(); + for(temp_commandsmember = temp_contact->service_notification_commands; + temp_commandsmember != NULL; + temp_commandsmember = temp_commandsmember->next) { + json_array_append_string(json_service_commands, &percent_escapes, + temp_commandsmember->command); + } + json_object_append_array(json_details, "service_notification_commands", + json_service_commands); + +#ifdef JSON_NAGIOS_4X +#if 0 + if( CORE3_COMPATIBLE) { + json_object_append_boolean(json_details, "notify_on_service_unknown", + flag_isset(temp_contact->service_notification_options, + OPT_UNKNOWN)); + json_object_append_boolean(json_details, "notify_on_service_warning", + flag_isset(temp_contact->service_notification_options, + OPT_WARNING)); + json_object_append_boolean(json_details, "notify_on_service_critical", + flag_isset(temp_contact->service_notification_options, + OPT_CRITICAL)); + json_object_append_boolean(json_details, "notify_on_service_recovery", + flag_isset(temp_contact->service_notification_options, + OPT_RECOVERY)); + json_object_append_boolean(json_details, "notify_on_service_flapping", + flag_isset(temp_contact->service_notification_options, + OPT_FLAPPING)); + json_object_append_boolean(json_details, "notify_on_service_downtime", + flag_isset(temp_contact->service_notification_options, + OPT_DOWNTIME)); + } + else { +#endif + json_bitmask(json_details, format_options, + "service_notification_options", + temp_contact->service_notification_options, svm_option_types); +#if 0 + } +#endif +#else + json_object_append_boolean(json_details, "notify_on_service_unknown", + temp_contact->notify_on_service_unknown); + json_object_append_boolean(json_details, "notify_on_service_warning", + temp_contact->notify_on_service_warning); + json_object_append_boolean(json_details, "notify_on_service_critical", + temp_contact->notify_on_service_critical); + json_object_append_boolean(json_details, "notify_on_service_recovery", + temp_contact->notify_on_service_recovery); + json_object_append_boolean(json_details, "notify_on_service_flapping", + temp_contact->notify_on_service_flapping); + json_object_append_boolean(json_details, "notify_on_service_downtime", + temp_contact->notify_on_service_downtime); +#endif + +#ifdef JSON_NAGIOS_4X +#if 0 + if( CORE3_COMPATIBLE) { + json_object_append_boolean(json_details, "notify_on_host_down", + flag_isset(temp_contact->host_notification_options, OPT_DOWN)); + json_object_append_boolean(json_details, "notify_on_host_unreachable", + flag_isset(temp_contact->host_notification_options, + OPT_UNREACHABLE)); + json_object_append_boolean(json_details, "notify_on_host_recovery", + flag_isset(temp_contact->host_notification_options, + OPT_RECOVERY)); + json_object_append_boolean(json_details, "notify_on_host_flapping", + flag_isset(temp_contact->host_notification_options, + OPT_FLAPPING)); + json_object_append_boolean(json_details, "notify_on_host_downtime", + flag_isset(temp_contact->host_notification_options, + OPT_DOWNTIME)); + } + else { +#endif + json_bitmask(json_details, format_options, "host_notification_options", + temp_contact->host_notification_options, svm_option_types); +#if 0 + } +#endif +#else + json_object_append_boolean(json_details, "notify_on_host_down", + temp_contact->notify_on_host_down); + json_object_append_boolean(json_details, "notify_on_host_unreachable", + temp_contact->notify_on_host_unreachable); + json_object_append_boolean(json_details, "notify_on_host_recovery", + temp_contact->notify_on_host_recovery); + json_object_append_boolean(json_details, "notify_on_host_flapping", + temp_contact->notify_on_host_flapping); + json_object_append_boolean(json_details, "notify_on_host_downtime", + temp_contact->notify_on_host_downtime); +#endif + + json_object_append_string(json_details, "host_notification_period", + &percent_escapes, temp_contact->host_notification_period); + json_object_append_string(json_details, "service_notification_period", + &percent_escapes, temp_contact->service_notification_period); + json_object_append_boolean(json_details, "host_notifications_enabled", + temp_contact->host_notifications_enabled); + json_object_append_boolean(json_details, "service_notifications_enabled", + temp_contact->service_notifications_enabled); + json_object_append_boolean(json_details, "can_submit_commands", + temp_contact->can_submit_commands); + json_object_append_boolean(json_details, "retain_status_information", + temp_contact->retain_status_information); + json_object_append_boolean(json_details, "retain_nonstatus_information", + temp_contact->retain_nonstatus_information); +#ifdef JSON_NAGIOS_4X + json_object_append_integer(json_details, "minimum_value", + temp_contact->minimum_value); +#endif + json_object_append_object(json_details, "custom_variables", + json_object_custom_variables(temp_contact->custom_variables)); + } + +int json_object_contactgroup_passes_selection(contactgroup *temp_contactgroup, + contact *temp_contactgroup_member) { + + /* Skip if a contactgroup member is specified and the contactgroup + member contact is not a member of the contactgroup */ + if( NULL != temp_contactgroup_member && + ( FALSE == is_contact_member_of_contactgroup(temp_contactgroup, + temp_contactgroup_member))) { + return 0; + } + + return 1; + } + +json_object *json_object_contactgroup_display_selectors( int start, int count, + contact *temp_contactgroup_member) { + + json_object *json_selectors; + + json_selectors = json_new_object(); + + if( start > 0) { + json_object_append_integer(json_selectors, "start", start); + } + if( count > 0) { + json_object_append_integer(json_selectors, "count", count); + } + if( NULL != temp_contactgroup_member) { + json_object_append_string(json_selectors, "contactgroupmember", + &percent_escapes, temp_contactgroup_member->name); + } + + return json_selectors; + } + +json_object *json_object_contactgroupcount(contact * temp_contactgroup_member) { + + json_object *json_data; + contactgroup *temp_contactgroup; + int count = 0; + + json_data = json_new_object(); + json_object_append_object(json_data, "selectors", + json_object_contactgroup_display_selectors(0, 0, + temp_contactgroup_member)); + + for(temp_contactgroup = contactgroup_list; temp_contactgroup != NULL; + temp_contactgroup = temp_contactgroup->next) { + + if(json_object_contactgroup_passes_selection(temp_contactgroup, + temp_contactgroup_member) == 0) { + continue; + } + + count++; + } + + json_object_append_integer(json_data, "count", count); + + return json_data; + } + +json_object *json_object_contactgrouplist(unsigned format_options, int start, + int count, int details, contact * temp_contactgroup_member) { + + json_object *json_data; + json_object *json_contactgrouplist_object = NULL; + json_array *json_contactgrouplist_array = NULL; + json_object *json_contactgroup_details; + contactgroup *temp_contactgroup; + int current = 0; + int counted = 0; + + json_data = json_new_object(); + json_object_append_object(json_data, "selectors", + json_object_contactgroup_display_selectors(start, count, + temp_contactgroup_member)); + + if(details > 0) { + json_contactgrouplist_object = json_new_object(); + } + else { + json_contactgrouplist_array = json_new_array(); + } + + for(temp_contactgroup = contactgroup_list; temp_contactgroup != NULL; + temp_contactgroup = temp_contactgroup->next) { + + if(json_object_contactgroup_passes_selection(temp_contactgroup, + temp_contactgroup_member) == 0) { + continue; + } + + /* If the current item passes the start and limit tests, display it */ + if( passes_start_and_count_limits(start, count, current, counted)) { + if( details > 0) { + json_contactgroup_details = json_new_object(); + json_object_contactgroup_details(json_contactgroup_details, + format_options, temp_contactgroup); + json_object_append_object(json_contactgrouplist_object, + temp_contactgroup->group_name, json_contactgroup_details); + } + else { + json_array_append_string(json_contactgrouplist_array, + &percent_escapes, temp_contactgroup->group_name); + } + counted++; + } + current++; + } + + if(details > 0) { + json_object_append_object(json_data, "contactgrouplist", + json_contactgrouplist_object); + } + else { + json_object_append_array(json_data, "contactgrouplist", + json_contactgrouplist_array); + } + + return json_data; + } + +json_object *json_object_contactgroup(unsigned format_options, + contactgroup *temp_contactgroup) { + + json_object *json_contactgroup = json_new_object(); + json_object *json_details = json_new_object(); + + json_object_append_string(json_details, "group_name", &percent_escapes, + temp_contactgroup->group_name); + json_object_contactgroup_details(json_details, format_options, + temp_contactgroup); + json_object_append_object(json_contactgroup, "contactgroup", json_details); + + return json_contactgroup; +} + +void json_object_contactgroup_details(json_object *json_details, + unsigned format_options, contactgroup *temp_contactgroup) { + + json_array *json_members; + contactsmember *temp_member; + + json_object_append_string(json_details, "group_name", &percent_escapes, + temp_contactgroup->group_name); + json_object_append_string(json_details, "alias", &percent_escapes, + temp_contactgroup->alias); + + json_members = json_new_array(); + for(temp_member = temp_contactgroup->members; temp_member != NULL; + temp_member = temp_member->next) { + json_array_append_string(json_members, &percent_escapes, + temp_member->contact_name); + } + json_object_append_array(json_details, "members", json_members); + } + +json_object *json_object_timeperiod_selectors(int start, int count) { + + json_object *json_selectors; + + json_selectors = json_new_object(); + + if( start > 0) { + json_object_append_integer(json_selectors, "start", start); + } + if( count > 0) { + json_object_append_integer(json_selectors, "count", count); + } + + return json_selectors; + } + +json_object *json_object_timeperiodcount(void) { + + json_object *json_data; + timeperiod *temp_timeperiod; + int count = 0; + + json_data = json_new_object(); + json_object_append_object(json_data, "selectors", + json_object_timeperiod_selectors(0, 0)); + + for(temp_timeperiod = timeperiod_list; temp_timeperiod != NULL; + temp_timeperiod = temp_timeperiod->next) { + + count++; + } + + json_object_append_integer(json_data, "count", count); + + return json_data; + } + +json_object *json_object_timeperiodlist(unsigned format_options, int start, + int count, int details) { + + json_object *json_data; + json_object *json_timeperiodlist_object = NULL; + json_array *json_timeperiodlist_array = NULL; + json_object *json_timeperiod_details; + timeperiod *temp_timeperiod; + int current = 0; + int counted = 0; + + json_data = json_new_object(); + json_object_append_object(json_data, "selectors", + json_object_timeperiod_selectors(start, count)); + + if(details > 0) { + json_timeperiodlist_object = json_new_object(); + } + else { + json_timeperiodlist_array = json_new_array(); + } + + for(temp_timeperiod = timeperiod_list; temp_timeperiod != NULL; + temp_timeperiod = temp_timeperiod->next) { + + /* If the current item passes the start and limit tests, display it */ + if( passes_start_and_count_limits(start, count, current, counted)) { + if( details > 0) { + json_timeperiod_details = json_new_object(); + json_object_timeperiod_details(json_timeperiod_details, + format_options, temp_timeperiod); + json_object_append_object(json_timeperiodlist_object, + temp_timeperiod->name, json_timeperiod_details); + } + else { + json_array_append_string(json_timeperiodlist_array, + &percent_escapes, temp_timeperiod->name); + } + counted++; + } + current++; + } + + if(details > 0) { + json_object_append_object(json_data, "timeperiodlist", + json_timeperiodlist_object); + } + else { + json_object_append_array(json_data, "timeperiodlist", + json_timeperiodlist_array); + } + + return json_data; + } + +json_object *json_object_timeperiod(unsigned format_options, + timeperiod *temp_timeperiod) { + + json_object *json_timeperiod = json_new_object(); + json_object *json_details = json_new_object(); + + json_object_append_string(json_details, "name", &percent_escapes, + temp_timeperiod->name); + json_object_timeperiod_details(json_details, format_options, temp_timeperiod); + json_object_append_object(json_timeperiod, "timeperiod", json_details); + + return json_timeperiod; +} + +void json_object_timeperiod_details(json_object *json_details, + unsigned format_options, timeperiod *temp_timeperiod) { + + json_object *json_days; + int x; + json_array *json_timeranges; + json_array *json_exceptions; + json_array *json_exclusions; + daterange *temp_daterange; + timeperiodexclusion *temp_timeperiodexclusion; + + json_object_append_string(json_details, "name", &percent_escapes, + temp_timeperiod->name); + json_object_append_string(json_details, "alias", &percent_escapes, + temp_timeperiod->alias); + + json_days = json_new_object(); + for(x = 0; x < sizeof(temp_timeperiod->days) / sizeof(temp_timeperiod->days[0]); x++) { + if( NULL != temp_timeperiod->days[x]) { + json_timeranges = json_new_array(); + json_object_timerange(json_timeranges, format_options, + temp_timeperiod->days[x]); + json_object_append_array(json_days, (char *)dayofweek[x], + json_timeranges); + } + } + json_object_append_object(json_details, "days", json_days); + + json_exceptions = json_new_array(); + for(x = 0; x < DATERANGE_TYPES; x++) { + for(temp_daterange = temp_timeperiod->exceptions[x]; + temp_daterange != NULL; temp_daterange = temp_daterange->next) { + json_array_append_object(json_exceptions, + json_object_daterange(format_options, temp_daterange, x)); + } + } + json_object_append_array(json_details, "exceptions", json_exceptions); + + json_exclusions = json_new_array(); + for(temp_timeperiodexclusion = temp_timeperiod->exclusions; + temp_timeperiodexclusion != NULL; + temp_timeperiodexclusion = temp_timeperiodexclusion->next) { + json_array_append_string(json_exclusions, &percent_escapes, + temp_timeperiodexclusion->timeperiod_name); + } + json_object_append_array(json_details, "exclusions", json_exclusions); + } + +json_object * json_object_daterange(unsigned format_options, + daterange *temp_daterange, int daterange_type) { + + json_object *json_daterange; + json_array *json_timeranges; + + json_daterange = json_new_object(); + + switch(daterange_type) { + case DATERANGE_CALENDAR_DATE: + json_object_append_string(json_daterange, "type", NULL, + "DATERANGE_CALENDAR_DATE"); + if(temp_daterange->syear == temp_daterange->eyear && + temp_daterange->smon == temp_daterange->emon && + temp_daterange->smday == temp_daterange->emday) { + json_object_append_string(json_daterange, "date", NULL, + "%4d-%02d-%02d", temp_daterange->syear, + temp_daterange->smon+1, temp_daterange->smday); + } + else { + json_object_append_string(json_daterange, "startdate", NULL, + "%4d-%02d-%02d", temp_daterange->syear, + temp_daterange->smon+1, temp_daterange->smday); + json_object_append_string(json_daterange, "enddate", NULL, + "%4d-%02d-%02d", temp_daterange->eyear, + temp_daterange->emon+1, temp_daterange->emday); + } + if( temp_daterange->skip_interval > 0) { + json_object_append_integer(json_daterange, "skip_interval", + temp_daterange->skip_interval); + } + json_timeranges = json_new_array(); + json_object_timerange(json_timeranges, format_options, + temp_daterange->times); + json_object_append_array(json_daterange, "times", json_timeranges); + break; + case DATERANGE_MONTH_DATE: + json_object_append_string(json_daterange, "type", NULL, + "DATERANGE_MONTH_DATE"); + if(temp_daterange->smon == temp_daterange->emon && + temp_daterange->smday == temp_daterange->emday) { + json_object_append_string(json_daterange, "month", &percent_escapes, + (char *)month[temp_daterange->smon]); + json_object_append_integer(json_daterange, "day", + temp_daterange->smday); + } + else { + json_object_append_string(json_daterange, "startmonth", + &percent_escapes, (char *)month[temp_daterange->smon]); + json_object_append_integer(json_daterange, "startday", + temp_daterange->smday); + json_object_append_string(json_daterange, "endmonth", + &percent_escapes, (char *)month[temp_daterange->emon]); + json_object_append_integer(json_daterange, "endday", + temp_daterange->emday); + } + if( temp_daterange->skip_interval > 0) { + json_object_append_integer(json_daterange, "skip_interval", + temp_daterange->skip_interval); + } + json_timeranges = json_new_array(); + json_object_timerange(json_timeranges, format_options, + temp_daterange->times); + json_object_append_array(json_daterange, "times", json_timeranges); + break; + case DATERANGE_MONTH_DAY: + json_object_append_string(json_daterange, "type", NULL, + "DATERANGE_MONTH_DAY"); + if(temp_daterange->smday == temp_daterange->emday) { + json_object_append_integer(json_daterange, "day", + temp_daterange->smday); + } + else { + json_object_append_integer(json_daterange, "startday", + temp_daterange->smday); + json_object_append_integer(json_daterange, "endday", + temp_daterange->emday); + } + if( temp_daterange->skip_interval > 0) { + json_object_append_integer(json_daterange, "skip_interval", + temp_daterange->skip_interval); + } + json_timeranges = json_new_array(); + json_object_timerange(json_timeranges, format_options, + temp_daterange->times); + json_object_append_array(json_daterange, "times", json_timeranges); + break; + case DATERANGE_MONTH_WEEK_DAY: + json_object_append_string(json_daterange, "type", NULL, + "DATERANGE_MONTH_WEEK_DAY"); + if(temp_daterange->smon == temp_daterange->emon && + temp_daterange->swday == temp_daterange->ewday && + temp_daterange->swday_offset == temp_daterange->ewday_offset) { + json_object_append_string(json_daterange, "month", &percent_escapes, + (char *)month[temp_daterange->smon]); + json_object_append_string(json_daterange, "weekday", + &percent_escapes, (char *)dayofweek[temp_daterange->swday]); + json_object_append_integer(json_daterange, "weekdayoffset", + temp_daterange->swday_offset); + } + else { + json_object_append_string(json_daterange, "startmonth", + &percent_escapes, (char *)month[temp_daterange->smon]); + json_object_append_string(json_daterange, "startweekday", + &percent_escapes, (char *)dayofweek[temp_daterange->swday]); + json_object_append_integer(json_daterange, "startweekdayoffset", + temp_daterange->swday_offset); + json_object_append_string(json_daterange, "endmonth", + &percent_escapes, (char *)month[temp_daterange->emon]); + json_object_append_string(json_daterange, "endweekday", + &percent_escapes, (char *)dayofweek[temp_daterange->ewday]); + json_object_append_integer(json_daterange, "endweekdayoffset", + temp_daterange->ewday_offset); + } + if( temp_daterange->skip_interval > 0) { + json_object_append_integer(json_daterange, "skip_interval", + temp_daterange->skip_interval); + } + json_timeranges = json_new_array(); + json_object_timerange(json_timeranges, format_options, + temp_daterange->times); + json_object_append_array(json_daterange, "times", json_timeranges); + break; + case DATERANGE_WEEK_DAY: + json_object_append_string(json_daterange, "type", NULL, + "DATERANGE_WEEK_DAY"); + if(temp_daterange->swday == temp_daterange->ewday && + temp_daterange->swday_offset == temp_daterange->ewday_offset) { + json_object_append_string(json_daterange, "weekday", + &percent_escapes, (char *)dayofweek[temp_daterange->swday]); + json_object_append_integer(json_daterange, "weekdayoffset", + temp_daterange->swday_offset); + } + else { + json_object_append_string(json_daterange, "startweekday", + &percent_escapes, (char *)dayofweek[temp_daterange->swday]); + json_object_append_integer(json_daterange, "startweekdayoffset", + temp_daterange->swday_offset); + json_object_append_string(json_daterange, "endweekday", + &percent_escapes, (char *)dayofweek[temp_daterange->ewday]); + json_object_append_integer(json_daterange, "endweekdayoffset", + temp_daterange->ewday_offset); + } + if( temp_daterange->skip_interval > 0) { + json_object_append_integer(json_daterange, "skip_interval", + temp_daterange->skip_interval); + } + json_timeranges = json_new_array(); + json_object_timerange(json_timeranges, format_options, + temp_daterange->times); + json_object_append_array(json_daterange, "times", json_timeranges); + break; + default: + json_object_append_string(json_daterange, "type", NULL, + "Unknown daterange type: %u", daterange_type); + break; + } + + return json_daterange; + } + +void json_object_timerange(json_array *json_parent, unsigned format_options, + timerange *temp_timerange) { + + json_object *json_timerange; + + for(; temp_timerange != NULL; temp_timerange = temp_timerange->next) { + json_timerange = json_new_object(); + json_object_append_time(json_timerange, "range_start", + temp_timerange->range_start); + json_object_append_time(json_timerange, "range_end", + temp_timerange->range_end); + json_array_append_object(json_parent, json_timerange); + } + } + +json_object *json_object_command_selectors(int start, int count) { + + json_object *json_selectors; + + json_selectors = json_new_object(); + + if( start > 0) { + json_object_append_integer(json_selectors, "start", start); + } + if( count > 0) { + json_object_append_integer(json_selectors, "count", count); + } + + return json_selectors; + } + +json_object *json_object_commandcount(void) { + + json_object *json_data; + command *temp_command; + int count = 0; + + json_data = json_new_object(); + json_object_append_object(json_data, "selectors", + json_object_command_selectors(0, 0)); + + for(temp_command = command_list; temp_command != NULL; + temp_command = temp_command->next) { + + count++; + } + + json_object_append_integer(json_data, "count", count); + + return json_data; + } + +json_object *json_object_commandlist(unsigned format_options, int start, + int count, int details) { + + json_object *json_data; + json_object *json_commandlist_object = NULL; + json_array *json_commandlist_array = NULL; + json_object *json_command_details; + command *temp_command; + int current = 0; + int counted = 0; + + json_data = json_new_object(); + json_object_append_object(json_data, "selectors", + json_object_command_selectors(start, count)); + + if(details > 0) { + json_commandlist_object = json_new_object(); + } + else { + json_commandlist_array = json_new_array(); + } + + for(temp_command = command_list; temp_command != NULL; + temp_command = temp_command->next) { + + /* If the current item passes the start and limit tests, display it */ + if( passes_start_and_count_limits(start, count, current, counted)) { + if( details > 0) { + json_command_details = json_new_object(); + json_object_command_details(json_command_details, format_options, + temp_command); + json_object_append_object(json_commandlist_object, + temp_command->name, json_command_details); + } + else { + json_array_append_string(json_commandlist_array, + &percent_escapes, temp_command->name); + } + counted++; + } + current++; + } + + if(details > 0) { + json_object_append_object(json_data, "commandlist", + json_commandlist_object); + } + else { + json_object_append_array(json_data, "commandlist", + json_commandlist_array); + } + + return json_data; + } + +json_object *json_object_command(unsigned format_options, command *temp_command) { + + json_object *json_command = json_new_object(); + json_object *json_details = json_new_object(); + + json_object_append_string(json_details, "name", &percent_escapes, + temp_command->name); + json_object_command_details(json_details, format_options, temp_command); + json_object_append_object(json_command, "command", json_details); + + return json_command; +} + +void json_object_command_details(json_object *json_details, + unsigned format_options, command *temp_command) { + json_object_append_string(json_details, "name", &percent_escapes, + temp_command->name); + json_object_append_string(json_details, "command_line", &percent_escapes, + temp_command->command_line); + } + +int json_object_servicedependency_passes_selection( + servicedependency *temp_servicedependency, host *master_host, + hostgroup *master_hostgroup, char *master_service_description, + servicegroup *master_servicegroup, host *dependent_host, + hostgroup *dependent_hostgroup, char * dependent_service_description, + servicegroup *dependent_servicegroup) { + + host *temp_host = NULL; + service *temp_service = NULL; + + /* Skip if the servicedependency does not have the specified master host */ + if(NULL != master_host && + strcmp(temp_servicedependency->host_name, master_host->name)) { + return 0; + } + + /* Skip if the servicedependency does not have a master host in the + specified hostgroup */ + if(NULL != master_hostgroup) { + temp_host = find_host(temp_servicedependency->host_name); + if((NULL != temp_host) && (FALSE == + is_host_member_of_hostgroup(master_hostgroup, temp_host))) { + return 0; + } + } + + /* Skip if the servicedependency does not have the specified master + service */ + if(NULL != master_service_description && + strcmp(temp_servicedependency->service_description, + master_service_description)) { + return 0; + } + + /* Skip if the servicedependency does not have a master service in the + specified servicegroup */ + if(NULL != master_servicegroup) { + temp_service = find_service(temp_servicedependency->host_name, + temp_servicedependency->service_description); + if((NULL != temp_service) && (FALSE == + is_service_member_of_servicegroup(master_servicegroup, + temp_service))) { + return 0; + } + } + + /* Skip if the servicedependency does not have the specified dependent + host */ + if(NULL != dependent_host && + strcmp(temp_servicedependency->dependent_host_name, + dependent_host->name)) { + return 0; + } + + /* Skip if the servicedependency does not have a dependent host in the + specified hostgroup */ + if(NULL != dependent_hostgroup) { + temp_host = find_host(temp_servicedependency->dependent_host_name); + if((NULL != temp_host) && (FALSE == + is_host_member_of_hostgroup(dependent_hostgroup, temp_host))) { + return 0; + } + } + + /* Skip if the servicedependency does not have the specified dependent + service */ + if(NULL != dependent_service_description && + strcmp(temp_servicedependency->dependent_service_description, + dependent_service_description)) { + return 0; + } + + /* Skip if the servicedependency does not have a dependent service in the + specified servicegroup */ + if(NULL != dependent_servicegroup) { + temp_service = find_service(temp_servicedependency->dependent_host_name, + temp_servicedependency->dependent_service_description); + if((NULL != temp_service) && (FALSE == + is_service_member_of_servicegroup(dependent_servicegroup, + temp_service))) { + return 0; + } + } + + return 1; + } + +json_object *json_object_servicedependency_selectors(int start, int count, + host *master_host, hostgroup *master_hostgroup, + char *master_service_description, servicegroup *master_servicegroup, + host *dependent_host, hostgroup *dependent_hostgroup, + char * dependent_service_description, + servicegroup *dependent_servicegroup) { + + json_object *json_selectors; + + json_selectors = json_new_object(); + + if( start > 0) { + json_object_append_integer(json_selectors, "start", start); + } + if( count > 0) { + json_object_append_integer(json_selectors, "count", count); + } + if(NULL != master_host) { + json_object_append_string(json_selectors, "masterhostname", + &percent_escapes, master_host->name); + } + if(NULL != master_hostgroup) { + json_object_append_string(json_selectors, "masterhostgroupname", + &percent_escapes, master_hostgroup->group_name); + } + if(NULL != master_service_description) { + json_object_append_string(json_selectors, "masterservicedescription", + &percent_escapes, master_service_description); + } + if(NULL != master_servicegroup) { + json_object_append_string(json_selectors, "masterservicegroupname", + &percent_escapes, master_servicegroup->group_name); + } + if(NULL != dependent_host) { + json_object_append_string(json_selectors, "dependenthostname", + &percent_escapes, dependent_host->name); + } + if(NULL != dependent_hostgroup) { + json_object_append_string(json_selectors, "dependenthostgroupname", + &percent_escapes, dependent_hostgroup->group_name); + } + if(NULL != dependent_service_description) { + json_object_append_string(json_selectors, "dependentservicedescription", + &percent_escapes, dependent_service_description); + } + if(NULL != dependent_servicegroup) { + json_object_append_string(json_selectors, "dependentservicegroupname", + &percent_escapes, dependent_servicegroup->group_name); + } + + return json_selectors; + } + +json_object *json_object_servicedependencycount(host *master_host, + hostgroup *master_hostgroup, char *master_service_description, + servicegroup *master_servicegroup, host *dependent_host, + hostgroup *dependent_hostgroup, char * dependent_service_description, + servicegroup *dependent_servicegroup) { + + json_object *json_data; +#ifdef JSON_NAGIOS_4X + int x; +#endif + servicedependency *temp_servicedependency; + int count = 0; + + json_data = json_new_object(); + json_object_append_object(json_data, "selectors", + json_object_servicedependency_selectors(0, 0, master_host, + master_hostgroup, master_service_description, master_servicegroup, + dependent_host, dependent_hostgroup, dependent_service_description, + dependent_servicegroup)); + +#ifdef JSON_NAGIOS_4X + for(x = 0; x < num_objects.servicedependencies; x++) { + temp_servicedependency = servicedependency_ary[ x]; +#else + for(temp_servicedependency = servicedependency_list; + temp_servicedependency != NULL; + temp_servicedependency = temp_servicedependency->next) { +#endif + + if(json_object_servicedependency_passes_selection(temp_servicedependency, + master_host, master_hostgroup, master_service_description, + master_servicegroup, dependent_host, dependent_hostgroup, + dependent_service_description, dependent_servicegroup)) { + count++; + } + } + + json_object_append_integer(json_data, "count", count); + + return json_data; + } + +json_object *json_object_servicedependencylist(unsigned format_options, + int start, int count, host *master_host, hostgroup *master_hostgroup, + char *master_service_description, servicegroup *master_servicegroup, + host *dependent_host, hostgroup *dependent_hostgroup, + char * dependent_service_description, + servicegroup *dependent_servicegroup) { + + json_object *json_data; + json_array *json_servicedependencylist; + json_object *json_servicedependency_details; +#ifdef JSON_NAGIOS_4X + int x; +#endif + servicedependency *temp_servicedependency; + int current = 0; + int counted = 0; + + json_data = json_new_object(); + json_object_append_object(json_data, "selectors", + json_object_servicedependency_selectors(start, count, + master_host, master_hostgroup, master_service_description, + master_servicegroup, dependent_host, dependent_hostgroup, + dependent_service_description, dependent_servicegroup)); + + json_servicedependencylist = json_new_array(); + +#ifdef JSON_NAGIOS_4X + for(x = 0; x < num_objects.servicedependencies; x++) { + temp_servicedependency = servicedependency_ary[ x]; +#else + for(temp_servicedependency = servicedependency_list; + temp_servicedependency != NULL; + temp_servicedependency = temp_servicedependency->next) { +#endif + + if(!json_object_servicedependency_passes_selection(temp_servicedependency, + master_host, master_hostgroup, master_service_description, + master_servicegroup, dependent_host, dependent_hostgroup, + dependent_service_description, dependent_servicegroup)) { + continue; + } + + /* If the current item passes the start and limit tests, display it */ + if( passes_start_and_count_limits(start, count, + current, counted)) { + json_servicedependency_details = json_new_object(); + json_object_servicedependency_details(json_servicedependency_details, + format_options, temp_servicedependency); + json_array_append_object(json_servicedependencylist, + json_servicedependency_details); + } + counted++; + current++; + } + + json_object_append_array(json_data, "servicedependencylist", + json_servicedependencylist); + + return json_data; + } + +void json_object_servicedependency_details(json_object *json_details, + unsigned format_options, servicedependency *temp_servicedependency) { + + json_object_append_integer(json_details, "dependency_type", + temp_servicedependency->dependency_type); + json_object_append_string(json_details, "dependent_host_name", + &percent_escapes, temp_servicedependency->dependent_host_name); + json_object_append_string(json_details, "dependent_service_description", + &percent_escapes, + temp_servicedependency->dependent_service_description); + json_object_append_string(json_details, "host_name", + &percent_escapes, temp_servicedependency->host_name); + json_object_append_string(json_details, "service_description", + &percent_escapes, temp_servicedependency->service_description); + json_object_append_string(json_details, "dependency_period", + &percent_escapes, temp_servicedependency->dependency_period); + json_object_append_boolean(json_details, "inherits_parent", + temp_servicedependency->inherits_parent); + +#ifdef JSON_NAGIOS_4X +#if 0 + if( CORE3_COMPATIBLE) { + json_object_append_boolean(json_details, "fail_on_ok", + flag_isset(temp_servicedependency->failure_options, OPT_OK)); + json_object_append_boolean(json_details, "fail_on_warning", + flag_isset(temp_servicedependency->failure_options, + OPT_WARNING)); + json_object_append_boolean(json_details, "fail_on_unknown", + flag_isset(temp_servicedependency->failure_options, + OPT_UNKNOWN)); + json_object_append_boolean(json_details, "fail_on_critical", + flag_isset(temp_servicedependency->failure_options, + OPT_CRITICAL)); + json_object_append_boolean(json_details, "fail_on_pending", + flag_isset(temp_servicedependency->failure_options, + OPT_PENDING)); + } + else { +#endif + json_bitmask(json_details, format_options, "failure_options", + temp_servicedependency->failure_options, svm_option_types); +#if 0 + } +#endif +#else + json_object_append_boolean(json_details, "fail_on_ok", + temp_servicedependency->fail_on_ok); + json_object_append_boolean(json_details, "fail_on_warning", + temp_servicedependency->fail_on_warning); + json_object_append_boolean(json_details, "fail_on_unknown", + temp_servicedependency->fail_on_unknown); + json_object_append_boolean(json_details, "fail_on_critical", + temp_servicedependency->fail_on_critical); + json_object_append_boolean(json_details, "fail_on_pending", + temp_servicedependency->fail_on_pending); +#endif + } + +int json_object_serviceescalation_passes_selection(serviceescalation *temp_serviceescalation, + host *match_host, char *service_description, + hostgroup *match_hostgroup, servicegroup *match_servicegroup, + contact *match_contact, contactgroup *match_contactgroup) { + + int found; + hostsmember *temp_hostsmember; + servicesmember *temp_servicesmember; + + /* Skip if the serviceescalation is not for the specified host */ + if( NULL != match_host && + strcmp( temp_serviceescalation->host_name, match_host->name)) { + return 0; + } + + if((NULL != service_description) && + strcmp(temp_serviceescalation->description, service_description)) { + return 0; + } + + if(NULL != match_hostgroup) { + found = 0; + for(temp_hostsmember = match_hostgroup->members; + temp_hostsmember != NULL; + temp_hostsmember = temp_hostsmember->next) { + if(!strcmp(temp_hostsmember->host_name, + temp_serviceescalation->host_name)) { + found = 1; + break; + } + } + if(0 == found) { + return 0; + } + } + + if(NULL != match_servicegroup) { + found = 0; + for(temp_servicesmember = match_servicegroup->members; + temp_servicesmember != NULL; + temp_servicesmember = temp_servicesmember->next) { + if(!strcmp(temp_servicesmember->host_name, + temp_serviceescalation->host_name) && + !strcmp(temp_servicesmember->service_description, + temp_serviceescalation->description)) { + found = 1; + break; + } + } + if(0 == found) { + return 0; + } + } + + /* If a contact was specified, skip this service escalation if it does + not have the contact specified */ + if( NULL != match_contact && + ( FALSE == is_contact_for_service_escalation(temp_serviceescalation, + match_contact))) { + return 0; + } + + /* If a contactgroup was specified, skip this service escalation if + it does not have the contactgroup specified */ + if(NULL != match_contactgroup && (FALSE == + is_contactgroup_for_service_escalation(temp_serviceescalation, + match_contactgroup))) { + return 0; + } + + return 1; + } + +json_object *json_object_serviceescalation_selectors(int start, int count, + host *match_host, char *service_description, + hostgroup *match_hostgroup, servicegroup *match_servicegroup, + contact *match_contact, contactgroup *match_contactgroup) { + + json_object *json_selectors; + + json_selectors = json_new_object(); + + if(start > 0) { + json_object_append_integer(json_selectors, "start", start); + } + if(count > 0) { + json_object_append_integer(json_selectors, "count", count); + } + if(NULL != match_host) { + json_object_append_string(json_selectors, "hostname", &percent_escapes, + match_host->name); + } + if(NULL != service_description) { + json_object_append_string(json_selectors, "servicedescription", + &percent_escapes, service_description); + } + if(NULL != match_hostgroup) { + json_object_append_string(json_selectors, "hostgroup", + &percent_escapes, match_hostgroup->group_name); + } + if(NULL != match_servicegroup) { + json_object_append_string(json_selectors, "servicegroup", + &percent_escapes, match_servicegroup->group_name); + } + if( NULL != match_contact) { + json_object_append_string(json_selectors, "contact", + &percent_escapes, match_contact->name); + } + if( NULL != match_contactgroup) { + json_object_append_string(json_selectors, "contactgroup", + &percent_escapes, match_contactgroup->group_name); + } + + return json_selectors; + } + +json_object *json_object_serviceescalationcount(host *match_host, + char *service_description, hostgroup *match_hostgroup, + servicegroup *match_servicegroup, contact *match_contact, + contactgroup *match_contactgroup) { + + json_object *json_data; +#ifdef JSON_NAGIOS_4X + int x; +#endif + serviceescalation *temp_serviceescalation; + int count = 0; + + json_data = json_new_object(); + json_object_append_object(json_data, "selectors", + json_object_serviceescalation_selectors(0, 0, match_host, + service_description, match_hostgroup, match_servicegroup, + match_contact, match_contactgroup)); + +#ifdef JSON_NAGIOS_4X + for(x = 0; x < num_objects.serviceescalations; x++) { + temp_serviceescalation=serviceescalation_ary[ x]; +#else + for(temp_serviceescalation = serviceescalation_list; + temp_serviceescalation != NULL; + temp_serviceescalation = temp_serviceescalation->next) { +#endif + if(json_object_serviceescalation_passes_selection(temp_serviceescalation, + match_host, service_description, match_hostgroup, + match_servicegroup, match_contact, match_contactgroup) == 0) { + continue; + } + + + count++; + } + + json_object_append_integer(json_data, "count", count); + + return json_data; + } + +json_object *json_object_serviceescalationlist(unsigned format_options, + int start, int count, host *match_host, char *service_description, + hostgroup *match_hostgroup, servicegroup *match_servicegroup, + contact *match_contact, contactgroup *match_contactgroup) { + + json_object *json_data; + json_array *json_serviceescalationlist; + json_object *json_serviceescalation_details; +#ifdef JSON_NAGIOS_4X + int x; +#endif + serviceescalation *temp_serviceescalation; + int current = 0; + int counted = 0; + + json_data = json_new_object(); + json_object_append_object(json_data, "selectors", + json_object_serviceescalation_selectors(start, count, match_host, + service_description, match_hostgroup, match_servicegroup, + match_contact, match_contactgroup)); + + json_serviceescalationlist = json_new_array(); + +#ifdef JSON_NAGIOS_4X + for(x = 0; x < num_objects.serviceescalations; x++) { + temp_serviceescalation=serviceescalation_ary[ x]; +#else + for(temp_serviceescalation = serviceescalation_list; + temp_serviceescalation != NULL; + temp_serviceescalation = temp_serviceescalation->next) { +#endif + if(json_object_serviceescalation_passes_selection(temp_serviceescalation, + match_host, service_description, match_hostgroup, + match_servicegroup, match_contact, match_contactgroup) == 0) { + continue; + } + + + /* If the current item passes the start and limit tests, display it */ + if( passes_start_and_count_limits(start, count, current, counted)) { + json_serviceescalation_details = json_new_object(); + json_object_serviceescalation_details(json_serviceescalation_details, + format_options, temp_serviceescalation); + json_array_append_object(json_serviceescalationlist, + json_serviceescalation_details); + } + counted++; + current++; + } + + json_object_append_array(json_data, "serviceescalationlist", + json_serviceescalationlist); + + return json_data; + } + +void json_object_serviceescalation_details(json_object *json_details, + unsigned format_options, serviceescalation *temp_serviceescalation) { + + json_array *json_contactgroups; + json_array *json_contacts; + contactgroupsmember *temp_contact_groupsmember; + contactsmember *temp_contactsmember; + + json_object_append_string(json_details, "host_name", &percent_escapes, + temp_serviceescalation->host_name); + json_object_append_string(json_details, "description", &percent_escapes, + temp_serviceescalation->description); + json_object_append_integer(json_details, "first_notification", + temp_serviceescalation->first_notification); + json_object_append_integer(json_details, "last_notification", + temp_serviceescalation->last_notification); + json_object_append_real(json_details, "notification_interval", + temp_serviceescalation->notification_interval); + json_object_append_string(json_details, "escalation_period", + &percent_escapes, temp_serviceescalation->escalation_period); + +#ifdef JSON_NAGIOS_4X +#if 0 + if( CORE3_COMPATIBLE) { + json_object_append_boolean(json_details, "escalate_on_recovery", + flag_isset(temp_serviceescalation->escalation_options, + OPT_RECOVERY)); + json_object_append_boolean(json_details, "escalate_on_warning", + flag_isset(temp_serviceescalation->escalation_options, + OPT_WARNING)); + json_object_append_boolean(json_details, "escalate_on_unknown", + flag_isset(temp_serviceescalation->escalation_options, + OPT_UNKNOWN))); + json_object_append_boolean(json_details, "escalate_on_critical", + flag_isset(temp_serviceescalation->escalation_options, + OPT_CRITICAL)); + } + else { +#endif + json_bitmask(json_details, format_options, "escalation_options", + temp_serviceescalation->escalation_options, svm_option_types); +#if 0 + } +#endif +#else + json_object_append_boolean(json_details, "escalate_on_recovery", + temp_serviceescalation->escalate_on_recovery); + json_object_append_boolean(json_details, "escalate_on_warning", + temp_serviceescalation->escalate_on_warning); + json_object_append_boolean(json_details, "escalate_on_unknown", + temp_serviceescalation->escalate_on_unknown); + json_object_append_boolean(json_details, "escalate_on_critical", + temp_serviceescalation->escalate_on_critical); +#endif + + json_contactgroups = json_new_object(); + for(temp_contact_groupsmember = temp_serviceescalation->contact_groups; + temp_contact_groupsmember != NULL; + temp_contact_groupsmember = temp_contact_groupsmember->next) { + json_array_append_string(json_contactgroups, &percent_escapes, + temp_contact_groupsmember->group_name); + } + json_object_append_array(json_details, "contact_groups", json_contactgroups); + + json_contacts = json_new_object(); + for(temp_contactsmember = temp_serviceescalation->contacts; + temp_contactsmember != NULL; + temp_contactsmember = temp_contactsmember->next) { + json_array_append_string(json_contacts, &percent_escapes, + temp_contactsmember->contact_name); + } + json_object_append_array(json_details, "contacts", json_contacts); + } + +int json_object_hostdependency_passes_selection( + hostdependency *temp_hostdependency, host *master_host, + hostgroup *master_hostgroup, host *dependent_host, + hostgroup *dependent_hostgroup) { + + host *temp_host = NULL; + + /* Skip if the hostdependency does not have the specified master host */ + if(NULL != master_host && + strcmp(temp_hostdependency->host_name, master_host->name)) { + return 0; + } + + /* Skip if the hostdependency does not have a master host in the + specified hostgroup*/ + if(NULL != master_hostgroup) { + temp_host = find_host(temp_hostdependency->host_name); + if((NULL != temp_host) && (FALSE == + is_host_member_of_hostgroup(master_hostgroup, temp_host))) { + return 0; + } + } + + /* Skip if the hostdependency does not have the specified dependent host */ + if(NULL != dependent_host && + strcmp(temp_hostdependency->dependent_host_name, + dependent_host->name)) { + return 0; + } + + /* Skip if the hostdependency does not have a dependent host in the + specified hostgroup*/ + if(NULL != dependent_hostgroup) { + temp_host = find_host(temp_hostdependency->dependent_host_name); + if((NULL != temp_host) && (FALSE == + is_host_member_of_hostgroup(dependent_hostgroup, temp_host))) { + return 0; + } + } + + return 1; + } + +json_object *json_object_hostdependency_selectors(int start, int count, + host *master_host, hostgroup *master_hostgroup, host *dependent_host, + hostgroup *dependent_hostgroup) { + + json_object *json_selectors; + + json_selectors = json_new_object(); + + if( start > 0) { + json_object_append_integer(json_selectors, "start", start); + } + if( count > 0) { + json_object_append_integer(json_selectors, "count", count); + } + if(NULL != master_host) { + json_object_append_string(json_selectors, "masterhostname", + &percent_escapes, master_host->name); + } + if(NULL != master_hostgroup) { + json_object_append_string(json_selectors, "masterhostgroupname", + &percent_escapes, master_hostgroup->group_name); + } + if(NULL != dependent_host) { + json_object_append_string(json_selectors, "dependenthostname", + &percent_escapes, dependent_host->name); + } + if(NULL != dependent_hostgroup) { + json_object_append_string(json_selectors, "dependenthostgroupname", + &percent_escapes, dependent_hostgroup->group_name); + } + + return json_selectors; + } + +json_object *json_object_hostdependencycount(host *master_host, + hostgroup *master_hostgroup, host *dependent_host, + hostgroup *dependent_hostgroup) { + + json_object *json_data; +#ifdef JSON_NAGIOS_4X + int x; +#endif + hostdependency *temp_hostdependency; + int count = 0; + + json_data = json_new_object(); + json_object_append_object(json_data, "selectors", + json_object_hostdependency_selectors(0, 0, master_host, + master_hostgroup, dependent_host, dependent_hostgroup)); + +#ifdef JSON_NAGIOS_4X + for(x = 0; x < num_objects.hostdependencies; x++) { + temp_hostdependency = hostdependency_ary[ x]; +#else + for(temp_hostdependency = hostdependency_list; + temp_hostdependency != NULL; + temp_hostdependency = temp_hostdependency->next) { +#endif + + if(json_object_hostdependency_passes_selection( + temp_hostdependency, master_host, master_hostgroup, + dependent_host, dependent_hostgroup)) { + count++; + } + } + + json_object_append_integer(json_data, "count", count); + + return json_data; + } + +json_object *json_object_hostdependencylist(unsigned format_options, int start, + int count, host *master_host, hostgroup *master_hostgroup, + host *dependent_host, hostgroup *dependent_hostgroup) { + + json_object *json_data; + json_array *json_hostdependencylist; +#ifdef JSON_NAGIOS_4X + int x; +#endif + json_object *json_hostdependency_details; + hostdependency *temp_hostdependency; + int current = 0; + int counted = 0; + + json_data = json_new_object(); + json_object_append_object(json_data, "selectors", + json_object_hostdependency_selectors(start, count, + master_host, master_hostgroup, dependent_host, + dependent_hostgroup)); + + json_hostdependencylist = json_new_array(); + +#ifdef JSON_NAGIOS_4X + for(x = 0; x < num_objects.hostdependencies; x++) { + temp_hostdependency = hostdependency_ary[ x]; +#else + for(temp_hostdependency = hostdependency_list; + temp_hostdependency != NULL; + temp_hostdependency = temp_hostdependency->next) { +#endif + + if(!json_object_hostdependency_passes_selection( + temp_hostdependency, master_host, master_hostgroup, + dependent_host, dependent_hostgroup)) { + continue; + } + + /* If the current item passes the start and limit tests, display it */ + if( passes_start_and_count_limits(start, count, current, counted)) { + json_hostdependency_details = json_new_object(); + json_object_hostdependency_details(json_hostdependency_details, + format_options, temp_hostdependency); + json_array_append_object(json_hostdependencylist, + json_hostdependency_details); + } + counted++; + current++; + } + + json_object_append_array(json_data, "hostdependencylist", + json_hostdependencylist); + + return json_data; + } + +void json_object_hostdependency_details(json_object *json_details, + unsigned format_options, hostdependency *temp_hostdependency) { + + json_object_append_integer(json_details, "dependency_type", + temp_hostdependency->dependency_type); + json_object_append_string(json_details, "dependent_host_name", + &percent_escapes, temp_hostdependency->dependent_host_name); + json_object_append_string(json_details, "host_name", + &percent_escapes, temp_hostdependency->host_name); + json_object_append_string(json_details, "dependency_period", + &percent_escapes, temp_hostdependency->dependency_period); + json_object_append_boolean(json_details, "inherits_parent", + temp_hostdependency->inherits_parent); + +#ifdef JSON_NAGIOS_4X +#if 0 + if( CORE3_COMPATIBLE) { + json_object_append_boolean(json_details, "fail_on_up", + flag_isset(temp_hostdependency->failure_options, OPT_UP)); + json_object_append_boolean(json_details, "fail_on_down", + flag_isset(temp_hostdependency->failure_options, OPT_DOWN)); + json_object_append_boolean(json_details, "fail_on_unreachable", + flag_isset(temp_hostdependency->failure_options, + OPT_UNREACHABLE)); + json_object_append_boolean(json_details, "fail_on_pending", + flag_isset(temp_hostdependency->failure_options, OPT_PENDING)); + } + else { +#endif + json_bitmask(json_details, format_options, "failure_options", + temp_hostdependency->failure_options, svm_option_types); +#if 0 + } +#endif +#else + json_object_append_boolean(json_details, "fail_on_up", + temp_hostdependency->fail_on_up); + json_object_append_boolean(json_details, "fail_on_down", + temp_hostdependency->fail_on_down); + json_object_append_boolean(json_details, "fail_on_unreachable", + temp_hostdependency->fail_on_unreachable); + json_object_append_boolean(json_details, "fail_on_pending", + temp_hostdependency->fail_on_pending); +#endif + } + +int json_object_hostescalation_passes_selection(hostescalation *temp_hostescalation, + host *match_host, hostgroup *match_hostgroup, contact *match_contact, + contactgroup *match_contactgroup) { + + int found; + hostsmember *temp_hostsmember; + + /* Skip if the hostescalation is not for the specified host */ + if( NULL != match_host && + strcmp( temp_hostescalation->host_name, match_host->name)) { + return 0; + } + + if(NULL != match_hostgroup) { + found = 0; + for(temp_hostsmember = match_hostgroup->members; + temp_hostsmember != NULL; + temp_hostsmember = temp_hostsmember->next) { + if(!strcmp(temp_hostsmember->host_name, + temp_hostescalation->host_name)) { + found = 1; + break; + } + } + if(0 == found) { + return 0; + } + } + + /* If a contact was specified, skip this host escalation if it does + not have the contact specified */ + if( NULL != match_contact && + ( FALSE == is_contact_for_host_escalation(temp_hostescalation, + match_contact))) { + return 0; + } + + /* If a contactgroup was specified, skip this host escalation if + it does not have the contactgroup specified */ + if(NULL != match_contactgroup && (FALSE == + is_contactgroup_for_host_escalation(temp_hostescalation, + match_contactgroup))) { + return 0; + } + + return 1; + } + +json_object *json_object_hostescalation_selectors(int start, int count, + host *match_host, hostgroup *match_hostgroup, contact *match_contact, + contactgroup *match_contactgroup) { + + json_object *json_selectors; + + json_selectors = json_new_object(); + + if( start > 0) { + json_object_append_integer(json_selectors, "start", start); + } + if( count > 0) { + json_object_append_integer(json_selectors, "count", count); + } + if( NULL != match_host) { + json_object_append_string(json_selectors, "hostname", &percent_escapes, + match_host->name); + } + if(NULL != match_hostgroup) { + json_object_append_string(json_selectors, "hostgroup", + &percent_escapes, match_hostgroup->group_name); + } + if( NULL != match_contact) { + json_object_append_string(json_selectors, "contact", + &percent_escapes, match_contact->name); + } + if( NULL != match_contactgroup) { + json_object_append_string(json_selectors, "contactgroup", + &percent_escapes, match_contactgroup->group_name); + } + + return json_selectors; + } + +json_object *json_object_hostescalationcount(host *match_host, + hostgroup *match_hostgroup, contact *match_contact, + contactgroup *match_contactgroup) { + + json_object *json_data; +#ifdef JSON_NAGIOS_4X + int x; +#endif + hostescalation *temp_hostescalation; + int count = 0; + + json_data = json_new_object(); + json_object_append_object(json_data, "selectors", + json_object_hostescalation_selectors(0, 0, match_host, + match_hostgroup, match_contact, match_contactgroup)); + +#ifdef JSON_NAGIOS_4X + for(x = 0; x < num_objects.hostescalations; x++) { + temp_hostescalation = hostescalation_ary[ x]; +#else + for(temp_hostescalation = hostescalation_list; + temp_hostescalation != NULL; + temp_hostescalation = temp_hostescalation->next) { +#endif + if(json_object_hostescalation_passes_selection(temp_hostescalation, + match_host, match_hostgroup, match_contact, + match_contactgroup) == 0) { + continue; + } + + count++; + } + + json_object_append_integer(json_data, "count", count); + + return json_data; + } + +json_object *json_object_hostescalationlist(unsigned format_options, int start, + int count, host *match_host, hostgroup *match_hostgroup, + contact *match_contact, contactgroup *match_contactgroup) { + + json_object *json_data; + json_array *json_hostescalationlist; + json_object *json_hostescalation_details; +#ifdef JSON_NAGIOS_4X + int x; +#endif + hostescalation *temp_hostescalation; + int current = 0; + int counted = 0; + + json_data = json_new_object(); + json_object_append_object(json_data, "selectors", + json_object_hostescalation_selectors(start, count, match_host, + match_hostgroup, match_contact, match_contactgroup)); + + json_hostescalationlist = json_new_array(); + +#ifdef JSON_NAGIOS_4X + for(x = 0; x < num_objects.hostescalations; x++) { + temp_hostescalation = hostescalation_ary[ x]; +#else + for(temp_hostescalation = hostescalation_list; + temp_hostescalation != NULL; + temp_hostescalation = temp_hostescalation->next) { +#endif + if(json_object_hostescalation_passes_selection(temp_hostescalation, + match_host, match_hostgroup, match_contact, + match_contactgroup) == 0) { + continue; + } + + + /* If the current item passes the start and limit tests, display it */ + if( passes_start_and_count_limits(start, count, current, counted)) { + json_hostescalation_details = json_new_object(); + json_object_hostescalation_details(json_hostescalation_details, + format_options, temp_hostescalation); + json_array_append_object(json_hostescalationlist, + json_hostescalation_details); + } + counted++; + current++; + } + + json_object_append_array(json_data, "hostescalationlist", + json_hostescalationlist); + + return json_data; + } + +void json_object_hostescalation_details(json_object *json_details, + unsigned format_options, hostescalation *temp_hostescalation) { + + json_array *json_contactgroups; + json_array *json_contacts; + contactgroupsmember *temp_contact_groupsmember; + contactsmember *temp_contactsmember; + + json_object_append_string(json_details, "host_name", &percent_escapes, + temp_hostescalation->host_name); + json_object_append_integer(json_details, "first_notification", + temp_hostescalation->first_notification); + json_object_append_integer(json_details, "last_notification", + temp_hostescalation->last_notification); + json_object_append_real(json_details, "notification_interval", + temp_hostescalation->notification_interval); + json_object_append_string(json_details, "escalation_period", + &percent_escapes, temp_hostescalation->escalation_period); + +#ifdef JSON_NAGIOS_4X +#if 0 + if( CORE3_COMPATIBLE) { + json_object_append_boolean(json_details, "escalate_on_recovery", + flag_isset(temp_hostescalation->escalation_options, + OPT_RECOVERY)); + json_object_append_boolean(json_details, "escalate_on_down", + flag_isset(temp_hostescalation->escalation_options, OPT_DOWN)); + json_object_append_boolean(json_details, "escalate_on_unreachable", + flag_isset(temp_hostescalation->escalation_options, + OPT_UNREACHABLE)); + } + else { +#endif + json_bitmask(json_details, format_options, "escalation_options", + temp_hostescalation->escalation_options, svm_option_types); +#if 0 + } +#endif +#else + json_object_append_boolean(json_details, "escalate_on_recovery", + temp_hostescalation->escalate_on_recovery); + json_object_append_boolean(json_details, "escalate_on_down", + temp_hostescalation->escalate_on_down); + json_object_append_boolean(json_details, "escalate_on_unreachable", + temp_hostescalation->escalate_on_unreachable); +#endif + + json_contactgroups = json_new_array(); + for(temp_contact_groupsmember = temp_hostescalation->contact_groups; + temp_contact_groupsmember != NULL; + temp_contact_groupsmember = temp_contact_groupsmember->next) { + json_array_append_string(json_contactgroups, &percent_escapes, + temp_contact_groupsmember->group_name); + } + json_object_append_array(json_details, "contact_groups", json_contactgroups); + + json_contacts = json_new_array(); + for(temp_contactsmember = temp_hostescalation->contacts; + temp_contactsmember != NULL; + temp_contactsmember = temp_contactsmember->next) { + json_array_append_string(json_contacts, &percent_escapes, + temp_contactsmember->contact_name); + } + json_object_append_array(json_details, "contacts", json_contacts); + } diff --git a/cgi/outages.c b/cgi/outages.c index ee274ba..1f523ea 100644 --- a/cgi/outages.c +++ b/cgi/outages.c @@ -2,8 +2,6 @@ * * OUTAGES.C - Nagios Network Outages CGI * - * Copyright (c) 1999-2008 Ethan Galstad (egalstad@nagios.org) - * Last Modified: 01-08-2008 * * License: * @@ -32,10 +30,7 @@ #include "../include/cgiauth.h" extern int refresh_rate; -extern time_t program_start; -extern host *host_list; -extern service *service_list; extern hoststatus *hoststatus_list; extern servicestatus *servicestatus_list; @@ -44,7 +39,6 @@ extern char url_html_path[MAX_FILENAME_LENGTH]; extern char url_stylesheets_path[MAX_FILENAME_LENGTH]; extern char url_images_path[MAX_FILENAME_LENGTH]; extern char url_logo_images_path[MAX_FILENAME_LENGTH]; -extern char log_file[MAX_FILENAME_LENGTH]; /* HOSTOUTAGE structure */ @@ -101,51 +95,13 @@ int display_header = TRUE; int main(void) { - int result = OK; - - /* get the arguments passed in the URL */ process_cgivars(); /* reset internal variables */ reset_cgi_vars(); - /* read the CGI configuration file */ - result = read_cgi_config_file(get_cgi_config_location()); - if(result == ERROR) { - document_header(FALSE); - cgi_config_file_error(get_cgi_config_location()); - document_footer(); - return ERROR; - } - - /* read the main configuration file */ - result = read_main_config_file(main_config_file); - if(result == ERROR) { - document_header(FALSE); - main_config_file_error(main_config_file); - document_footer(); - return ERROR; - } - - /* read all object configuration data */ - result = read_all_object_configuration_data(main_config_file, READ_ALL_OBJECT_DATA); - if(result == ERROR) { - document_header(FALSE); - object_data_error(); - document_footer(); - return ERROR; - } - - /* read all status data */ - result = read_all_status_data(get_cgi_config_location(), READ_ALL_STATUS_DATA); - if(result == ERROR) { - document_header(FALSE); - status_data_error(); - document_footer(); - free_memory(); - return ERROR; - } + cgi_init(document_header, document_footer, READ_ALL_OBJECT_DATA, READ_ALL_STATUS_DATA); document_header(TRUE); @@ -215,7 +171,7 @@ void document_header(int use_stylesheet) { get_time_string(&expire_time, date_time, (int)sizeof(date_time), HTTP_DATE_TIME); printf("Expires: %s\r\n", date_time); - printf("Content-type: text/html\r\n\r\n"); + printf("Content-type: text/html; charset=utf-8\r\n\r\n"); if(embedded == TRUE) return; @@ -269,7 +225,6 @@ int process_cgivars(void) { /* do some basic length checking on the variable identifier to prevent buffer overflows */ if(strlen(variables[x]) >= MAX_INPUT_BUFFER - 1) { - x++; continue; } @@ -313,8 +268,8 @@ void display_network_outages(void) { hostoutage *temp_hostoutage; hoststatus *temp_hoststatus; int odd = 0; - char *bg_class = ""; - char *status = ""; + const char *bg_class = ""; + const char *status = ""; int days; int hours; int minutes; @@ -326,6 +281,7 @@ void display_network_outages(void) { int total_entries = 0; /* user must be authorized for all hosts.. */ +/* if(is_authorized_for_all_hosts(¤t_authdata) == FALSE) { printf("

It appears as though you do not have permission to view information you requested...

\n"); @@ -334,6 +290,7 @@ void display_network_outages(void) { return; } +*/ /* find all hosts that are causing network outages */ find_hosts_causing_outages(); @@ -375,7 +332,7 @@ void display_network_outages(void) { continue; /* make sure we only caught valid state types */ - if(temp_hoststatus->status != HOST_DOWN && temp_hoststatus->status != HOST_UNREACHABLE) + if(temp_hoststatus->status != SD_HOST_DOWN && temp_hoststatus->status != SD_HOST_UNREACHABLE) continue; total_entries++; @@ -389,9 +346,9 @@ void display_network_outages(void) { bg_class = "dataEven"; } - if(temp_hoststatus->status == HOST_UNREACHABLE) + if(temp_hoststatus->status == SD_HOST_UNREACHABLE) status = "UNREACHABLE"; - else if(temp_hoststatus->status == HOST_DOWN) + else if(temp_hoststatus->status == SD_HOST_DOWN) status = "DOWN"; printf("\n", bg_class); @@ -469,7 +426,7 @@ void find_hosts_causing_outages(void) { for(temp_hoststatus = hoststatus_list; temp_hoststatus != NULL; temp_hoststatus = temp_hoststatus->next) { /* check only hosts that are not up and not pending */ - if(temp_hoststatus->status != HOST_UP && temp_hoststatus->status != HOST_PENDING) { + if(temp_hoststatus->status != SD_HOST_UP && temp_hoststatus->status != HOST_PENDING) { /* find the host entry */ temp_host = find_host(temp_hoststatus->host_name); @@ -477,6 +434,9 @@ void find_hosts_causing_outages(void) { if(temp_host == NULL) continue; + if (!is_authorized_for_host(temp_host, ¤t_authdata)) + continue; + /* if the route to this host is not blocked, it is a causing an outage */ if(is_route_to_host_blocked(temp_host) == FALSE) add_hostoutage(temp_host); @@ -622,7 +582,7 @@ int is_route_to_host_blocked(host *hst) { continue; /* at least one parent it up (or pending), so this host is not blocked */ - if(temp_hoststatus->status == HOST_UP || temp_hoststatus->status == HOST_PENDING) + if(temp_hoststatus->status == SD_HOST_UP || temp_hoststatus->status == HOST_PENDING) return FALSE; } diff --git a/cgi/showlog.c b/cgi/showlog.c index d249326..fcaaadb 100644 --- a/cgi/showlog.c +++ b/cgi/showlog.c @@ -2,8 +2,6 @@ * * SHOWLOG.C - Nagios Log File CGI * - * Copyright (c) 1999-2008 Ethan Galstad (egalstad@nagios.org) - * Last Modified: 01-08-2008 * * This CGI program will display the contents of the Nagios * log file. @@ -37,8 +35,6 @@ extern char url_html_path[MAX_FILENAME_LENGTH]; extern char url_images_path[MAX_FILENAME_LENGTH]; extern char url_stylesheets_path[MAX_FILENAME_LENGTH]; -extern int log_rotation_method; - extern int enable_splunk_integration; void document_header(int); @@ -61,7 +57,6 @@ int display_timebreaks = TRUE; int main(void) { - int result = OK; char temp_buffer[MAX_INPUT_BUFFER]; @@ -71,33 +66,7 @@ int main(void) { /* reset internal variables */ reset_cgi_vars(); - /* read the CGI configuration file */ - result = read_cgi_config_file(get_cgi_config_location()); - if(result == ERROR) { - document_header(FALSE); - cgi_config_file_error(get_cgi_config_location()); - document_footer(); - return ERROR; - } - - /* read the main configuration file */ - result = read_main_config_file(main_config_file); - if(result == ERROR) { - document_header(FALSE); - main_config_file_error(main_config_file); - document_footer(); - return ERROR; - } - - /* read all object configuration data */ - result = read_all_object_configuration_data(main_config_file, READ_ALL_OBJECT_DATA); - if(result == ERROR) { - document_header(FALSE); - object_data_error(); - document_footer(); - return ERROR; - } - + cgi_init(document_header, document_footer, READ_ALL_OBJECT_DATA, 0); document_header(TRUE); @@ -188,7 +157,7 @@ void document_header(int use_stylesheet) { get_time_string(&expire_time, date_time, (int)sizeof(date_time), HTTP_DATE_TIME); printf("Expires: %s\r\n", date_time); - printf("Content-type: text/html\r\n\r\n"); + printf("Content-type: text/html; charset=utf-8\r\n\r\n"); if(embedded == TRUE) return; @@ -547,4 +516,3 @@ int display_log(void) { return OK; } - diff --git a/cgi/status.c b/cgi/status.c index 849d938..fccb08b 100644 --- a/cgi/status.c +++ b/cgi/status.c @@ -2,8 +2,6 @@ * * STATUS.C - Nagios Status CGI * - * Copyright (c) 1999-2010 Ethan Galstad (egalstad@nagios.org) - * Last Modified: 08-05-2020 * * License: * @@ -34,7 +32,6 @@ extern int refresh_rate; extern int result_limit; -extern time_t program_start; extern char main_config_file[MAX_FILENAME_LENGTH]; extern char url_html_path[MAX_FILENAME_LENGTH]; @@ -44,7 +41,6 @@ extern char url_stylesheets_path[MAX_FILENAME_LENGTH]; extern char url_logo_images_path[MAX_FILENAME_LENGTH]; extern char url_media_path[MAX_FILENAME_LENGTH]; extern char url_js_path[MAX_FILENAME_LENGTH]; -extern char log_file[MAX_FILENAME_LENGTH]; extern char *service_critical_sound; extern char *service_warning_sound; @@ -60,10 +56,9 @@ extern int suppress_alert_window; extern int enable_splunk_integration; -extern host *host_list; -extern service *service_list; -extern hostgroup *hostgroup_list; -extern servicegroup *servicegroup_list; +extern int navbar_search_addresses; +extern int navbar_search_aliases; + extern hoststatus *hoststatus_list; extern servicestatus *servicestatus_list; @@ -128,8 +123,8 @@ void show_hostgroup_grids(void); void show_hostgroup_grid(hostgroup *); void show_filters(void); -void create_pagenumbers(int total_entries, int visible_entries, char *temp_url, int type_service); -void create_page_limiter(int result_limit, char *temp_url); +void create_pagenumbers(int total_entries, char *temp_url,int type_service); +void create_page_limiter(int result_limit,char *temp_url); int passes_host_properties_filter(hoststatus *); int passes_service_properties_filter(servicestatus *); @@ -144,6 +139,7 @@ time_t current_time; char alert_message[MAX_MESSAGE_BUFFER]; char *host_name = NULL; +char *host_address = NULL; char *host_filter = NULL; char *hostgroup_name = NULL; char *servicegroup_name = NULL; @@ -167,17 +163,18 @@ int limit_results = TRUE; int service_status_types = SERVICE_PENDING | SERVICE_OK | SERVICE_UNKNOWN | SERVICE_WARNING | SERVICE_CRITICAL; int all_service_status_types = SERVICE_PENDING | SERVICE_OK | SERVICE_UNKNOWN | SERVICE_WARNING | SERVICE_CRITICAL; -int host_status_types = HOST_PENDING | HOST_UP | HOST_DOWN | HOST_UNREACHABLE; -int all_host_status_types = HOST_PENDING | HOST_UP | HOST_DOWN | HOST_UNREACHABLE; +int host_status_types = HOST_PENDING | SD_HOST_UP | SD_HOST_DOWN | SD_HOST_UNREACHABLE; +int all_host_status_types = HOST_PENDING | SD_HOST_UP | SD_HOST_DOWN | SD_HOST_UNREACHABLE; int all_service_problems = SERVICE_UNKNOWN | SERVICE_WARNING | SERVICE_CRITICAL; -int all_host_problems = HOST_DOWN | HOST_UNREACHABLE; +int all_host_problems = SD_HOST_DOWN | SD_HOST_UNREACHABLE; unsigned long host_properties = 0L; unsigned long service_properties = 0L; - +int num_services = 0; +int num_hosts = 0; int sort_type = SORT_NONE; int sort_option = SORT_HOSTNAME; @@ -194,7 +191,6 @@ int display_header = TRUE; int main(void) { - int result = OK; char *sound = NULL; host *temp_host = NULL; hostgroup *temp_hostgroup = NULL; @@ -212,51 +208,16 @@ int main(void) { /* reset internal variables */ reset_cgi_vars(); - /* read the CGI configuration file */ - result = read_cgi_config_file(get_cgi_config_location()); - if(result == ERROR) { - document_header(FALSE); - cgi_config_file_error(get_cgi_config_location()); - document_footer(); - return ERROR; - } - - /* read the main configuration file */ - result = read_main_config_file(main_config_file); - if(result == ERROR) { - document_header(FALSE); - main_config_file_error(main_config_file); - document_footer(); - return ERROR; - } - - /* read all object configuration data */ - result = read_all_object_configuration_data(main_config_file, READ_ALL_OBJECT_DATA); - if(result == ERROR) { - document_header(FALSE); - object_data_error(); - document_footer(); - return ERROR; - } - - /* read all status data */ - result = read_all_status_data(get_cgi_config_location(), READ_ALL_STATUS_DATA); - if(result == ERROR) { - document_header(FALSE); - status_data_error(); - document_footer(); - free_memory(); - return ERROR; - } + cgi_init(document_header, document_footer, READ_ALL_OBJECT_DATA, READ_ALL_STATUS_DATA); /* initialize macros */ init_macros(); - document_header(TRUE); - /* get authentication information */ get_authentication_information(¤t_authdata); + document_header(TRUE); + /* if a navbar search was performed, find the host by name, address or partial name */ if(navbar_search == TRUE) { if(host_name != NULL && NULL != strstr(host_name, "*")) { @@ -281,8 +242,15 @@ int main(void) { if(is_authorized_for_host(temp_host, ¤t_authdata) == FALSE) continue; if(!strcmp(host_name, temp_host->address)) { - free(host_name); - host_name = strdup(temp_host->name); + host_address = strdup(temp_host->address); + host_filter = malloc(sizeof(char) * (strlen(host_address) * 2 + 3)); + len = strlen(host_address); + for(i = 0; i < len; i++, regex_i++) { + host_filter[regex_i] = host_address[i]; + } + host_filter[0] = '^'; + host_filter[regex_i++] = '$'; + host_filter[regex_i] = '\0'; break; } } @@ -473,13 +441,18 @@ int main(void) { else if(problem_services_unknown == 0 && problem_services_warning == 0 && problem_services_critical == 0 && problem_hosts_down == 0 && problem_hosts_unreachable == 0 && normal_sound != NULL) sound = normal_sound; if(sound != NULL) { - printf("", url_media_path, sound); + printf("", url_media_path, sound); printf("", url_media_path, sound); printf(""); printf(""); printf(""); } + /* Special case where there is a host with no services */ + if(display_type == DISPLAY_HOSTS && num_services == 0 && num_hosts != 0 && display_header) { + display_type = DISPLAY_HOSTGROUPS; + group_style_type = STYLE_HOST_DETAIL; + } /* bottom portion of screen - service or hostgroup detail */ if(display_type == DISPLAY_HOSTS) @@ -525,6 +498,7 @@ int main(void) { void document_header(int use_stylesheet) { char date_time[MAX_DATETIME_LENGTH]; + char *vidurl = NULL; time_t expire_time; printf("Cache-Control: no-store\r\n"); @@ -538,7 +512,7 @@ void document_header(int use_stylesheet) { get_time_string(&expire_time, date_time, (int)sizeof(date_time), HTTP_DATE_TIME); printf("Expires: %s\r\n", date_time); - printf("Content-type: text/html\r\n\r\n"); + printf("Content-type: text/html; charset=utf-8\r\n\r\n"); if(embedded == TRUE) return; @@ -553,14 +527,42 @@ void document_header(int use_stylesheet) { if(use_stylesheet == TRUE) { printf("\n", url_stylesheets_path, COMMON_CSS); printf("\n", url_stylesheets_path, STATUS_CSS); + printf("\n", url_stylesheets_path, NAGFUNCS_CSS); } /* added jquery library 1/31/2012 */ printf("\n", url_js_path, JQUERY_JS); + printf("\n", url_js_path, NAGFUNCS_JS); /* JS function to append content to elements on page */ printf("\n"); printf("\n"); @@ -600,7 +602,6 @@ int process_cgivars(void) { /* do some basic length checking on the variable identifier to prevent buffer overflows */ if(strlen(variables[x]) >= MAX_INPUT_BUFFER - 1) { - x++; continue; } @@ -834,7 +835,10 @@ void show_service_status_totals(void) { service *temp_service; host *temp_host; int count_service; + regex_t preg_hostname; + if(host_filter != NULL) + regcomp(&preg_hostname, host_filter, REG_ICASE); /* check the status of all services... */ for(temp_servicestatus = servicestatus_list; temp_servicestatus != NULL; temp_servicestatus = temp_servicestatus->next) { @@ -849,10 +853,30 @@ void show_service_status_totals(void) { count_service = 0; - if(display_type == DISPLAY_HOSTS && (show_all_hosts == TRUE || !strcmp(host_name, temp_servicestatus->host_name))) - count_service = 1; - else if(display_type == DISPLAY_SERVICEGROUPS && (show_all_servicegroups == TRUE || (is_service_member_of_servicegroup(find_servicegroup(servicegroup_name), temp_service) == TRUE))) - count_service = 1; + if(display_type == DISPLAY_HOSTS) { + if (show_all_hosts == TRUE) + count_service = 1; + else if (!strcmp(host_name, temp_servicestatus->host_name)) + count_service = 1; + else if(host_filter != NULL && 0 == regexec(&preg_hostname, temp_servicestatus->host_name, 0, NULL, 0)) + count_service = 1; + else if (!strcmp(host_name, temp_host->address)) + count_service = 1; + else if(host_filter != NULL && navbar_search_addresses == TRUE && 0 == regexec(&preg_hostname, temp_host->address, 0, NULL, 0)) + count_service = 1; + else if (!strcmp(host_name, temp_host->alias)) + count_service = 1; + else if(host_filter != NULL && navbar_search_aliases == TRUE && 0 == regexec(&preg_hostname, temp_host->alias, 0, NULL, 0)) + count_service = 1; + } + else if(display_type == DISPLAY_SERVICEGROUPS) { + if(show_all_servicegroups == TRUE) { + count_service = 1; + } + else if(is_host_member_of_servicegroup(find_servicegroup(servicegroup_name), temp_host) == TRUE) { + count_service = 1; + } + } else if(display_type == DISPLAY_HOSTGROUPS && (show_all_hostgroups == TRUE || (is_host_member_of_hostgroup(find_hostgroup(hostgroup_name), temp_host) == TRUE))) count_service = 1; @@ -860,17 +884,17 @@ void show_service_status_totals(void) { if(temp_servicestatus->status == SERVICE_CRITICAL) { total_critical++; - if(temp_servicestatus->problem_has_been_acknowledged == FALSE && (temp_servicestatus->checks_enabled == TRUE || temp_servicestatus->accept_passive_service_checks == TRUE) && temp_servicestatus->notifications_enabled == TRUE && temp_servicestatus->scheduled_downtime_depth == 0) + if(temp_servicestatus->problem_has_been_acknowledged == FALSE && (temp_servicestatus->checks_enabled == TRUE || temp_servicestatus->accept_passive_checks == TRUE) && temp_servicestatus->notifications_enabled == TRUE && temp_servicestatus->scheduled_downtime_depth == 0) problem_services_critical++; } else if(temp_servicestatus->status == SERVICE_WARNING) { total_warning++; - if(temp_servicestatus->problem_has_been_acknowledged == FALSE && (temp_servicestatus->checks_enabled == TRUE || temp_servicestatus->accept_passive_service_checks == TRUE) && temp_servicestatus->notifications_enabled == TRUE && temp_servicestatus->scheduled_downtime_depth == 0) + if(temp_servicestatus->problem_has_been_acknowledged == FALSE && (temp_servicestatus->checks_enabled == TRUE || temp_servicestatus->accept_passive_checks == TRUE) && temp_servicestatus->notifications_enabled == TRUE && temp_servicestatus->scheduled_downtime_depth == 0) problem_services_warning++; } else if(temp_servicestatus->status == SERVICE_UNKNOWN) { total_unknown++; - if(temp_servicestatus->problem_has_been_acknowledged == FALSE && (temp_servicestatus->checks_enabled == TRUE || temp_servicestatus->accept_passive_service_checks == TRUE) && temp_servicestatus->notifications_enabled == TRUE && temp_servicestatus->scheduled_downtime_depth == 0) + if(temp_servicestatus->problem_has_been_acknowledged == FALSE && (temp_servicestatus->checks_enabled == TRUE || temp_servicestatus->accept_passive_checks == TRUE) && temp_servicestatus->notifications_enabled == TRUE && temp_servicestatus->scheduled_downtime_depth == 0) problem_services_unknown++; } else if(temp_servicestatus->status == SERVICE_OK) @@ -883,6 +907,7 @@ void show_service_status_totals(void) { } total_services = total_ok + total_unknown + total_warning + total_critical + total_pending; + num_services = total_services; total_problems = total_unknown + total_warning + total_critical; @@ -896,9 +921,11 @@ void show_service_status_totals(void) { printf("\n"); printf("\n"); printf("\n"); printf("\n"); printf("", url_encode(temp_status->description), url_images_path, ACKNOWLEDGEMENT_ICON, STATUS_ICON_WIDTH, STATUS_ICON_HEIGHT); } - if(temp_status->checks_enabled == FALSE && temp_status->accept_passive_service_checks == FALSE) { + if(temp_status->checks_enabled == FALSE && temp_status->accept_passive_checks == FALSE) { printf("", url_encode(temp_status->description), url_images_path, DISABLED_ICON, STATUS_ICON_WIDTH, STATUS_ICON_HEIGHT); } @@ -1936,7 +2010,7 @@ void show_service_detail(void) { } else { /* do page numbers if applicable */ - create_pagenumbers(total_entries, visible_entries, temp_url, TRUE); + create_pagenumbers(total_entries,temp_url,TRUE); } return; @@ -1954,8 +2028,8 @@ void show_host_detail(void) { char temp_buffer[MAX_INPUT_BUFFER]; char temp_url[MAX_INPUT_BUFFER]; char *processed_string = NULL; - char *status_class = ""; - char *status_bg_class = ""; + const char *status_class = ""; + const char *status_bg_class = ""; hoststatus *temp_status = NULL; hostgroup *temp_hostgroup = NULL; host *temp_host = NULL; @@ -1973,8 +2047,11 @@ void show_host_detail(void) { int duration_error = FALSE; int total_entries = 0; int visible_entries = 0; + regex_t preg_hostname; // int show_host = FALSE; + if(host_filter != NULL) + regcomp(&preg_hostname, host_filter, REG_ICASE); /* sort the host list if necessary */ if(sort_type != SORT_NONE) { @@ -2081,12 +2158,12 @@ void show_host_detail(void) { */ /* GET input can override cgi.cfg */ - if(limit_results == TRUE) + if(limit_results==TRUE) result_limit = temp_result_limit ? temp_result_limit : result_limit; else result_limit = 0; /* select box to set result limit */ - create_page_limiter(result_limit, temp_url); + create_page_limiter(result_limit,temp_url); /* the main list of hosts */ @@ -2142,6 +2219,16 @@ void show_host_detail(void) { if(is_authorized_for_host(temp_host, ¤t_authdata) == FALSE) continue; + if (show_all_hosts == FALSE) { + if(host_filter != NULL) { + if (regexec(&preg_hostname, temp_host->name, 0, NULL, 0) != 0 + && regexec(&preg_hostname, temp_host->address, 0, NULL, 0) != 0 + && regexec(&preg_hostname, temp_host->alias, 0, NULL, 0) != 0) + continue; + } else if (strcmp(host_name, temp_host->name)) + continue; + } + user_has_seen_something = TRUE; /* see if we should display services for hosts with this type of status */ @@ -2170,7 +2257,7 @@ void show_host_detail(void) { if(result_limit == 0) limit_results = FALSE; - if((limit_results == TRUE) && ((total_entries < page_start) || (total_entries >= (page_start + result_limit)))) { + if( (limit_results == TRUE) && ( (total_entries < page_start) || (total_entries > (page_start + result_limit)) ) ) { continue; } @@ -2200,12 +2287,12 @@ void show_host_detail(void) { status_class = "PENDING"; status_bg_class = (odd) ? "Even" : "Odd"; } - else if(temp_status->status == HOST_UP) { + else if(temp_status->status == SD_HOST_UP) { strncpy(status, "UP", sizeof(status)); status_class = "HOSTUP"; status_bg_class = (odd) ? "Even" : "Odd"; } - else if(temp_status->status == HOST_DOWN) { + else if(temp_status->status == SD_HOST_DOWN) { strncpy(status, "DOWN", sizeof(status)); status_class = "HOSTDOWN"; if(temp_status->problem_has_been_acknowledged == TRUE) @@ -2215,7 +2302,7 @@ void show_host_detail(void) { else status_bg_class = "BGDOWN"; } - else if(temp_status->status == HOST_UNREACHABLE) { + else if(temp_status->status == SD_HOST_UNREACHABLE) { strncpy(status, "UNREACHABLE", sizeof(status)); status_class = "HOSTUNREACHABLE"; if(temp_status->problem_has_been_acknowledged == TRUE) @@ -2256,8 +2343,13 @@ void show_host_detail(void) { if(temp_status->notifications_enabled == FALSE) { printf("", EXTINFO_CGI, DISPLAY_HOST_INFO, url_encode(temp_status->host_name), url_images_path, NOTIFICATIONS_DISABLED_ICON, STATUS_ICON_WIDTH, STATUS_ICON_HEIGHT); } - if(temp_status->checks_enabled == FALSE) { - printf("", EXTINFO_CGI, DISPLAY_HOST_INFO, url_encode(temp_status->host_name), url_images_path, DISABLED_ICON, STATUS_ICON_WIDTH, STATUS_ICON_HEIGHT); + if(temp_status->checks_enabled == FALSE && temp_status->accept_passive_checks == FALSE) { + printf("", url_images_path, DISABLED_ICON, STATUS_ICON_WIDTH, STATUS_ICON_HEIGHT); + } + else if(temp_status->checks_enabled == FALSE) { + printf("", url_images_path, PASSIVE_ONLY_ICON, STATUS_ICON_WIDTH, STATUS_ICON_HEIGHT); } if(temp_status->is_flapping == TRUE) { printf("", EXTINFO_CGI, DISPLAY_HOST_INFO, url_encode(temp_status->host_name), url_images_path, FLAPPING_ICON, STATUS_ICON_WIDTH, STATUS_ICON_HEIGHT); @@ -2373,7 +2465,7 @@ void show_host_detail(void) { else { /* do page numbers if applicable */ - create_pagenumbers(total_entries, visible_entries, temp_url, FALSE); + create_pagenumbers(total_entries,temp_url,FALSE); } return; } @@ -2547,6 +2639,10 @@ void show_servicegroup_overview(servicegroup *temp_servicegroup) { if(temp_host == NULL) continue; + /* make sure user has rights to view this host */ + if(is_authorized_for_host(temp_host, ¤t_authdata) == FALSE) + continue; + /* skip this if it isn't a new host... */ if(temp_host == last_host) continue; @@ -2697,7 +2793,7 @@ void show_servicegroup_summaries(void) { /* displays status summary information for a specific servicegroup */ void show_servicegroup_summary(servicegroup *temp_servicegroup, int odd) { - char *status_bg_class = ""; + const char *status_bg_class = ""; if(odd == 1) status_bg_class = "Even"; @@ -2752,6 +2848,10 @@ void show_servicegroup_host_totals_summary(servicegroup *temp_servicegroup) { if(temp_host == NULL) continue; + /* make sure user has rights to view this host */ + if(is_authorized_for_host(temp_host, ¤t_authdata) == FALSE) + continue; + /* skip this if it isn't a new host... */ if(temp_host == last_host) continue; @@ -2771,10 +2871,10 @@ void show_servicegroup_host_totals_summary(servicegroup *temp_servicegroup) { problem = TRUE; - if(temp_hoststatus->status == HOST_UP) + if(temp_hoststatus->status == SD_HOST_UP) hosts_up++; - else if(temp_hoststatus->status == HOST_DOWN) { + else if(temp_hoststatus->status == SD_HOST_DOWN) { if(temp_hoststatus->scheduled_downtime_depth > 0) { hosts_down_scheduled++; problem = FALSE; @@ -2792,7 +2892,7 @@ void show_servicegroup_host_totals_summary(servicegroup *temp_servicegroup) { hosts_down++; } - else if(temp_hoststatus->status == HOST_UNREACHABLE) { + else if(temp_hoststatus->status == SD_HOST_UNREACHABLE) { if(temp_hoststatus->scheduled_downtime_depth > 0) { hosts_unreachable_scheduled++; problem = FALSE; @@ -2820,7 +2920,7 @@ void show_servicegroup_host_totals_summary(servicegroup *temp_servicegroup) { if(hosts_up > 0) { printf(""); - printf("", STATUS_CGI, url_encode(temp_servicegroup->group_name), HOST_UP, host_properties, hosts_up); + printf("", STATUS_CGI, url_encode(temp_servicegroup->group_name), SD_HOST_UP, host_properties, hosts_up); printf("\n"); } @@ -2829,21 +2929,21 @@ void show_servicegroup_host_totals_summary(servicegroup *temp_servicegroup) { printf("
Type:\n"); @@ -992,7 +1011,7 @@ void document_header(int use_stylesheet) { get_time_string(&expire_time, date_time, sizeof(date_time), HTTP_DATE_TIME); printf("Expires: %s\r\n", date_time); - printf("Content-type: text/html\r\n\r\n"); + printf("Content-type: text/html; charset=utf-8\r\n\r\n"); if(embedded == TRUE) return; @@ -1014,7 +1033,11 @@ void document_header(int use_stylesheet) { printf("\n"); /* include user SSI header */ +#ifdef LEGACY_GRAPHICAL_CGIS include_ssi_files(HISTOGRAM_CGI, SSI_HEADER); +#else + include_ssi_files(LEGACY_HISTOGRAM_CGI, SSI_HEADER); +#endif printf("
\n"); } @@ -1047,7 +1070,11 @@ void document_footer(void) { if(mode == CREATE_HTML) { /* include user SSI footer */ +#ifdef LEGACY_GRAPHICAL_CGIS include_ssi_files(HISTOGRAM_CGI, SSI_FOOTER); +#else + include_ssi_files(LEGACY_HISTOGRAM_CGI, SSI_FOOTER); +#endif printf("\n"); printf("\n"); @@ -1069,7 +1096,6 @@ int process_cgivars(void) { /* do some basic length checking on the variable identifier to prevent buffer overflows */ if(strlen(variables[x]) >= MAX_INPUT_BUFFER - 1) { - x++; continue; } diff --git a/cgi/history.c b/cgi/history.c index 2e8eee7..b254738 100644 --- a/cgi/history.c +++ b/cgi/history.c @@ -2,8 +2,6 @@ * * HISTORY.C - Nagios History CGI * - * Copyright (c) 1999-2008 Ethan Galstad (egalstad@nagios.org) - * Last Modified: 06-23-2008 * * This CGI program will display the history for the specified host. * If no host is specified, the history for all hosts will be displayed. @@ -57,8 +55,6 @@ extern char url_html_path[MAX_FILENAME_LENGTH]; extern char url_images_path[MAX_FILENAME_LENGTH]; extern char url_stylesheets_path[MAX_FILENAME_LENGTH]; -extern int log_rotation_method; - extern int enable_splunk_integration; authdata current_authdata; @@ -85,7 +81,6 @@ int display_downtime_alerts = TRUE; int main(void) { - int result = OK; char temp_buffer[MAX_INPUT_BUFFER]; char temp_buffer2[MAX_INPUT_BUFFER]; @@ -95,32 +90,7 @@ int main(void) { /* reset internal CGI variables */ reset_cgi_vars(); - /* read the CGI configuration file */ - result = read_cgi_config_file(get_cgi_config_location()); - if(result == ERROR) { - document_header(FALSE); - cgi_config_file_error(get_cgi_config_location()); - document_footer(); - return ERROR; - } - - /* read the main configuration file */ - result = read_main_config_file(main_config_file); - if(result == ERROR) { - document_header(FALSE); - main_config_file_error(main_config_file); - document_footer(); - return ERROR; - } - - /* read all object configuration data */ - result = read_all_object_configuration_data(main_config_file, READ_ALL_OBJECT_DATA); - if(result == ERROR) { - document_header(FALSE); - object_data_error(); - document_footer(); - return ERROR; - } + cgi_init(document_header, document_footer, READ_ALL_OBJECT_DATA, 0); document_header(TRUE); @@ -315,7 +285,7 @@ void document_header(int use_stylesheet) { get_time_string(&expire_time, date_time, sizeof(date_time), HTTP_DATE_TIME); printf("Expires: %s\r\n", date_time); - printf("Content-type: text/html\r\n\r\n"); + printf("Content-type: text/html; charset=utf-8\r\n\r\n"); if(embedded == TRUE) return; @@ -805,22 +775,22 @@ void get_history(void) { else if(display_type == DISPLAY_HOSTS) { if(history_type == HOST_HISTORY || history_type == SERVICE_HISTORY) { - snprintf(match1, sizeof(match1), - " HOST ALERT: %s;", host_name); - snprintf(match2, sizeof(match2), - " SERVICE ALERT: %s;", host_name); + snprintf(match1, sizeof( match1), + " HOST ALERT: %s;", host_name); + snprintf(match2, sizeof( match2), + " SERVICE ALERT: %s;", host_name); } else if(history_type == HOST_FLAPPING_HISTORY || history_type == SERVICE_FLAPPING_HISTORY) { - snprintf(match1, sizeof(match1), - " HOST FLAPPING ALERT: %s;", host_name); - snprintf(match2, sizeof(match2), - " SERVICE FLAPPING ALERT: %s;", host_name); + snprintf(match1, sizeof( match1), + " HOST FLAPPING ALERT: %s;", host_name); + snprintf(match2, sizeof( match2), + " SERVICE FLAPPING ALERT: %s;", host_name); } else if(history_type == HOST_DOWNTIME_HISTORY || history_type == SERVICE_DOWNTIME_HISTORY) { - snprintf(match1, sizeof(match1), - " HOST DOWNTIME ALERT: %s;", host_name); - snprintf(match2, sizeof(match2), - " SERVICE DOWNTIME ALERT: %s;", host_name); + snprintf(match1, sizeof( match1), + " HOST DOWNTIME ALERT: %s;", host_name); + snprintf(match2, sizeof( match2), + " SERVICE DOWNTIME ALERT: %s;", host_name); } if(show_all_hosts == TRUE) @@ -859,11 +829,11 @@ void get_history(void) { else if(display_type == DISPLAY_SERVICES) { if(history_type == SERVICE_HISTORY) - snprintf(match1, sizeof(match1), " SERVICE ALERT: %s;%s;", host_name, svc_description); + snprintf(match1, sizeof( match1), " SERVICE ALERT: %s;%s;", host_name, svc_description); else if(history_type == SERVICE_FLAPPING_HISTORY) - snprintf(match1, sizeof(match1), " SERVICE FLAPPING ALERT: %s;%s;", host_name, svc_description); + snprintf(match1, sizeof( match1), " SERVICE FLAPPING ALERT: %s;%s;", host_name, svc_description); else if(history_type == SERVICE_DOWNTIME_HISTORY) - snprintf(match1, sizeof(match1), " SERVICE DOWNTIME ALERT: %s;%s;", host_name, svc_description); + snprintf(match1, sizeof( match1), " SERVICE DOWNTIME ALERT: %s;%s;", host_name, svc_description); if(strstr(temp_buffer, match1) && (history_type == SERVICE_HISTORY || history_type == SERVICE_FLAPPING_HISTORY || history_type == SERVICE_DOWNTIME_HISTORY)) display_line = TRUE; diff --git a/cgi/jsonutils.c b/cgi/jsonutils.c new file mode 100644 index 0000000..f30bd24 --- /dev/null +++ b/cgi/jsonutils.c @@ -0,0 +1,1483 @@ +/************************************************************************** + * + * JSONUTILS.C - Utilities for Nagios CGIs for returning JSON-formatted + * object data + * + * Copyright (c) 2013 Nagios Enterprises, LLC + * Last Modified: 04-13-2013 + * + * License: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + *************************************************************************/ + +#include "../include/config.h" +#include "../include/common.h" +#include "../include/objects.h" +#include "../include/statusdata.h" +#include "../include/comments.h" + +#include "../include/cgiutils.h" +#include "../include/getcgi.h" +#include "../include/cgiauth.h" +#include "../include/jsonutils.h" + +/* Multiplier to increment the buffer in json_escape_string() to avoid frequent + repeated reallocations */ +#define BUF_REALLOC_MULTIPLIER 16 + +const char *result_types[] = { + "Success", + "Unable to Allocate Memory", + "Unable to Open File for Reading", + "Option Invalid", + "Option Missing", + "Option Value Missing", + "Option Value Invalid", + "Option Ignored" + }; + +const string_value_mapping svm_format_options[] = { + { "whitespace", JSON_FORMAT_WHITESPACE, + "Pad with whitespace to increase readability" }, + { "enumerate", JSON_FORMAT_ENUMERATE, + "Use textual representations of enumerated values rather than " + "raw numeric values" }, + { "bitmask", JSON_FORMAT_BITMASK, + "Use textual representations of bitmask values rather than " + "raw numeric values" }, + { "duration", JSON_FORMAT_DURATION, + "Use textual representations (xd xh xm xs) of duration values rather " + "than raw number of seconds" }, +#if 0 + { "datetime", JSON_FORMAT_DATETIME, + "Format date/time values according to the supplied strftime format " + "or '%%Y-%%m-%%d %%H:%%M:%%S' if no format specified" }, + { "date", JSON_FORMAT_DATE, + "Format dates according to the supplied strftime format or " + "default Javascript format (number of ms since the beginning of the " + "Unix epoch) if no format specified" }, + { "time", JSON_FORMAT_TIME, + "Format times according the supplied strftime format or " + "'%%H:%%M:%%S' in for format specified" }, +#endif + { NULL, -1, NULL }, + }; + +const string_value_mapping query_statuses[] = { + { "alpha", QUERY_STATUS_ALPHA, "Alpha" }, + { "beta", QUERY_STATUS_BETA, "Beta" }, + { "released", QUERY_STATUS_RELEASED, "Released" }, + { "deprecated", QUERY_STATUS_DEPRECATED, "Deprecated" }, + { NULL, -1, NULL }, + }; + +const string_value_mapping svm_host_statuses[] = { +#ifdef JSON_NAGIOS_4X + { "up", SD_HOST_UP, "HOST_UP" }, + { "down", SD_HOST_DOWN, "HOST_DOWN" }, + { "unreachable", SD_HOST_UNREACHABLE, "HOST_UNREACHABLE" }, +#else + { "up", HOST_UP, "HOST_UP" }, + { "down", HOST_DOWN, "HOST_DOWN" }, + { "unreachable", HOST_UNREACHABLE, "HOST_UNREACHABLE" }, +#endif + { "pending", HOST_PENDING, "HOST_PENDING" }, + { NULL, -1, NULL }, + }; + +/* Hard-coded values used because the HOST_UP/DOWN/UNREACHABLE + macros are host status (and include PENDING), not host state */ +const string_value_mapping svm_host_states[] = { + { "up", 0, "HOST_UP" }, + { "down", 1, "HOST_DOWN" }, + { "unreachable", 2, "HOST_UNREACHABLE" }, + { NULL, -1, NULL }, + }; + +const string_value_mapping svm_service_statuses[] = { + { "ok", SERVICE_OK, "SERVICE_OK" }, + { "warning", SERVICE_WARNING, "SERVICE_WARNING" }, + { "critical", SERVICE_CRITICAL, "SERVICE_CRITICAL" }, + { "unknown", SERVICE_UNKNOWN, "SERVICE_UNKNOWN" }, + { "pending", SERVICE_PENDING, "SERVICE_PENDING" }, + { NULL, -1, NULL }, + }; + +/* Hard-coded values used because the SERVICE_OK/WARNING/CRITICAL/UNKNOWN + macros are service status (and include PENDING), not service state */ +const string_value_mapping svm_service_states[] = { + { "ok", 0, "SERVICE_OK" }, + { "warning", 1, "SERVICE_WARNING" }, + { "critical", 2, "SERVICE_CRITICAL" }, + { "unknown", 3, "SERVICE_UNKNOWN" }, + { NULL, -1, NULL }, + }; + +const string_value_mapping svm_check_options[] = { + { "force_execution", CHECK_OPTION_FORCE_EXECUTION, "FORCE_EXECUTION" }, + { "freshness_check", CHECK_OPTION_FRESHNESS_CHECK, "FRESHNESS_CHECK" }, + { "orphan_check", CHECK_OPTION_ORPHAN_CHECK, "ORPHAN_CHECK" }, + { NULL, -1, NULL }, + }; + +const string_value_mapping svm_host_check_types[] = { + { "active", HOST_CHECK_ACTIVE, "ACTIVE" }, + { "passive", HOST_CHECK_PASSIVE, "PASSIVE" }, + { NULL, -1, NULL }, + }; + +const string_value_mapping svm_service_check_types[] = { + { "active", SERVICE_CHECK_ACTIVE, "ACTIVE" }, + { "passive", SERVICE_CHECK_PASSIVE, "PASSIVE" }, + { NULL, -1, NULL }, + }; + +const string_value_mapping svm_state_types[] = { + { "soft", SOFT_STATE, "SOFT" }, + { "hard", HARD_STATE, "HARD" }, + { NULL, -1, NULL }, + }; + +const string_value_mapping svm_acknowledgement_types[] = { + { "none", ACKNOWLEDGEMENT_NONE, "NONE" }, + { "normal", ACKNOWLEDGEMENT_NORMAL, "NORMAL" }, + { "sticky", ACKNOWLEDGEMENT_STICKY, "STICKY" }, + { NULL, -1, NULL }, + }; + +const string_value_mapping svm_comment_types[] = { + { "host", HOST_COMMENT, "Host Comment" }, + { "service", SERVICE_COMMENT, "Service Comment" }, + { NULL, -1, NULL }, + }; + +const string_value_mapping svm_comment_entry_types[] = { + { "user", USER_COMMENT, "User Comment" }, + { "downtime", DOWNTIME_COMMENT, "Downtime Comment" }, + { "flapping", FLAPPING_COMMENT, "Flapping Comment" }, + { "acknowledgement", ACKNOWLEDGEMENT_COMMENT, "Acknowledgement Comment" }, + { NULL, -1, NULL }, + }; + +const string_value_mapping svm_downtime_types[] = { + { "service", SERVICE_DOWNTIME, "Service Downtime" }, + { "host", HOST_DOWNTIME, "Host Downtime" }, + { "any", ANY_DOWNTIME, "Any Downtime" }, + { NULL, -1, NULL }, + }; + +#ifdef JSON_NAGIOS_4X +const string_value_mapping svm_option_types[] = { + { "up", OPT_UP, "Up" }, + { "down", OPT_DOWN, "Down" }, + { "unreachable", OPT_UNREACHABLE, "Unreachable" }, + { "ok", OPT_OK, "OK" }, + { "unknown", OPT_UNKNOWN, "Unknown" }, + { "warning", OPT_WARNING, "Warning" }, + { "critical", OPT_CRITICAL, "Critical" }, + { "recovery", OPT_RECOVERY, "Recovery" }, + { "pending", OPT_PENDING, "Pending" }, + { "flapping", OPT_FLAPPING, "Flapping" }, + { "downtime", OPT_DOWNTIME, "Downtime" }, + { NULL, -1, NULL }, + }; +#endif + +const string_value_mapping parent_host_extras[] = { + { "none", 0, "Hosts that are directly reachable by the Nagios Core host" }, + { NULL, -1, NULL }, + }; + +const string_value_mapping child_host_extras[] = { + { "none", 0, "Hosts that have no child hosts" }, + { NULL, -1, NULL }, + }; + +const string_value_mapping parent_service_extras[] = { + { "none", 0, "Services that have no parent services" }, + { NULL, -1, NULL }, + }; + +const string_value_mapping child_service_extras[] = { + { "none", 0, "Services that have no child services" }, + { NULL, -1, NULL }, + }; + +const char *dayofweek[7] = { "Sunday", "Monday", "Tuesday", "Wednesday", + "Thursday", "Friday", "Saturday" }; +const char *month[12] = { "January", "February", "March", "April", "May", + "June", "July", "August", "September", "October", "November", + "December" }; + +static const json_escape_pair string_escape_pairs[] = { + { L"\\", L"\\\\" }, + { L"\x01", L"\\u0001" }, + { L"\x02", L"\\u0002" }, + { L"\x03", L"\\u0003" }, + { L"\x04", L"\\u0004" }, + { L"\x05", L"\\u0004" }, + { L"\x06", L"\\u0006" }, + { L"\a", L"\\a" }, + { L"\b", L"\\b" }, + { L"\t", L"\\t" }, + { L"\n", L"\\n" }, + { L"\v", L"\\v" }, + { L"\f", L"\\f" }, + { L"\r", L"\\r" }, + { L"\x0e", L"\\u000e" }, + { L"\x0f", L"\\u000f" }, + { L"\x10", L"\\u0010" }, + { L"\x11", L"\\u0011" }, + { L"\x12", L"\\u0012" }, + { L"\x13", L"\\u0013" }, + { L"\x14", L"\\u0014" }, + { L"\x15", L"\\u0015" }, + { L"\x16", L"\\u0016" }, + { L"\x17", L"\\u0017" }, + { L"\x18", L"\\u0018" }, + { L"\x19", L"\\u0019" }, + { L"\x1a", L"\\u001a" }, + { L"\x1b", L"\\u001b" }, + { L"\x1c", L"\\u001c" }, + { L"\x1d", L"\\u001d" }, + { L"\x1e", L"\\u001e" }, + { L"\x1f", L"\\u001f" }, + { L"\"", L"\\\"" }, +}; + +static const json_escape string_escapes = { + (sizeof(string_escape_pairs) / sizeof(string_escape_pairs[0])), + string_escape_pairs +}; + +const json_escape_pair percent_escape_pairs[] = { + { L"%", L"%%" }, +}; + +const json_escape percent_escapes = { + (sizeof(percent_escape_pairs) / sizeof(percent_escape_pairs[0])), + percent_escape_pairs +}; + +extern char main_config_file[MAX_FILENAME_LENGTH]; +extern time_t program_start; + +static json_object_member * json_object_add_member(json_object *); + +json_object *json_new_object(void) { + json_object *new; + new = calloc(1, sizeof(json_object)); + return new; + } + +void json_free_object(json_object *obj, int free_children) { + + int x; + json_object_member **mpp; + + if(1 == free_children) { + for(x = 0, mpp = obj->members; x < obj->member_count; x++, mpp++) { + json_free_member(*mpp, free_children); + } + } + free(obj->members); + free(obj); + } + +json_array *json_new_array(void) { + return (json_array *)json_new_object(); + } + +void json_free_member(json_object_member *mp, int free_children) { + + if(NULL != mp->key) free(mp->key); + + switch(mp->type) { + case JSON_TYPE_OBJECT: + case JSON_TYPE_ARRAY: + if(NULL != mp->value.object) { + json_free_object(mp->value.object, free_children); + } + break; + case JSON_TYPE_STRING: + if(NULL != mp->value.string) { + free(mp->value.string); + } + break; + case JSON_TYPE_INTEGER: + case JSON_TYPE_REAL: + case JSON_TYPE_TIME_T: + case JSON_TYPE_BOOLEAN: + break; + default: + break; + } + + free(mp); + } + +/* Adds a member to a JSON object and returns a pointer to the new member. + Returns NULL on failure. */ +static json_object_member * json_object_add_member(json_object *obj) { + + if(0 == obj->member_count) { + obj->members = calloc(1, sizeof(json_object_member *)); + if(NULL == obj->members) { + obj->member_count = 0; + return NULL; + } + } + else { + obj->members = realloc(obj->members, + ((obj->member_count + 1) * sizeof(json_object_member *))); + if(NULL == obj->members) { + obj->member_count = 0; + return NULL; + } + } + obj->members[ obj->member_count] = calloc(1, sizeof(json_object_member)); + if(NULL == obj->members[ obj->member_count]) { + return NULL; + } + obj->member_count++; + + return obj->members[ obj->member_count - 1]; + } + +void json_object_append_object(json_object *obj, char *key, json_object *value) { + json_object_member *mp; + + if(NULL == obj) return; + if(NULL == value) return; + + if((mp = json_object_add_member(obj)) == NULL) { + return; + } + mp->type = JSON_TYPE_OBJECT; + if(NULL != key) { + mp->key = strdup(key); + if(NULL == mp->key) { + obj->member_count--; + return; + } + } + mp->value.object = value; + } + +void json_array_append_object(json_object *obj, json_object *value) { + json_object_append_object(obj, NULL, value); + } + +void json_object_append_array(json_object *obj, char *key, json_array *value) { + json_object_member *mp; + + if(NULL == obj) return; + if(NULL == value) return; + + if((mp = json_object_add_member(obj)) == NULL) { + return; + } + mp->type = JSON_TYPE_ARRAY; + if(NULL != key) { + mp->key = strdup(key); + if(NULL == mp->key) { + obj->member_count--; + return; + } + } + mp->value.object = value; + } + +void json_array_append_array(json_array *obj, json_array *value) { + json_object_append_array((json_object *)obj, NULL, value); + } + +void json_object_append_integer(json_object *obj, char *key, int value) { + json_object_member *mp; + + if(NULL == obj) return; + + if((mp = json_object_add_member(obj)) == NULL) { + return; + } + mp->type = JSON_TYPE_INTEGER; + if(NULL != key) { + mp->key = strdup(key); + if(NULL == mp->key) { + obj->member_count--; + return; + } + } + mp->value.integer = value; + } + +void json_array_append_integer(json_object *obj, int value) { + json_object_append_integer(obj, NULL, value); + } + +void json_object_append_real(json_object *obj, char *key, double value) { + json_object_member *mp; + + if(NULL == obj) return; + + if((mp = json_object_add_member(obj)) == NULL) { + return; + } + mp->type = JSON_TYPE_REAL; + if(NULL != key) { + mp->key = strdup(key); + if(NULL == mp->key) { + obj->member_count--; + return; + } + } + mp->value.real = value; + } + +void json_array_append_real(json_array *obj, double value) { + json_object_append_real(obj, NULL, value); + } + +void json_object_append_time(json_object *obj, char *key, unsigned long value) { + + unsigned hours; + unsigned minutes; + unsigned seconds; + + hours = (unsigned)(value / 3600); + value -= hours * 3600; + minutes = (unsigned)(value / 60); + value -= minutes * 60; + seconds = value; + + json_object_append_string(obj, key, NULL, "%02u:%02u:%02u", hours, minutes, + seconds); + } + +void json_array_append_time(json_array *obj, unsigned long value) { + json_object_append_time(obj, NULL, value); + } + +void json_object_append_time_t(json_object *obj, char *key, time_t value) { + json_object_member *mp; + + if(NULL == obj) return; + + if((mp = json_object_add_member(obj)) == NULL) { + return; + } + mp->type = JSON_TYPE_TIME_T; + if(NULL != key) { + mp->key = strdup(key); + if(NULL == mp->key) { + obj->member_count--; + return; + } + } + mp->value.time = value; + } + +void json_set_time_t(json_object_member *mp, time_t value) { + if(NULL == mp) return; + mp->value.time = value; + } + +void json_object_append_string(json_object *obj, char *key, + const json_escape *format_escapes, char *format, ...) { + json_object_member *mp; + va_list a_list; + int result; + char *escaped_format; + char *buf; + + if(NULL == obj) return; + + if((mp = json_object_add_member(obj)) == NULL) { + return; + } + mp->type = JSON_TYPE_STRING; + if(NULL != key) { + mp->key = strdup(key); + if(NULL == mp->key) { + obj->member_count--; + return; + } + } + if((NULL != format_escapes) && (NULL != format)) { + escaped_format = json_escape_string(format, format_escapes); + } + else { + escaped_format = format; + } + if(NULL != escaped_format) { + va_start(a_list, format); + result = vasprintf(&buf, escaped_format, a_list); + va_end(a_list); + if(result >= 0) { + mp->value.string = buf; + } + } + if((NULL != format_escapes) && (NULL != escaped_format)) { + /* free only if format_escapes were passed and the escaping succeeded */ + free(escaped_format); + } + } + +void json_array_append_string(json_object *obj, + const json_escape *format_escapes, char *format, ...) { + + va_list a_list; + int result; + char *buf; + + va_start( a_list, format); + result = vasprintf(&buf, format, a_list); + va_end( a_list); + if(result >= 0) { + json_object_append_string(obj, NULL, format_escapes, buf); + } + } + +void json_object_append_boolean(json_object *obj, char *key, int value) { + json_object_member *mp; + + if(NULL == obj) return; + + if((mp = json_object_add_member(obj)) == NULL) { + return; + } + mp->type = JSON_TYPE_BOOLEAN; + if(NULL != key) { + mp->key = strdup(key); + if(NULL == mp->key) { + obj->member_count--; + return; + } + } + mp->value.boolean = value; + } + +void json_array_append_boolean(json_object *obj, int value) { + json_object_append_boolean(obj, NULL, value); + } + +void json_object_append_duration(json_object *obj, char *key, + unsigned long value) { + json_object_member *mp; + + if(NULL == obj) return; + + if((mp = json_object_add_member(obj)) == NULL) { + return; + } + mp->type = JSON_TYPE_DURATION; + if(NULL != key) { + mp->key = strdup(key); + if(NULL == mp->key) { + obj->member_count--; + return; + } + } + mp->value.unsigned_integer = value; + } + +void json_array_append_duration(json_object *obj, unsigned long value) { + json_object_append_duration(obj, NULL, value); + } + +/* + Fetch an object member based on the path. The path is a dot-separated + list of nodes. Nodes may be either a key or a zero-based array index. + + For example to return the query_time key in the result object, the + path would be "result.query_time". To find the 2nd host host in + the list of hosts for a hostlist query, the path would be + "data.hostlist.1" +*/ + +json_object_member *json_get_object_member(json_object *root, char *path) { + + char *dot; + char node[1024]; + int x; + json_object_member **mpp; + + /* Parse the path to get the first node */ + dot = strchr(path, '.'); + if(NULL == dot) { /* single node path */ + strcpy(node, path); + } + else { + strncpy(node, path, (dot - path)); + node[dot - path] = '\0'; + } + + /* Loop over the members of the passed root looking for the node name */ + for(x = 0, mpp = root->members; x < root->member_count; x++, mpp++) { + if(!strcmp((*mpp)->key, node)) { + if(NULL == dot) { /* return this node */ + return *mpp; + } + else { + switch((*mpp)->type) { + case JSON_TYPE_OBJECT: + return json_get_object_member((*mpp)->value.object, dot + 1); + break; + case JSON_TYPE_ARRAY: + return json_get_array_member((*mpp)->value.object, dot + 1); + break; + default: + /* It should never happen that we want the child of a + childless node */ + return NULL; + break; + } + } + } + } + + return NULL; + } + +json_object_member *json_get_array_member(json_object *root, char *path) { + + char *dot; + char node[1024]; + int index; + json_object_member *mp; + + /* Parse the path to get the first node */ + dot = strchr(path, '.'); + if(NULL == dot) { /* single node path */ + strcpy(node, path); + } + else { + strncpy(node, path, (dot - path)); + node[dot - path] = '\0'; + } + index = (int)strtol(node, NULL, 10); + + /* Verify that we have a reasonable index */ + if(index < 0 || index >= root->member_count) { + return NULL; + } + + /* Find the requested member and deal with it appropriately */ + mp = root->members[ index]; + if(NULL == dot) { /* return this node */ + return mp; + } + else { + switch(mp->type) { + case JSON_TYPE_OBJECT: + return json_get_object_member(mp->value.object, dot + 1); + break; + case JSON_TYPE_ARRAY: + return json_get_array_member(mp->value.object, dot + 1); + break; + default: + /* It should never happen that we want the child of a + childless node */ + return NULL; + break; + } + } + + return NULL; + } + +void json_object_print(json_object *obj, int padding, int whitespace, + char *strftime_format, unsigned format_options) { + int x; + json_object_member **mpp; + + //indentf(padding, whitespace, "{%s", (whitespace ? "\n" : "")); + printf( "{%s", (whitespace ? "\n" : "")); + padding++; + for(x = 0, mpp = obj->members; x < obj->member_count; x++, mpp++) { + json_member_print(*mpp, padding, whitespace, strftime_format, + format_options); + if(x != obj->member_count - 1) printf(","); + if(whitespace) printf("\n"); + } + padding--; + indentf(padding, whitespace, "}"); +} + +void json_array_print(json_array *obj, int padding, int whitespace, + char *strftime_format, unsigned format_options) { + int x; + json_object_member **mpp; + + printf( "[%s", (whitespace ? "\n" : "")); + padding++; + for(x = 0, mpp = obj->members; x < obj->member_count; x++, mpp++) { + json_member_print(*mpp, padding, whitespace, strftime_format, + format_options); + if(x != obj->member_count - 1) printf(","); + if(whitespace) printf("\n"); + } + padding--; + indentf(padding, whitespace, "]"); + } + +void json_member_print(json_object_member *mp, int padding, int whitespace, + char *strftime_format, unsigned format_options) { + + char *buf = NULL; + + switch(mp->type) { + case JSON_TYPE_OBJECT: + if(NULL != mp->key) { + buf = json_escape_string(mp->key, &string_escapes); + indentf(padding, whitespace, "\"%s\": ", buf); + if(NULL != buf) free(buf); + } + else { + indentf(padding, whitespace, ""); + } + json_object_print(mp->value.object, padding, whitespace, + strftime_format, format_options); + break; + case JSON_TYPE_ARRAY: + if(NULL != mp->key) { + buf = json_escape_string(mp->key, &string_escapes); + indentf(padding, whitespace, "\"%s\": ", buf); + if(NULL != buf) free(buf); + } + else { + indentf(padding, whitespace, ""); + } + json_array_print(mp->value.object, padding, whitespace, strftime_format, + format_options); + break; + case JSON_TYPE_INTEGER: + json_int(padding, whitespace, mp->key, mp->value.integer); + break; + case JSON_TYPE_REAL: + json_float(padding, whitespace, mp->key, mp->value.real); + break; + case JSON_TYPE_TIME_T: + json_time_t(padding, whitespace, mp->key, mp->value.time, + strftime_format); + break; + case JSON_TYPE_STRING: + json_string(padding, whitespace, mp->key, mp->value.string); + break; + case JSON_TYPE_BOOLEAN: + json_boolean(padding, whitespace, mp->key, mp->value.boolean); + break; + case JSON_TYPE_DURATION: + json_duration(padding, whitespace, mp->key, mp->value.unsigned_integer, + format_options & JSON_FORMAT_DURATION); + break; + default: + break; + } + } + +void indentf(int padding, int whitespace, char *format, ...) { + va_list a_list; + int padvar; + + if( whitespace > 0) { + for(padvar = 0; padvar < padding; padvar++) printf( " "); + } + va_start( a_list, format); + vprintf(format, a_list); + va_end( a_list); + } + +json_object * json_result(time_t query_time, char *cgi, char *query, + int query_status, time_t last_data_update, authdata *authinfo, int type, + char *message, ...) { + + json_object *json_result; + va_list a_list; + char *buf; + + + json_result = json_new_object(); + json_object_append_time_t(json_result, "query_time", query_time); + json_object_append_string(json_result, "cgi", &percent_escapes, cgi); + if(NULL != authinfo) { + json_object_append_string(json_result, "user", &percent_escapes, + authinfo->username); + } + if(NULL != query) { + json_object_append_string(json_result, "query", &percent_escapes, + query); + json_object_append_string(json_result, "query_status", &percent_escapes, + svm_get_string_from_value(query_status, query_statuses)); + } + json_object_append_time_t(json_result, "program_start", program_start); + if(last_data_update != (time_t)-1) { + json_object_append_time_t(json_result, "last_data_update", + last_data_update); + } + json_object_append_integer(json_result, "type_code", type); + json_object_append_string(json_result, "type_text", &percent_escapes, + (char *)result_types[ type]); + va_start( a_list, message); + if(vasprintf(&buf, message, a_list) == -1) { + buf = NULL; + } + va_end( a_list); + json_object_append_string(json_result, "message", &percent_escapes, buf); + if(NULL != buf) free(buf); + + return json_result; +} + +json_object *json_help(option_help *help) { + + json_object *json_data = json_new_object(); + json_object *json_options = json_new_object(); + json_object *json_option; + json_array *json_required; + json_array *json_optional; + json_object *json_validvalues; + json_object *json_validvalue; + int x; + char ** stpp; + string_value_mapping *svmp; + + while(NULL != help->name) { + json_option = json_new_object(); + json_object_append_string(json_option, "label", &percent_escapes, + (char *)help->label); + json_object_append_string(json_option, "type", &percent_escapes, + (char *)help->type); + + json_required = json_new_array(); + for(x = 0, stpp = (char **)help->required; + (( x < sizeof( help->required) / + sizeof( help->required[ 0])) && ( NULL != *stpp)); + x++, stpp++) { + json_array_append_string(json_required, &percent_escapes, *stpp); + } + json_object_append_array(json_option, "required", + json_required); + + json_optional = json_new_array(); + for(x = 0, stpp = (char **)help->optional; + (( x < sizeof( help->optional) / + sizeof( help->optional[ 0])) && ( NULL != *stpp)); + x++, stpp++) { + json_array_append_string(json_optional, &percent_escapes, *stpp); + } + json_object_append_array(json_option, "optional", + json_optional); + + json_object_append_string(json_option, "depends_on", + &percent_escapes, (char *)help->depends_on); + json_object_append_string(json_option, "description", + &percent_escapes, (char *)help->description); + if( NULL != help->valid_values) { + json_validvalues = json_new_object(); + for(svmp = (string_value_mapping *)help->valid_values; + NULL != svmp->string; svmp++) { + if( NULL != svmp->description) { + json_validvalue = json_new_object(); + json_object_append_string(json_validvalue, "description", + &percent_escapes, svmp->description); + json_object_append_object(json_validvalues, svmp->string, + json_validvalue); + } + else { + json_array_append_string(json_validvalues, &percent_escapes, + svmp->string); + } + } + json_object_append_object(json_option, "valid_values", + json_validvalues); + } + json_object_append_object(json_options, (char *)help->name, json_option); + help++; + } + + json_object_append_object(json_data, "options", json_options); + + return json_data; + } + +int passes_start_and_count_limits(int start, int max, int current, int counted) { + + int result = FALSE; + + if(start > 0) { + /* The user requested we start at a specific index */ + if(current >= start) { + if(max > 0) { + /* The user requested a limit on the number of items returned */ + if(counted < max) { + result = TRUE; + } + } + else { + /* The user did not request a limit on the number of items + returned */ + result = TRUE; + } + } + } + else { + /* The user did not request we start at a specific index */ + if(max > 0) { + /* The user requested a limit on the number of items returned */ + if(counted < max) { + result = TRUE; + } + } + else { + /* The user did not request a limit on the number of items + returned */ + result = TRUE; + } + } + return result; + } + +void json_string(int padding, int whitespace, char *key, char *value) { + + char *keybuf = NULL; + char *valbuf = NULL; + + valbuf = json_escape_string(value, &string_escapes); + + if( NULL == key) { + indentf(padding, whitespace, "\"%s\"", + (( NULL == valbuf) ? "" : valbuf)); + } + else { + keybuf = json_escape_string(key, &string_escapes); + indentf(padding, whitespace, "\"%s\":%s\"%s\"", keybuf, + (( whitespace> 0) ? " " : ""), + (( NULL == valbuf) ? "" : valbuf)); + } + if(NULL != keybuf) free(keybuf); + if(NULL != valbuf) free(valbuf); + } + +void json_boolean(int padding, int whitespace, char *key, int value) { + + char *keybuf = NULL; + + if( NULL == key) { + indentf(padding, whitespace, "%s", + (( 0 == value) ? "false" : "true")); + } + else { + keybuf = json_escape_string(key, &string_escapes); + indentf(padding, whitespace, "\"%s\":%s%s", keybuf, + (( whitespace > 0) ? " " : ""), + (( 0 == value) ? "false" : "true")); + } + if(NULL != keybuf) free(keybuf); + } + +void json_int(int padding, int whitespace, char *key, int value) { + + char *keybuf = NULL; + + if( NULL == key) { + indentf(padding, whitespace, "%d", value); + } + else { + keybuf = json_escape_string(key, &string_escapes); + indentf(padding, whitespace, "\"%s\":%s%d", keybuf, + (( whitespace > 0) ? " " : ""), value); + } + if(NULL != keybuf) free(keybuf); + } + +void json_unsigned(int padding, int whitespace, char *key, + unsigned long long value) { + + char *keybuf = NULL; + + if( NULL == key) { + indentf(padding, whitespace, "%llu", value); + } + else { + keybuf = json_escape_string(key, &string_escapes); + indentf(padding, whitespace, "\"%s\":%s%llu", keybuf, + (( whitespace > 0) ? " " : ""), value); + } + if(NULL != keybuf) free(keybuf); + } + +void json_float(int padding, int whitespace, char *key, double value) { + + char *keybuf = NULL; + + if( NULL == key) { + indentf(padding, whitespace, "%.2f", value); + } + else { + keybuf = json_escape_string(key, &string_escapes); + indentf(padding, whitespace, "\"%s\":%s%.2f", keybuf, + (( whitespace > 0) ? " " : ""), value); + } + if(NULL != keybuf) free(keybuf); + } + +void json_time(int padding, int whitespace, char *key, unsigned long value) { + + char *keybuf = NULL; + unsigned hours; + unsigned minutes; + unsigned seconds; + + hours = (unsigned)(value / 3600); + value -= hours * 3600; + minutes = (unsigned)(value / 60); + value -= minutes * 60; + seconds = value; + + if( NULL == key) { + indentf(padding, whitespace, "\"%02u:%02u:%02u\"", hours, minutes, + seconds); + } + else { + keybuf = json_escape_string(key, &string_escapes); + indentf(padding, whitespace, "\"%s\":%s\"%02u:%02u:%02u\"", keybuf, + (( whitespace > 0) ? " " : ""), hours, minutes, + seconds); + } + if(NULL != keybuf) free(keybuf); + } + +void json_time_t(int padding, int whitespace, char *key, time_t value, + char *format) { + + char *keybuf = NULL; + char buf[1024]; + struct tm *tmp_tm; + + if(NULL == format) { + snprintf(buf, sizeof(buf)-1, "%llu%s", (unsigned long long)value, + ((unsigned long long)value > 0 ? "000" : "")); + } + else { + tmp_tm = localtime(&value); + buf[ 0] = '"'; + strftime(buf+1, sizeof(buf)-3, format, tmp_tm); + strcat(buf, "\""); + } + + if(NULL == key) { + indentf(padding, whitespace, "%s", buf); + } + else { + keybuf = json_escape_string(key, &string_escapes); + indentf(padding, whitespace, "\"%s\":%s%s", keybuf, + (( whitespace > 0) ? " " : ""), buf); + } + if(NULL != keybuf) free(keybuf); + } + +void json_duration(int padding, int whitespace, char *key, unsigned long value, + int format_duration) { + + char *keybuf = NULL; + char buf[1024]; + int days = 0; + int hours = 0; + int minutes = 0; + int seconds = 0; + + if(0 == format_duration) { + snprintf(buf, sizeof(buf)-1, "%lu", (unsigned long)value); + } + else { + days = (unsigned)(value / 86400); + value -= days * 86400; + hours = (unsigned)(value / 3600); + value -= hours * 3600; + minutes = (unsigned)(value / 60); + value -= minutes * 60; + seconds = value; + snprintf(buf, sizeof(buf)-1, "%ud %uh %um %us", days, hours, minutes, + seconds); + } + + if( NULL == key) { + indentf(padding, whitespace, "%s", buf); + } + else { + keybuf = json_escape_string(key, &string_escapes); + indentf(padding, whitespace, "\"%s\":%s%s%s%s", keybuf, + (( whitespace > 0) ? " " : ""), (format_duration ? "\"" : ""), + buf, (format_duration ? "\"" : "")); + } + if(NULL != keybuf) free(keybuf); + } + +void json_enumeration(json_object *json_parent, unsigned format_options, + char *key, int value, const string_value_mapping *map) { + + string_value_mapping *svmp; + + if(format_options & JSON_FORMAT_ENUMERATE) { + for(svmp = (string_value_mapping *)map; NULL != svmp->string; svmp++) { + if( value == svmp->value) { + json_object_append_string(json_parent, key, &percent_escapes, + svmp->string); + break; + } + } + if( NULL == svmp->string) { + json_object_append_string(json_parent, key, NULL, + "Unknown value %d", svmp->value); + } + } + else { + json_object_append_integer(json_parent, key, value); + } + } + +void json_bitmask(json_object *json_parent, unsigned format_options, char *key, + int value, const string_value_mapping *map) { + + json_array *json_bitmask_array; + string_value_mapping *svmp; + + if(format_options & JSON_FORMAT_BITMASK) { + json_bitmask_array = json_new_array(); + for(svmp = (string_value_mapping *)map; NULL != svmp->string; svmp++) { + if( value & svmp->value) { + json_array_append_string(json_bitmask_array, &percent_escapes, + svmp->string); + } + } + json_object_append_array(json_parent, key, json_bitmask_array); + } + else { + json_object_append_integer(json_parent, key, value); + } + } + +int parse_bitmask_cgivar(char *cgi, char *query, int query_status, + json_object *json_parent, time_t query_time, authdata *authinfo, + char *key, char *value, const string_value_mapping *svm, + unsigned *var) { + + int result = RESULT_SUCCESS; + char *option; + char *saveptr; + string_value_mapping *svmp; + + if(value == NULL) { + json_object_append_object(json_parent, "result", + json_result(query_time, cgi, query, query_status, + (time_t)-1, authinfo, RESULT_OPTION_VALUE_MISSING, + "No value specified for %s option.", key)); + return RESULT_OPTION_VALUE_MISSING; + } + + option = strtok_r(value, " ", &saveptr); + while(NULL != option) { + for(svmp = (string_value_mapping *)svm; NULL != svmp->string; svmp++) { + if( !strcmp( svmp->string, option)) { + *var |= svmp->value; + break; + } + } + if( NULL == svmp->string) { + json_object_append_object(json_parent, "result", + json_result(query_time, cgi, query, query_status, + (time_t)-1, authinfo, RESULT_OPTION_VALUE_INVALID, + "The %s option value '%s' is invalid.", key, option)); + result = RESULT_OPTION_VALUE_INVALID; + break; + } + option = strtok_r(NULL, " ", &saveptr); + } + return result; + } + +int parse_enumeration_cgivar(char *cgi, char *query, int query_status, + json_object *json_parent, time_t query_time, authdata *authinfo, + char *key, char *value, const string_value_mapping *svm, int *var) { + + string_value_mapping *svmp; + + if(value == NULL) { + json_object_append_object(json_parent, "result", + json_result(query_time, cgi, query, query_status, + (time_t)-1, authinfo, RESULT_OPTION_VALUE_MISSING, + "No value specified for %s option.", key)); + return RESULT_OPTION_VALUE_MISSING; + } + + for(svmp = (string_value_mapping *)svm; NULL != svmp->string; svmp++) { + if( !strcmp( svmp->string, value)) { + *var = svmp->value; + break; + } + } + if( NULL == svmp->string) { + json_object_append_object(json_parent, "result", + json_result(query_time, cgi, query, query_status, + (time_t)-1, authinfo, RESULT_OPTION_VALUE_INVALID, + "The %s option value '%s' is invalid.", key, value)); + return RESULT_OPTION_VALUE_INVALID; + } + + return RESULT_SUCCESS; + } + + +int parse_string_cgivar(char *cgi, char *query, int query_status, + json_object *json_parent, time_t query_time, authdata *authinfo, + char *key, char *value, char **var) { + + if(value == NULL) { + json_object_append_object(json_parent, "result", + json_result(query_time, cgi, query, query_status, + (time_t)-1, authinfo, RESULT_OPTION_VALUE_MISSING, + "No value specified for %s option.", key)); + return RESULT_OPTION_VALUE_MISSING; + } + + if(NULL == (*var = strdup( value))) { + json_object_append_object(json_parent, "result", + json_result(query_time, cgi, query, query_status, + (time_t)-1, authinfo, RESULT_MEMORY_ALLOCATION_ERROR, + "Unable to allocate memory for %s option.", key)); + return RESULT_MEMORY_ALLOCATION_ERROR; + } + + return RESULT_SUCCESS; + } + + +int parse_time_cgivar(char *cgi, char *query, int query_status, + json_object *json_parent, time_t query_time, authdata *authinfo, + char *key, char *value, time_t *var) { + + long long templl; + + if(value == NULL) { + json_object_append_object(json_parent, "result", + json_result(query_time, cgi, query, query_status, + (time_t)-1, authinfo, RESULT_OPTION_VALUE_MISSING, + "No value specified for %s option.", key)); + return RESULT_OPTION_VALUE_MISSING; + } + + if('+' == value[0]) { + templl = strtoll(&(value[1]), NULL, 10); + *var = (time_t)((long long)query_time + templl); + } + else if('-' == value[0]) { + templl = strtoll(&(value[1]), NULL, 10); + *var = (time_t)((long long)query_time - templl); + } + else { + templl = strtoll(value, NULL, 10); + *var = (time_t)templl; + } + + return RESULT_SUCCESS; + } + + +int parse_boolean_cgivar(char *cgi, char *query, int query_status, + json_object *json_parent, time_t query_time, authdata *authinfo, + char *key, char *value, int *var) { + + if(value == NULL) { + json_object_append_object(json_parent, "result", + json_result(query_time, cgi, query, query_status, + (time_t)-1, authinfo, RESULT_OPTION_VALUE_MISSING, + "No value specified for %s option.", key)); + return ERROR; + } + + if(!strcmp(value, "true")) { + *var = 1; + } + else if(!strcmp(value, "false")) { + *var = 0; + } + else { + json_object_append_object(json_parent, "result", + json_result(query_time, cgi, query, query_status, + (time_t)-1, authinfo, RESULT_OPTION_VALUE_INVALID, + "Value for %s option must be 'true' or 'false'.", key)); + return RESULT_OPTION_VALUE_INVALID; + } + + return RESULT_SUCCESS; + } + + +int parse_int_cgivar(char *cgi, char *query, int query_status, + json_object *json_parent, time_t query_time, authdata *authinfo, + char *key, char *value, int *var) { + + if(value == NULL) { + json_object_append_object(json_parent, "result", + json_result(query_time, cgi, query, query_status, + (time_t)-1, authinfo, RESULT_OPTION_VALUE_MISSING, + "No value specified for %s option.", key)); + return RESULT_OPTION_VALUE_MISSING; + } + + *var = atoi(value); + return RESULT_SUCCESS; + } + +int get_query_status(const int statuses[][2], int query) { + int x; + + for(x = 0; -1 != statuses[x][0]; x++) { + if(statuses[x][0] == query) return statuses[x][1]; + } + return -1; + } + +char *svm_get_string_from_value(int value, const string_value_mapping *svm) { + + string_value_mapping *svmp; + + for(svmp = (string_value_mapping *)svm; NULL != svmp->string; svmp++) { + if(svmp->value == value) return svmp->string; + } + return NULL; + } + +char *svm_get_description_from_value(int value, const string_value_mapping *svm) { + + string_value_mapping *svmp; + + for(svmp = (string_value_mapping *)svm; NULL != svmp->string; svmp++) { + if(svmp->value == value) return svmp->description; + } + return NULL; + } + +/* Thanks to Jerry Coffin for posting the basis of this function on Stack + Overflow */ +time_t compile_time(const char *date, const char *time) { + + char buf[5]; + int year; + int month; + int day; + int hour; + int minute; + int second; + + struct tm t; + const char *months = "JanFebMarAprMayJunJulAugSepOctNovDec"; + + sscanf(date, "%s %d %d", buf, &day, &year); + sscanf(time, "%d:%d:%d", &hour, &minute, &second); + + month = (strstr(months, buf) - months) / 3; + + t.tm_year = year - 1900; + t.tm_mon = month; + t.tm_mday = day; + t.tm_hour = hour; + t.tm_min = minute; + t.tm_sec = second; + t.tm_isdst = -1; + + return mktime(&t); +} + +/* Escape a string based on the values in the escapes parameter */ +char *json_escape_string(const char *src, const json_escape *escapes) { + + wchar_t *wdest; /* wide character version of the output string */ + size_t wdest_size; /* number of available wchars in wdest */ + size_t wdest_len; /* number of wchars in wdest */ + int x; + json_escape_pair *escp; /* pointer to current escape pair */ + size_t from_len; + size_t to_len; + wchar_t *fromp; /* pointer to a found "from" string */ + long offset; /* offset from beginning of wdest to a "from" string */ + size_t wchars; /* number of wide characters to move */ + size_t dest_len; /* length of output string "dest" */ + char *dest; /* buffer containing the escaped version of src */ + + /* Make sure we're passed valid parameters */ + if((NULL == src) || (NULL == escapes)) { + return NULL; + } + + /* Make a wide string copy of src */ + wdest_len = mbstowcs(NULL, src, 0); + if(wdest_len <= 0) return NULL; + if((wdest = calloc(wdest_len + 1, sizeof(wchar_t))) == NULL) { + return NULL; + } + if(mbstowcs(wdest, src, wdest_len) != wdest_len) { + free(wdest); + return NULL; + } + wdest_size = wdest_len; + + /* Process each escape pair */ + for(x = 0, escp = (json_escape_pair *)escapes->pairs; x < escapes->count; + x++, escp++) { + from_len = wcslen(escp->from); + to_len = wcslen(escp->to); + fromp = wdest; + while((fromp = wcsstr(fromp, escp->from)) != NULL) { + offset = fromp - wdest; + if(from_len < to_len) { + if((wdest_size - wdest_len) < (to_len - from_len)) { + /* If more room is needed, realloc and update variables */ + wdest_size += (to_len - from_len) * BUF_REALLOC_MULTIPLIER; + wdest = realloc(wdest, (wdest_size + 1) * sizeof(wchar_t)); + if(NULL == wdest) return NULL; + fromp = wdest + offset; + } + wchars = wdest_len - offset - from_len + 1; + wmemmove(fromp + to_len, fromp + from_len, wchars); + wcsncpy(fromp, escp->to, to_len); + wdest_len += (to_len - from_len); + fromp += to_len; + } + else { + wchars = wdest_len - offset - to_len; + memmove(fromp + to_len, fromp + from_len, + wchars * sizeof(wchar_t)); + wcsncpy(fromp, escp->to, to_len); + fromp += (from_len - to_len); + wdest_len -= (from_len - to_len); + } + } + } + + /* Covert the wide string back to a multibyte string */ + dest_len = wcstombs(NULL, wdest, 0); + if(0 == dest_len) return NULL; + if((dest = calloc(dest_len + 1, sizeof(char))) == NULL) { + return NULL; + } + if(wcstombs(dest, wdest, dest_len) != dest_len) { + free(dest); + return NULL; + } + + return dest; + } diff --git a/cgi/notifications.c b/cgi/notifications.c index 633e1f2..98f59e4 100644 --- a/cgi/notifications.c +++ b/cgi/notifications.c @@ -2,8 +2,6 @@ * * NOTIFICATIONS.C - Nagios Notifications CGI * - * Copyright (c) 1999-2008 Ethan Galstad (egalstad@nagios.org) - * Last Modified: 01-08-2008 * * This CGI program will display the notification events for * a given host or contact or for all contacts/hosts. @@ -37,8 +35,6 @@ extern char url_images_path[MAX_FILENAME_LENGTH]; extern char url_docs_path[MAX_FILENAME_LENGTH]; extern char url_stylesheets_path[MAX_FILENAME_LENGTH]; -extern int log_rotation_method; - #define FIND_HOST 1 #define FIND_CONTACT 2 @@ -77,7 +73,6 @@ int display_header = TRUE; int main(void) { - int result = OK; char temp_buffer[MAX_INPUT_BUFFER]; char temp_buffer2[MAX_INPUT_BUFFER]; @@ -88,33 +83,7 @@ int main(void) { /* reset internal variables */ reset_cgi_vars(); - /* read the CGI configuration file */ - result = read_cgi_config_file(get_cgi_config_location()); - if(result == ERROR) { - document_header(FALSE); - cgi_config_file_error(get_cgi_config_location()); - document_footer(); - return ERROR; - } - - /* read the main configuration file */ - result = read_main_config_file(main_config_file); - if(result == ERROR) { - document_header(FALSE); - main_config_file_error(main_config_file); - document_footer(); - return ERROR; - } - - /* read all object configuration data */ - result = read_all_object_configuration_data(main_config_file, READ_ALL_OBJECT_DATA); - if(result == ERROR) { - document_header(FALSE); - object_data_error(); - document_footer(); - return ERROR; - } - + cgi_init(document_header, document_footer, READ_ALL_OBJECT_DATA, 0); document_header(TRUE); @@ -238,6 +207,7 @@ int main(void) { printf("
"); printf(""); printf(""); printf(""); printf(""); printf(""); printf(""); printf("Host Status Totals\n"); @@ -1122,9 +1179,11 @@ void show_host_status_totals(void) { printf(""); printf("", HOST_UP); + printf("&hoststatustypes=%d'>", SD_HOST_UP); printf("Up"); printf("", HOST_DOWN); + printf("&hoststatustypes=%d'>", SD_HOST_DOWN); printf("Down"); printf("", HOST_UNREACHABLE); + printf("&hoststatustypes=%d'>", SD_HOST_UNREACHABLE); printf("Unreachable"); printf(""); printf("", HOST_DOWN | HOST_UNREACHABLE); + printf("&hoststatustypes=%d'>", SD_HOST_DOWN | SD_HOST_UNREACHABLE); printf("All Problems"); printf("\n"); @@ -1574,8 +1640,16 @@ void show_service_detail(void) { show_service = TRUE; else if(host_filter != NULL && 0 == regexec(&preg_hostname, temp_status->host_name, 0, NULL, 0)) show_service = TRUE; + else if(host_filter != NULL && navbar_search_addresses == TRUE && 0 == regexec(&preg_hostname, temp_host->address, 0, NULL, 0)) + show_service = TRUE; + else if(host_filter != NULL && navbar_search_aliases == TRUE && 0 == regexec(&preg_hostname, temp_host->alias, 0, NULL, 0)) + show_service = TRUE; else if(!strcmp(host_name, temp_status->host_name)) show_service = TRUE; + else if(navbar_search_addresses == TRUE && !strcmp(host_name, temp_host->address)) + show_service = TRUE; + else if(navbar_search_aliases == TRUE && !strcmp(host_name, temp_host->alias)) + show_service = TRUE; } else if(display_type == DISPLAY_HOSTGROUPS) { @@ -1596,14 +1670,14 @@ void show_service_detail(void) { if(result_limit == 0) limit_results = FALSE; - if((limit_results == TRUE && show_service == TRUE) && ((total_entries < page_start) || (total_entries >= (page_start + result_limit)))) { + if( (limit_results == TRUE && show_service== TRUE) && ( (total_entries < page_start) || (total_entries > (page_start + result_limit)) ) ) { total_entries++; show_service = FALSE; } /* a visible entry */ if(show_service == TRUE) { - if(strcmp(last_host, temp_status->host_name) || visible_entries == 0) + if(strcmp(last_host, temp_status->host_name) || visible_entries == 0 ) new_host = TRUE; else new_host = FALSE; @@ -1681,7 +1755,7 @@ void show_service_detail(void) { /* grab macros */ grab_host_macros_r(mac, temp_host); - if(temp_hoststatus->status == HOST_DOWN) { + if(temp_hoststatus->status == SD_HOST_DOWN) { if(temp_hoststatus->problem_has_been_acknowledged == TRUE) host_status_bg_class = "HOSTDOWNACK"; else if(temp_hoststatus->scheduled_downtime_depth > 0) @@ -1689,7 +1763,7 @@ void show_service_detail(void) { else host_status_bg_class = "HOSTDOWN"; } - else if(temp_hoststatus->status == HOST_UNREACHABLE) { + else if(temp_hoststatus->status == SD_HOST_UNREACHABLE) { if(temp_hoststatus->problem_has_been_acknowledged == TRUE) host_status_bg_class = "HOSTUNREACHABLEACK"; else if(temp_hoststatus->scheduled_downtime_depth > 0) @@ -1809,7 +1883,7 @@ void show_service_detail(void) { printf("This service problem has been acknowledgedActive and passive checks have been disabled for this serviceNotifications for this host have been disabledChecks of this host have been disabled", EXTINFO_CGI, DISPLAY_HOST_INFO, url_encode(temp_status->host_name)); + printf("Active and passive checks have been disabled for this host", EXTINFO_CGI, DISPLAY_HOST_INFO, url_encode(temp_status->host_name)); + printf("Active checks of this host have been disabled - only passive checks are being acceptedThis host is flapping between states
%d UP%d UP
\n"); printf("\n"); - printf("\n", STATUS_CGI, url_encode(temp_servicegroup->group_name), HOST_DOWN, host_properties, hosts_down); + printf("\n", STATUS_CGI, url_encode(temp_servicegroup->group_name), SD_HOST_DOWN, host_properties, hosts_down); printf("\n"); @@ -2857,21 +2957,21 @@ void show_servicegroup_host_totals_summary(servicegroup *temp_servicegroup) { printf("
%d DOWN :%d DOWN :\n"); if(hosts_down_unacknowledged > 0) - printf("\n", STATUS_CGI, url_encode(temp_servicegroup->group_name), HOST_DOWN, HOST_NO_SCHEDULED_DOWNTIME | HOST_STATE_UNACKNOWLEDGED | HOST_CHECKS_ENABLED, hosts_down_unacknowledged); + printf("\n", STATUS_CGI, url_encode(temp_servicegroup->group_name), SD_HOST_DOWN, HOST_NO_SCHEDULED_DOWNTIME | HOST_STATE_UNACKNOWLEDGED | HOST_CHECKS_ENABLED, hosts_down_unacknowledged); if(hosts_down_scheduled > 0) - printf("\n", STATUS_CGI, url_encode(temp_servicegroup->group_name), HOST_DOWN, HOST_SCHEDULED_DOWNTIME, hosts_down_scheduled); + printf("\n", STATUS_CGI, url_encode(temp_servicegroup->group_name), SD_HOST_DOWN, HOST_SCHEDULED_DOWNTIME, hosts_down_scheduled); if(hosts_down_acknowledged > 0) - printf("\n", STATUS_CGI, url_encode(temp_servicegroup->group_name), HOST_DOWN, HOST_STATE_ACKNOWLEDGED, hosts_down_acknowledged); + printf("\n", STATUS_CGI, url_encode(temp_servicegroup->group_name), SD_HOST_DOWN, HOST_STATE_ACKNOWLEDGED, hosts_down_acknowledged); if(hosts_down_disabled > 0) - printf("\n", STATUS_CGI, url_encode(temp_servicegroup->group_name), HOST_DOWN, HOST_CHECKS_DISABLED, hosts_down_disabled); + printf("\n", STATUS_CGI, url_encode(temp_servicegroup->group_name), SD_HOST_DOWN, HOST_CHECKS_DISABLED, hosts_down_disabled); printf("
%d Unhandled
%d Unhandled
%d Scheduled
%d Scheduled
%d Acknowledged
%d Acknowledged
%d Disabled
%d Disabled
\n"); printf("\n"); - printf("\n", STATUS_CGI, url_encode(temp_servicegroup->group_name), HOST_UNREACHABLE, host_properties, hosts_unreachable); + printf("\n", STATUS_CGI, url_encode(temp_servicegroup->group_name), SD_HOST_UNREACHABLE, host_properties, hosts_unreachable); printf("\n"); @@ -2932,6 +3032,10 @@ void show_servicegroup_service_totals_summary(servicegroup *temp_servicegroup) { if(temp_service == NULL) continue; + /* make sure user has rights to view this service */ + if(is_authorized_for_service(temp_service, ¤t_authdata) == FALSE) + continue; + /* skip this if it isn't a new service... */ if(temp_service == last_service) continue; @@ -2969,7 +3073,7 @@ void show_servicegroup_service_totals_summary(servicegroup *temp_servicegroup) { else if(temp_servicestatus->status == SERVICE_WARNING) { temp_hoststatus = find_hoststatus(temp_servicestatus->host_name); - if(temp_hoststatus != NULL && (temp_hoststatus->status == HOST_DOWN || temp_hoststatus->status == HOST_UNREACHABLE)) { + if(temp_hoststatus != NULL && (temp_hoststatus->status == SD_HOST_DOWN || temp_hoststatus->status == SD_HOST_UNREACHABLE)) { services_warning_host_problem++; problem = FALSE; } @@ -2992,7 +3096,7 @@ void show_servicegroup_service_totals_summary(servicegroup *temp_servicegroup) { else if(temp_servicestatus->status == SERVICE_UNKNOWN) { temp_hoststatus = find_hoststatus(temp_servicestatus->host_name); - if(temp_hoststatus != NULL && (temp_hoststatus->status == HOST_DOWN || temp_hoststatus->status == HOST_UNREACHABLE)) { + if(temp_hoststatus != NULL && (temp_hoststatus->status == SD_HOST_DOWN || temp_hoststatus->status == SD_HOST_UNREACHABLE)) { services_unknown_host_problem++; problem = FALSE; } @@ -3015,7 +3119,7 @@ void show_servicegroup_service_totals_summary(servicegroup *temp_servicegroup) { else if(temp_servicestatus->status == SERVICE_CRITICAL) { temp_hoststatus = find_hoststatus(temp_servicestatus->host_name); - if(temp_hoststatus != NULL && (temp_hoststatus->status == HOST_DOWN || temp_hoststatus->status == HOST_UNREACHABLE)) { + if(temp_hoststatus != NULL && (temp_hoststatus->status == SD_HOST_DOWN || temp_hoststatus->status == SD_HOST_UNREACHABLE)) { services_critical_host_problem++; problem = FALSE; } @@ -3058,10 +3162,10 @@ void show_servicegroup_service_totals_summary(servicegroup *temp_servicegroup) { printf("
%d UNREACHABLE :%d UNREACHABLE :\n"); if(hosts_unreachable_unacknowledged > 0) - printf("\n", STATUS_CGI, url_encode(temp_servicegroup->group_name), HOST_UNREACHABLE, HOST_NO_SCHEDULED_DOWNTIME | HOST_STATE_UNACKNOWLEDGED | HOST_CHECKS_ENABLED, hosts_unreachable_unacknowledged); + printf("\n", STATUS_CGI, url_encode(temp_servicegroup->group_name), SD_HOST_UNREACHABLE, HOST_NO_SCHEDULED_DOWNTIME | HOST_STATE_UNACKNOWLEDGED | HOST_CHECKS_ENABLED, hosts_unreachable_unacknowledged); if(hosts_unreachable_scheduled > 0) - printf("\n", STATUS_CGI, url_encode(temp_servicegroup->group_name), HOST_UNREACHABLE, HOST_SCHEDULED_DOWNTIME, hosts_unreachable_scheduled); + printf("\n", STATUS_CGI, url_encode(temp_servicegroup->group_name), SD_HOST_UNREACHABLE, HOST_SCHEDULED_DOWNTIME, hosts_unreachable_scheduled); if(hosts_unreachable_acknowledged > 0) - printf("\n", STATUS_CGI, url_encode(temp_servicegroup->group_name), HOST_UNREACHABLE, HOST_STATE_ACKNOWLEDGED, hosts_unreachable_acknowledged); + printf("\n", STATUS_CGI, url_encode(temp_servicegroup->group_name), SD_HOST_UNREACHABLE, HOST_STATE_ACKNOWLEDGED, hosts_unreachable_acknowledged); if(hosts_unreachable_disabled > 0) - printf("\n", STATUS_CGI, url_encode(temp_servicegroup->group_name), HOST_UNREACHABLE, HOST_CHECKS_DISABLED, hosts_unreachable_disabled); + printf("\n", STATUS_CGI, url_encode(temp_servicegroup->group_name), SD_HOST_UNREACHABLE, HOST_CHECKS_DISABLED, hosts_unreachable_disabled); printf("
%d Unhandled
%d Unhandled
%d Scheduled
%d Scheduled
%d Acknowledged
%d Acknowledged
%d Disabled
%d Disabled
\n"); if(services_warning_unacknowledged > 0) - printf("\n", STATUS_CGI, url_encode(temp_servicegroup->group_name), SERVICE_WARNING, HOST_UP | HOST_PENDING, SERVICE_NO_SCHEDULED_DOWNTIME | SERVICE_STATE_UNACKNOWLEDGED | SERVICE_CHECKS_ENABLED, services_warning_unacknowledged); + printf("\n", STATUS_CGI, url_encode(temp_servicegroup->group_name), SERVICE_WARNING, SD_HOST_UP | HOST_PENDING, SERVICE_NO_SCHEDULED_DOWNTIME | SERVICE_STATE_UNACKNOWLEDGED | SERVICE_CHECKS_ENABLED, services_warning_unacknowledged); if(services_warning_host_problem > 0) - printf("\n", STATUS_CGI, url_encode(temp_servicegroup->group_name), SERVICE_WARNING, HOST_DOWN | HOST_UNREACHABLE, services_warning_host_problem); + printf("\n", STATUS_CGI, url_encode(temp_servicegroup->group_name), SERVICE_WARNING, SD_HOST_DOWN | SD_HOST_UNREACHABLE, services_warning_host_problem); if(services_warning_scheduled > 0) printf("\n", STATUS_CGI, url_encode(temp_servicegroup->group_name), SERVICE_WARNING, SERVICE_SCHEDULED_DOWNTIME, services_warning_scheduled); @@ -3089,10 +3193,10 @@ void show_servicegroup_service_totals_summary(servicegroup *temp_servicegroup) { printf("
%d Unhandled
%d Unhandled
%d on Problem Hosts
%d on Problem Hosts
%d Scheduled
\n"); if(services_unknown_unacknowledged > 0) - printf("\n", STATUS_CGI, url_encode(temp_servicegroup->group_name), SERVICE_UNKNOWN, HOST_UP | HOST_PENDING, SERVICE_NO_SCHEDULED_DOWNTIME | SERVICE_STATE_UNACKNOWLEDGED | SERVICE_CHECKS_ENABLED, services_unknown_unacknowledged); + printf("\n", STATUS_CGI, url_encode(temp_servicegroup->group_name), SERVICE_UNKNOWN, SD_HOST_UP | HOST_PENDING, SERVICE_NO_SCHEDULED_DOWNTIME | SERVICE_STATE_UNACKNOWLEDGED | SERVICE_CHECKS_ENABLED, services_unknown_unacknowledged); if(services_unknown_host_problem > 0) - printf("\n", STATUS_CGI, url_encode(temp_servicegroup->group_name), SERVICE_UNKNOWN, HOST_DOWN | HOST_UNREACHABLE, services_unknown_host_problem); + printf("\n", STATUS_CGI, url_encode(temp_servicegroup->group_name), SERVICE_UNKNOWN, SD_HOST_DOWN | SD_HOST_UNREACHABLE, services_unknown_host_problem); if(services_unknown_scheduled > 0) printf("\n", STATUS_CGI, url_encode(temp_servicegroup->group_name), SERVICE_UNKNOWN, SERVICE_SCHEDULED_DOWNTIME, services_unknown_scheduled); @@ -3120,10 +3224,10 @@ void show_servicegroup_service_totals_summary(servicegroup *temp_servicegroup) { printf("
%d Unhandled
%d Unhandled
%d on Problem Hosts
%d on Problem Hosts
%d Scheduled
\n"); if(services_critical_unacknowledged > 0) - printf("\n", STATUS_CGI, url_encode(temp_servicegroup->group_name), SERVICE_CRITICAL, HOST_UP | HOST_PENDING, SERVICE_NO_SCHEDULED_DOWNTIME | SERVICE_STATE_UNACKNOWLEDGED | SERVICE_CHECKS_ENABLED, services_critical_unacknowledged); + printf("\n", STATUS_CGI, url_encode(temp_servicegroup->group_name), SERVICE_CRITICAL, SD_HOST_UP | HOST_PENDING, SERVICE_NO_SCHEDULED_DOWNTIME | SERVICE_STATE_UNACKNOWLEDGED | SERVICE_CHECKS_ENABLED, services_critical_unacknowledged); if(services_critical_host_problem > 0) - printf("\n", STATUS_CGI, url_encode(temp_servicegroup->group_name), SERVICE_CRITICAL, HOST_DOWN | HOST_UNREACHABLE, services_critical_host_problem); + printf("\n", STATUS_CGI, url_encode(temp_servicegroup->group_name), SERVICE_CRITICAL, SD_HOST_DOWN | SD_HOST_UNREACHABLE, services_critical_host_problem); if(services_critical_scheduled > 0) printf("\n", STATUS_CGI, url_encode(temp_servicegroup->group_name), SERVICE_CRITICAL, SERVICE_SCHEDULED_DOWNTIME, services_critical_scheduled); @@ -3258,9 +3362,9 @@ void show_servicegroup_grids(void) { /* displays status grid for a specific servicegroup */ void show_servicegroup_grid(servicegroup *temp_servicegroup) { - char *status_bg_class = ""; - char *host_status_class = ""; - char *service_status_class = ""; + const char *status_bg_class = ""; + const char *host_status_class = ""; + const char *service_status_class = ""; char *processed_string = NULL; servicesmember *temp_member; servicesmember *temp_member2; @@ -3290,6 +3394,10 @@ void show_servicegroup_grid(servicegroup *temp_servicegroup) { if(temp_host == NULL) continue; + /* make sure user has rights to view this host */ + if(is_authorized_for_host(temp_host, ¤t_authdata) == FALSE) + continue; + /* get the status of the host */ temp_hoststatus = find_hoststatus(temp_host->name); if(temp_hoststatus == NULL) @@ -3310,9 +3418,9 @@ void show_servicegroup_grid(servicegroup *temp_servicegroup) { printf("\n", status_bg_class); - if(temp_hoststatus->status == HOST_DOWN) + if(temp_hoststatus->status == SD_HOST_DOWN) host_status_class = "HOStdOWN"; - else if(temp_hoststatus->status == HOST_UNREACHABLE) + else if(temp_hoststatus->status == SD_HOST_UNREACHABLE) host_status_class = "HOSTUNREACHABLE"; else host_status_class = status_bg_class; @@ -3557,15 +3665,14 @@ void show_hostgroup_overviews(void) { printf("

\n"); printf("

\n"); - if(hoststatus_list != NULL) { + if(hostgroup_list != NULL) { printf("
It appears as though you do not have permission to view information for any of the hosts you requested...
\n"); printf("
If you believe this is an error, check the HTTP server authentication requirements for accessing this CGI
"); printf("and check the authorization options in your CGI configuration file.
\n"); - } + } else { - printf("
There doesn't appear to be any host status information in the status log...

\n"); - printf("Make sure that Nagios is running and that you have specified the location of you status log correctly in the configuration files.
\n"); - } + printf("
There are no host groups defined.
\n"); + } printf("
\n"); printf("

\n"); @@ -3607,6 +3714,10 @@ void show_hostgroup_overview(hostgroup *hstgrp) { if(temp_host == NULL) continue; + /* make sure user has rights to view this host */ + if(is_authorized_for_host(temp_host, ¤t_authdata) == FALSE) + continue; + /* find the host status */ temp_hoststatus = find_hoststatus(temp_host->name); if(temp_hoststatus == NULL) @@ -3639,8 +3750,8 @@ void show_hostgroup_overview(hostgroup *hstgrp) { /* shows a host status overview... */ void show_servicegroup_hostgroup_member_overview(hoststatus *hststatus, int odd, void *data) { char status[MAX_INPUT_BUFFER]; - char *status_bg_class = ""; - char *status_class = ""; + const char *status_bg_class = ""; + const char *status_class = ""; host *temp_host = NULL; char *processed_string = NULL; @@ -3654,17 +3765,17 @@ void show_servicegroup_hostgroup_member_overview(hoststatus *hststatus, int odd, status_class = "HOSTPENDING"; status_bg_class = (odd) ? "Even" : "Odd"; } - else if(hststatus->status == HOST_UP) { + else if(hststatus->status == SD_HOST_UP) { strncpy(status, "UP", sizeof(status)); status_class = "HOSTUP"; status_bg_class = (odd) ? "Even" : "Odd"; } - else if(hststatus->status == HOST_DOWN) { + else if(hststatus->status == SD_HOST_DOWN) { strncpy(status, "DOWN", sizeof(status)); status_class = "HOStdOWN"; status_bg_class = "HOStdOWN"; } - else if(hststatus->status == HOST_UNREACHABLE) { + else if(hststatus->status == SD_HOST_UNREACHABLE) { strncpy(status, "UNREACHABLE", sizeof(status)); status_class = "HOSTUNREACHABLE"; status_bg_class = "HOSTUNREACHABLE"; @@ -3735,7 +3846,7 @@ void show_servicegroup_hostgroup_member_overview(hoststatus *hststatus, int odd, -void show_servicegroup_hostgroup_member_service_status_totals(char *host_name, void *data) { +void show_servicegroup_hostgroup_member_service_status_totals(char *hst_name, void *data) { int total_ok = 0; int total_warning = 0; int total_unknown = 0; @@ -3753,7 +3864,7 @@ void show_servicegroup_hostgroup_member_service_status_totals(char *host_name, v /* check all services... */ for(temp_servicestatus = servicestatus_list; temp_servicestatus != NULL; temp_servicestatus = temp_servicestatus->next) { - if(!strcmp(host_name, temp_servicestatus->host_name)) { + if(!strcmp(hst_name, temp_servicestatus->host_name)) { /* make sure the user is authorized to see this service... */ temp_service = find_service(temp_servicestatus->host_name, temp_servicestatus->description); @@ -3796,7 +3907,7 @@ void show_servicegroup_hostgroup_member_service_status_totals(char *host_name, v if(display_type == DISPLAY_SERVICEGROUPS) snprintf(temp_buffer, sizeof(temp_buffer) - 1, "servicegroup=%s&style=detail", url_encode(temp_servicegroup->group_name)); else - snprintf(temp_buffer, sizeof(temp_buffer) - 1, "host=%s", url_encode(host_name)); + snprintf(temp_buffer, sizeof(temp_buffer) - 1, "host=%s", url_encode(hst_name)); temp_buffer[sizeof(temp_buffer) - 1] = '\x0'; if(total_ok > 0) @@ -3936,7 +4047,7 @@ void show_hostgroup_summaries(void) { /* displays status summary information for a specific hostgroup */ void show_hostgroup_summary(hostgroup *temp_hostgroup, int odd) { - char *status_bg_class = ""; + const char *status_bg_class = ""; if(odd == 1) status_bg_class = "Even"; @@ -3990,6 +4101,10 @@ void show_hostgroup_host_totals_summary(hostgroup *temp_hostgroup) { if(temp_host == NULL) continue; + /* make sure user has rights to view this host */ + if(is_authorized_for_host(temp_host, ¤t_authdata) == FALSE) + continue; + /* find the host status */ temp_hoststatus = find_hoststatus(temp_host->name); if(temp_hoststatus == NULL) @@ -4005,10 +4120,10 @@ void show_hostgroup_host_totals_summary(hostgroup *temp_hostgroup) { problem = TRUE; - if(temp_hoststatus->status == HOST_UP) + if(temp_hoststatus->status == SD_HOST_UP) hosts_up++; - else if(temp_hoststatus->status == HOST_DOWN) { + else if(temp_hoststatus->status == SD_HOST_DOWN) { if(temp_hoststatus->scheduled_downtime_depth > 0) { hosts_down_scheduled++; problem = FALSE; @@ -4026,7 +4141,7 @@ void show_hostgroup_host_totals_summary(hostgroup *temp_hostgroup) { hosts_down++; } - else if(temp_hoststatus->status == HOST_UNREACHABLE) { + else if(temp_hoststatus->status == SD_HOST_UNREACHABLE) { if(temp_hoststatus->scheduled_downtime_depth > 0) { hosts_unreachable_scheduled++; problem = FALSE; @@ -4052,7 +4167,7 @@ void show_hostgroup_host_totals_summary(hostgroup *temp_hostgroup) { if(hosts_up > 0) { printf(""); - printf("", STATUS_CGI, url_encode(temp_hostgroup->group_name), HOST_UP, host_properties, hosts_up); + printf("", STATUS_CGI, url_encode(temp_hostgroup->group_name), SD_HOST_UP, host_properties, hosts_up); printf("\n"); } @@ -4061,21 +4176,21 @@ void show_hostgroup_host_totals_summary(hostgroup *temp_hostgroup) { printf("
%d Unhandled
%d Unhandled
%d on Problem Hosts
%d on Problem Hosts
%d Scheduled
%d UP%d UP
\n"); printf("\n"); - printf("\n", STATUS_CGI, url_encode(temp_hostgroup->group_name), HOST_DOWN, host_properties, hosts_down); + printf("\n", STATUS_CGI, url_encode(temp_hostgroup->group_name), SD_HOST_DOWN, host_properties, hosts_down); printf("\n"); @@ -4089,21 +4204,21 @@ void show_hostgroup_host_totals_summary(hostgroup *temp_hostgroup) { printf("
%d DOWN :%d DOWN :\n"); if(hosts_down_unacknowledged > 0) - printf("\n", STATUS_CGI, url_encode(temp_hostgroup->group_name), HOST_DOWN, HOST_NO_SCHEDULED_DOWNTIME | HOST_STATE_UNACKNOWLEDGED | HOST_CHECKS_ENABLED, hosts_down_unacknowledged); + printf("\n", STATUS_CGI, url_encode(temp_hostgroup->group_name), SD_HOST_DOWN, HOST_NO_SCHEDULED_DOWNTIME | HOST_STATE_UNACKNOWLEDGED | HOST_CHECKS_ENABLED, hosts_down_unacknowledged); if(hosts_down_scheduled > 0) - printf("\n", STATUS_CGI, url_encode(temp_hostgroup->group_name), HOST_DOWN, HOST_SCHEDULED_DOWNTIME, hosts_down_scheduled); + printf("\n", STATUS_CGI, url_encode(temp_hostgroup->group_name), SD_HOST_DOWN, HOST_SCHEDULED_DOWNTIME, hosts_down_scheduled); if(hosts_down_acknowledged > 0) - printf("\n", STATUS_CGI, url_encode(temp_hostgroup->group_name), HOST_DOWN, HOST_STATE_ACKNOWLEDGED, hosts_down_acknowledged); + printf("\n", STATUS_CGI, url_encode(temp_hostgroup->group_name), SD_HOST_DOWN, HOST_STATE_ACKNOWLEDGED, hosts_down_acknowledged); if(hosts_down_disabled > 0) - printf("\n", STATUS_CGI, url_encode(temp_hostgroup->group_name), HOST_DOWN, HOST_CHECKS_DISABLED, hosts_down_disabled); + printf("\n", STATUS_CGI, url_encode(temp_hostgroup->group_name), SD_HOST_DOWN, HOST_CHECKS_DISABLED, hosts_down_disabled); printf("
%d Unhandled
%d Unhandled
%d Scheduled
%d Scheduled
%d Acknowledged
%d Acknowledged
%d Disabled
%d Disabled
\n"); printf("\n"); - printf("\n", STATUS_CGI, url_encode(temp_hostgroup->group_name), HOST_UNREACHABLE, host_properties, hosts_unreachable); + printf("\n", STATUS_CGI, url_encode(temp_hostgroup->group_name), SD_HOST_UNREACHABLE, host_properties, hosts_unreachable); printf("\n"); @@ -4161,6 +4276,10 @@ void show_hostgroup_service_totals_summary(hostgroup *temp_hostgroup) { if(temp_host == NULL) continue; + /* make sure user has rights to view this host */ + if(is_authorized_for_host(temp_host, ¤t_authdata) == FALSE) + continue; + /* see if this service is associated with a host in the specified hostgroup */ if(is_host_member_of_hostgroup(temp_hostgroup, temp_host) == FALSE) continue; @@ -4198,7 +4317,7 @@ void show_hostgroup_service_totals_summary(hostgroup *temp_hostgroup) { else if(temp_servicestatus->status == SERVICE_WARNING) { temp_hoststatus = find_hoststatus(temp_servicestatus->host_name); - if(temp_hoststatus != NULL && (temp_hoststatus->status == HOST_DOWN || temp_hoststatus->status == HOST_UNREACHABLE)) { + if(temp_hoststatus != NULL && (temp_hoststatus->status == SD_HOST_DOWN || temp_hoststatus->status == SD_HOST_UNREACHABLE)) { services_warning_host_problem++; problem = FALSE; } @@ -4221,7 +4340,7 @@ void show_hostgroup_service_totals_summary(hostgroup *temp_hostgroup) { else if(temp_servicestatus->status == SERVICE_UNKNOWN) { temp_hoststatus = find_hoststatus(temp_servicestatus->host_name); - if(temp_hoststatus != NULL && (temp_hoststatus->status == HOST_DOWN || temp_hoststatus->status == HOST_UNREACHABLE)) { + if(temp_hoststatus != NULL && (temp_hoststatus->status == SD_HOST_DOWN || temp_hoststatus->status == SD_HOST_UNREACHABLE)) { services_unknown_host_problem++; problem = FALSE; } @@ -4244,7 +4363,7 @@ void show_hostgroup_service_totals_summary(hostgroup *temp_hostgroup) { else if(temp_servicestatus->status == SERVICE_CRITICAL) { temp_hoststatus = find_hoststatus(temp_servicestatus->host_name); - if(temp_hoststatus != NULL && (temp_hoststatus->status == HOST_DOWN || temp_hoststatus->status == HOST_UNREACHABLE)) { + if(temp_hoststatus != NULL && (temp_hoststatus->status == SD_HOST_DOWN || temp_hoststatus->status == SD_HOST_UNREACHABLE)) { services_critical_host_problem++; problem = FALSE; } @@ -4285,10 +4404,10 @@ void show_hostgroup_service_totals_summary(hostgroup *temp_hostgroup) { printf("
%d UNREACHABLE :%d UNREACHABLE :\n"); if(hosts_unreachable_unacknowledged > 0) - printf("\n", STATUS_CGI, url_encode(temp_hostgroup->group_name), HOST_UNREACHABLE, HOST_NO_SCHEDULED_DOWNTIME | HOST_STATE_UNACKNOWLEDGED | HOST_CHECKS_ENABLED, hosts_unreachable_unacknowledged); + printf("\n", STATUS_CGI, url_encode(temp_hostgroup->group_name), SD_HOST_UNREACHABLE, HOST_NO_SCHEDULED_DOWNTIME | HOST_STATE_UNACKNOWLEDGED | HOST_CHECKS_ENABLED, hosts_unreachable_unacknowledged); if(hosts_unreachable_scheduled > 0) - printf("\n", STATUS_CGI, url_encode(temp_hostgroup->group_name), HOST_UNREACHABLE, HOST_SCHEDULED_DOWNTIME, hosts_unreachable_scheduled); + printf("\n", STATUS_CGI, url_encode(temp_hostgroup->group_name), SD_HOST_UNREACHABLE, HOST_SCHEDULED_DOWNTIME, hosts_unreachable_scheduled); if(hosts_unreachable_acknowledged > 0) - printf("\n", STATUS_CGI, url_encode(temp_hostgroup->group_name), HOST_UNREACHABLE, HOST_STATE_ACKNOWLEDGED, hosts_unreachable_acknowledged); + printf("\n", STATUS_CGI, url_encode(temp_hostgroup->group_name), SD_HOST_UNREACHABLE, HOST_STATE_ACKNOWLEDGED, hosts_unreachable_acknowledged); if(hosts_unreachable_disabled > 0) - printf("\n", STATUS_CGI, url_encode(temp_hostgroup->group_name), HOST_UNREACHABLE, HOST_CHECKS_DISABLED, hosts_unreachable_disabled); + printf("\n", STATUS_CGI, url_encode(temp_hostgroup->group_name), SD_HOST_UNREACHABLE, HOST_CHECKS_DISABLED, hosts_unreachable_disabled); printf("
%d Unhandled
%d Unhandled
%d Scheduled
%d Scheduled
%d Acknowledged
%d Acknowledged
%d Disabled
%d Disabled
\n"); if(services_warning_unacknowledged > 0) - printf("\n", STATUS_CGI, url_encode(temp_hostgroup->group_name), SERVICE_WARNING, HOST_UP | HOST_PENDING, SERVICE_NO_SCHEDULED_DOWNTIME | SERVICE_STATE_UNACKNOWLEDGED | SERVICE_CHECKS_ENABLED, services_warning_unacknowledged); + printf("\n", STATUS_CGI, url_encode(temp_hostgroup->group_name), SERVICE_WARNING, SD_HOST_UP | HOST_PENDING, SERVICE_NO_SCHEDULED_DOWNTIME | SERVICE_STATE_UNACKNOWLEDGED | SERVICE_CHECKS_ENABLED, services_warning_unacknowledged); if(services_warning_host_problem > 0) - printf("\n", STATUS_CGI, url_encode(temp_hostgroup->group_name), SERVICE_WARNING, HOST_DOWN | HOST_UNREACHABLE, services_warning_host_problem); + printf("\n", STATUS_CGI, url_encode(temp_hostgroup->group_name), SERVICE_WARNING, SD_HOST_DOWN | SD_HOST_UNREACHABLE, services_warning_host_problem); if(services_warning_scheduled > 0) printf("\n", STATUS_CGI, url_encode(temp_hostgroup->group_name), SERVICE_WARNING, SERVICE_SCHEDULED_DOWNTIME, services_warning_scheduled); @@ -4316,10 +4435,10 @@ void show_hostgroup_service_totals_summary(hostgroup *temp_hostgroup) { printf("
%d Unhandled
%d Unhandled
%d on Problem Hosts
%d on Problem Hosts
%d Scheduled
\n"); if(services_unknown_unacknowledged > 0) - printf("\n", STATUS_CGI, url_encode(temp_hostgroup->group_name), SERVICE_UNKNOWN, HOST_UP | HOST_PENDING, SERVICE_NO_SCHEDULED_DOWNTIME | SERVICE_STATE_UNACKNOWLEDGED | SERVICE_CHECKS_ENABLED, services_unknown_unacknowledged); + printf("\n", STATUS_CGI, url_encode(temp_hostgroup->group_name), SERVICE_UNKNOWN, SD_HOST_UP | HOST_PENDING, SERVICE_NO_SCHEDULED_DOWNTIME | SERVICE_STATE_UNACKNOWLEDGED | SERVICE_CHECKS_ENABLED, services_unknown_unacknowledged); if(services_unknown_host_problem > 0) - printf("\n", STATUS_CGI, url_encode(temp_hostgroup->group_name), SERVICE_UNKNOWN, HOST_DOWN | HOST_UNREACHABLE, services_unknown_host_problem); + printf("\n", STATUS_CGI, url_encode(temp_hostgroup->group_name), SERVICE_UNKNOWN, SD_HOST_DOWN | SD_HOST_UNREACHABLE, services_unknown_host_problem); if(services_unknown_scheduled > 0) printf("\n", STATUS_CGI, url_encode(temp_hostgroup->group_name), SERVICE_UNKNOWN, SERVICE_SCHEDULED_DOWNTIME, services_unknown_scheduled); @@ -4347,10 +4466,10 @@ void show_hostgroup_service_totals_summary(hostgroup *temp_hostgroup) { printf("
%d Unhandled
%d Unhandled
%d on Problem Hosts
%d on Problem Hosts
%d Scheduled
\n"); if(services_critical_unacknowledged > 0) - printf("\n", STATUS_CGI, url_encode(temp_hostgroup->group_name), SERVICE_CRITICAL, HOST_UP | HOST_PENDING, SERVICE_NO_SCHEDULED_DOWNTIME | SERVICE_STATE_UNACKNOWLEDGED | SERVICE_CHECKS_ENABLED, services_critical_unacknowledged); + printf("\n", STATUS_CGI, url_encode(temp_hostgroup->group_name), SERVICE_CRITICAL, SD_HOST_UP | HOST_PENDING, SERVICE_NO_SCHEDULED_DOWNTIME | SERVICE_STATE_UNACKNOWLEDGED | SERVICE_CHECKS_ENABLED, services_critical_unacknowledged); if(services_critical_host_problem > 0) - printf("\n", STATUS_CGI, url_encode(temp_hostgroup->group_name), SERVICE_CRITICAL, HOST_DOWN | HOST_UNREACHABLE, services_critical_host_problem); + printf("\n", STATUS_CGI, url_encode(temp_hostgroup->group_name), SERVICE_CRITICAL, SD_HOST_DOWN | SD_HOST_UNREACHABLE, services_critical_host_problem); if(services_critical_scheduled > 0) printf("\n", STATUS_CGI, url_encode(temp_hostgroup->group_name), SERVICE_CRITICAL, SERVICE_SCHEDULED_DOWNTIME, services_critical_scheduled); @@ -4487,9 +4606,9 @@ void show_hostgroup_grids(void) { /* displays status grid for a specific hostgroup */ void show_hostgroup_grid(hostgroup *temp_hostgroup) { hostsmember *temp_member; - char *status_bg_class = ""; - char *host_status_class = ""; - char *service_status_class = ""; + const char *status_bg_class = ""; + const char *host_status_class = ""; + const char *service_status_class = ""; host *temp_host; service *temp_service; hoststatus *temp_hoststatus; @@ -4516,6 +4635,10 @@ void show_hostgroup_grid(hostgroup *temp_hostgroup) { if(temp_host == NULL) continue; + /* make sure user has rights to view this host */ + if(is_authorized_for_host(temp_host, ¤t_authdata) == FALSE) + continue; + /* grab macros */ grab_host_macros_r(mac, temp_host); @@ -4536,9 +4659,9 @@ void show_hostgroup_grid(hostgroup *temp_hostgroup) { printf("\n", status_bg_class); /* get the status of the host */ - if(temp_hoststatus->status == HOST_DOWN) + if(temp_hoststatus->status == SD_HOST_DOWN) host_status_class = "HOStdOWN"; - else if(temp_hoststatus->status == HOST_UNREACHABLE) + else if(temp_hoststatus->status == SD_HOST_UNREACHABLE) host_status_class = "HOSTUNREACHABLE"; else host_status_class = status_bg_class; @@ -5056,16 +5179,16 @@ int passes_host_properties_filter(hoststatus *temp_hoststatus) { if((host_properties & HOST_NOTIFICATIONS_ENABLED) && temp_hoststatus->notifications_enabled == FALSE) return FALSE; - if((host_properties & HOST_PASSIVE_CHECKS_DISABLED) && temp_hoststatus->accept_passive_host_checks == TRUE) + if((host_properties & HOST_PASSIVE_CHECKS_DISABLED) && temp_hoststatus->accept_passive_checks == TRUE) return FALSE; - if((host_properties & HOST_PASSIVE_CHECKS_ENABLED) && temp_hoststatus->accept_passive_host_checks == FALSE) + if((host_properties & HOST_PASSIVE_CHECKS_ENABLED) && temp_hoststatus->accept_passive_checks == FALSE) return FALSE; - if((host_properties & HOST_PASSIVE_CHECK) && temp_hoststatus->check_type == HOST_CHECK_ACTIVE) + if((host_properties & HOST_PASSIVE_CHECK) && temp_hoststatus->check_type == CHECK_TYPE_ACTIVE) return FALSE; - if((host_properties & HOST_ACTIVE_CHECK) && temp_hoststatus->check_type == HOST_CHECK_PASSIVE) + if((host_properties & HOST_ACTIVE_CHECK) && temp_hoststatus->check_type == CHECK_TYPE_PASSIVE) return FALSE; if((host_properties & HOST_HARD_STATE) && temp_hoststatus->state_type == SOFT_STATE) @@ -5124,16 +5247,16 @@ int passes_service_properties_filter(servicestatus *temp_servicestatus) { if((service_properties & SERVICE_NOTIFICATIONS_ENABLED) && temp_servicestatus->notifications_enabled == FALSE) return FALSE; - if((service_properties & SERVICE_PASSIVE_CHECKS_DISABLED) && temp_servicestatus->accept_passive_service_checks == TRUE) + if((service_properties & SERVICE_PASSIVE_CHECKS_DISABLED) && temp_servicestatus->accept_passive_checks == TRUE) return FALSE; - if((service_properties & SERVICE_PASSIVE_CHECKS_ENABLED) && temp_servicestatus->accept_passive_service_checks == FALSE) + if((service_properties & SERVICE_PASSIVE_CHECKS_ENABLED) && temp_servicestatus->accept_passive_checks == FALSE) return FALSE; - if((service_properties & SERVICE_PASSIVE_CHECK) && temp_servicestatus->check_type == SERVICE_CHECK_ACTIVE) + if((service_properties & SERVICE_PASSIVE_CHECK) && temp_servicestatus->check_type == CHECK_TYPE_ACTIVE) return FALSE; - if((service_properties & SERVICE_ACTIVE_CHECK) && temp_servicestatus->check_type == SERVICE_CHECK_PASSIVE) + if((service_properties & SERVICE_ACTIVE_CHECK) && temp_servicestatus->check_type == CHECK_TYPE_PASSIVE) return FALSE; if((service_properties & SERVICE_HARD_STATE) && temp_servicestatus->state_type == SOFT_STATE) @@ -5170,15 +5293,15 @@ void show_filters(void) { printf(" Pending"); found = 1; } - if(host_status_types & HOST_UP) { + if(host_status_types & SD_HOST_UP) { printf("%s Up", (found == 1) ? " |" : ""); found = 1; } - if(host_status_types & HOST_DOWN) { + if(host_status_types & SD_HOST_DOWN) { printf("%s Down", (found == 1) ? " |" : ""); found = 1; } - if(host_status_types & HOST_UNREACHABLE) + if(host_status_types & SD_HOST_UNREACHABLE) printf("%s Unreachable", (found == 1) ? " |" : ""); } printf(""); @@ -5400,49 +5523,48 @@ void show_filters(void) { return; } -void create_pagenumbers(int total_entries, int visible_entries, char *temp_url, int type_service) { +void create_pagenumbers(int total_entries,char *temp_url,int type_service) { int pages = 1; - int leftovers = 0; int tmp_start; - int i; - int next_page; + int i, last_page; int previous_page; /* do page numbers if applicable */ if(result_limit > 0 && total_entries > result_limit) { pages = (total_entries / result_limit); - leftovers = (total_entries % result_limit); - previous_page = (page_start - result_limit) > 0 ? (page_start - result_limit) : 0; - next_page = (page_start + result_limit) > total_entries ? page_start : (page_start + result_limit); + last_page = pages; + if (total_entries % result_limit > 0) + ++last_page; + previous_page = (page_start-result_limit) > 0 ? (page_start-result_limit) : 0; printf("
\n"); printf("
\n"); - printf("<<\n", temp_url, result_limit, url_images_path, FIRST_PAGE_ICON); - printf("<\n", temp_url, previous_page, result_limit, url_images_path, PREVIOUS_PAGE_ICON); + printf("<<\n",temp_url,result_limit,url_images_path,FIRST_PAGE_ICON); + printf("<\n",temp_url,previous_page,result_limit,url_images_path,PREVIOUS_PAGE_ICON); - for(i = 0; i < (pages + 1); i++) { + for(i = 0; i < last_page; i++) { tmp_start = (i * result_limit); if(tmp_start == page_start) - printf("
%i
\n", (i + 1)); + printf("
%i
\n",(i+1)); else - printf(" %i \n", temp_url, tmp_start, result_limit, (i + 1), (i + 1)); + printf(" %i \n",temp_url,tmp_start,result_limit,(i+1),(i+1)); } - printf(">\n", temp_url, (page_start + result_limit), result_limit, url_images_path, NEXT_PAGE_ICON); - printf(">>\n", temp_url, ((pages)*result_limit), result_limit, url_images_path, LAST_PAGE_ICON); + printf(">\n",temp_url,(page_start+result_limit),result_limit,url_images_path,NEXT_PAGE_ICON); + printf(">>\n",temp_url,((pages)*result_limit),result_limit,url_images_path,LAST_PAGE_ICON); printf("
\n"); if(type_service == TRUE) - printf("
Results %i - %i of %d Matching Services
\n
\n", page_start, ((page_start + result_limit) > total_entries ? total_entries : (page_start + result_limit)), total_entries); + printf("
Results %i - %i of %d Matching Services
\n\n",page_start,((page_start+result_limit) > total_entries ? total_entries :(page_start+result_limit) ),total_entries ); else - printf("
Results %i - %i of %d Matching Hosts
\n\n", page_start, ((page_start + result_limit) > total_entries ? total_entries : (page_start + result_limit)), total_entries); + printf("
Results %i - %i of %d Matching Hosts
\n\n",page_start,((page_start+result_limit) > total_entries ? total_entries :(page_start+result_limit) ),total_entries ); printf("\n\n"); } else { if(type_service == TRUE) - printf("
Results %i - %i of %d Matching Services
\n\n", 1, total_entries, total_entries); + printf("
Results %i - %i of %d Matching Services
\n\n",1,total_entries,total_entries); else - printf("
Results %i - %i of %d Matching Hosts
\n\n", 1, total_entries, total_entries); + printf("
Results %i - %i of %d Matching Hosts
\n\n",1,total_entries,total_entries); } @@ -5451,19 +5573,18 @@ void create_pagenumbers(int total_entries, int visible_entries, char *temp_url, } -void create_page_limiter(int result_limit, char *temp_url) { +void create_page_limiter(int limit,char *temp_url) { /* Result Limit Select Box */ printf("
\n
\n"); printf("\n"); - printf("\n",temp_url); + printf("\n",( (limit==50) ? "selected='selected'" : "") ); + printf("\n",( (limit==100) ? "selected='selected'" : "") ); + printf("\n",( (limit==250) ? "selected='selected'" : "") ); + printf("\n",( (limit==1000) ? "selected='selected'" : "") ); + printf("\n",(limit==0) ? "selected='selected'" : ""); printf("
\n"); printf("
\n
\n"); //page numbers - } diff --git a/cgi/statusjson.c b/cgi/statusjson.c new file mode 100644 index 0000000..e01fb54 --- /dev/null +++ b/cgi/statusjson.c @@ -0,0 +1,4962 @@ +/************************************************************************** + * + * STATUSJSON.C - Nagios CGI for returning JSON-formatted status data + * + * Copyright (c) 2013 Nagios Enterprises, LLC + * Last Modified: 04-13-2013 + * + * License: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + *************************************************************************/ + +/* + TODO: + Return an error when the authenticated user is not authorized + for the requested host or service + Consolidate criteria functions for *count and *list queries + Move static programstatus information to objectjson.c? +*/ + +#include "../include/config.h" +#include "../include/common.h" +#include "../include/objects.h" +#include "../include/statusdata.h" +#include "../include/comments.h" +#include "../include/downtime.h" + +#include "../include/cgiutils.h" +#include "../include/getcgi.h" +#include "../include/cgiauth.h" +#include "../include/jsonutils.h" +#include "../include/objectjson.h" +#include "../include/statusjson.h" + +#define THISCGI "statusjson.cgi" + +#ifdef JSON_NAGIOS_4X +#define HOST_STATUS_ALL (SD_HOST_UP | SD_HOST_DOWN | SD_HOST_UNREACHABLE | HOST_PENDING) +#define SERVICE_STATUS_ALL (SERVICE_OK | SERVICE_WARNING | SERVICE_CRITICAL | SERVICE_UNKNOWN | SERVICE_PENDING) +#else +#define HOST_STATUS_ALL (HOST_UP | HOST_DOWN | HOST_UNREACHABLE | HOST_PENDING) +#define SERVICE_STATUS_ALL (SERVICE_OK | SERVICE_WARNING | SERVICE_CRITICAL | SERVICE_UNKNOWN | SERVICE_PENDING) +#endif + +extern char main_config_file[MAX_FILENAME_LENGTH]; +extern char *status_file; + +extern host *host_list; +extern hoststatus *hoststatus_list; +extern service *service_list; +#if 0 +extern contact *contact_list; +#endif +extern servicestatus *servicestatus_list; +extern nagios_comment *comment_list; +extern scheduled_downtime *scheduled_downtime_list; + +/* Program status variables */ +extern unsigned long modified_host_process_attributes; +extern unsigned long modified_service_process_attributes; +extern int nagios_pid; +extern int daemon_mode; +extern time_t program_start; +#ifndef JSON_NAGIOS_4X +extern time_t last_command_check; +#endif +extern time_t last_log_rotation; +extern int enable_notifications; +extern int execute_service_checks; +extern int accept_passive_service_checks; +extern int execute_host_checks; +extern int accept_passive_host_checks; +extern int enable_event_handlers; +extern int obsess_over_services; +extern int obsess_over_hosts; +extern int check_service_freshness; +extern int check_host_freshness; +extern int enable_flap_detection; +#ifndef JSON_NAGIOS_4X +extern int enable_failure_prediction; +#endif +extern int process_performance_data; +#if 0 +extern char *global_host_event_handler; +extern char *global_service_event_handler; +extern unsigned long next_comment_id; +extern unsigned long next_downtime_id; +extern unsigned long next_event_id; +extern unsigned long next_problem_id; +extern unsigned long next_notification_id; +extern int external_command_buffer_slots; +extern check_stats check_statistics[MAX_CHECK_STATS_TYPES]; +#endif + +/* Performance data variables */ +extern int program_stats[MAX_CHECK_STATS_TYPES][3]; +extern int buffer_stats[1][3]; + +void document_header(int); +void document_footer(void); +void init_cgi_data(status_json_cgi_data *); +int process_cgivars(json_object *, status_json_cgi_data *, time_t); +void free_cgi_data(status_json_cgi_data *); +int validate_arguments(json_object *, status_json_cgi_data *, time_t); + +authdata current_authdata; + +const string_value_mapping valid_queries[] = { + { "hostcount", STATUS_QUERY_HOSTCOUNT, + "Return the number of hosts in each state" }, + { "hostlist", STATUS_QUERY_HOSTLIST, + "Return a list of hosts and their current status" }, + { "host", STATUS_QUERY_HOST, + "Return the status of a single host." }, + { "servicecount", STATUS_QUERY_SERVICECOUNT, + "Return the number of services in each state" }, + { "servicelist", STATUS_QUERY_SERVICELIST, + "Return a list of services and their current status" }, + { "service", STATUS_QUERY_SERVICE, + "Return the status of a single service" }, +#if 0 + { "contactcount", STATUS_QUERY_CONTACTCOUNT, + "Return the number of contacts" }, + { "contactlist", STATUS_QUERY_CONTACTLIST, + "Return a list of of contacts and their current status" }, + { "contact", STATUS_QUERY_CONTACT, + "Return a single contact" }, +#endif + { "commentcount", STATUS_QUERY_COMMENTCOUNT, + "Return the number of comments" }, + { "commentlist", STATUS_QUERY_COMMENTLIST, + "Return a list of comments" }, + { "comment", STATUS_QUERY_COMMENT, + "Return a single comment" }, + { "downtimecount", STATUS_QUERY_DOWNTIMECOUNT, + "Return the number of downtimes" }, + { "downtimelist", STATUS_QUERY_DOWNTIMELIST, + "Return a list of downtimes" }, + { "downtime", STATUS_QUERY_DOWNTIME, + "Return a single downtime" }, + { "programstatus", STATUS_QUERY_PROGRAMSTATUS, + "Return the Nagios Core program status" }, + { "performancedata", STATUS_QUERY_PERFORMANCEDATA, + "Return the Nagios Core performance data" }, + { "help", STATUS_QUERY_HELP, + "Display help for this CGI" }, + { NULL, -1, NULL}, + }; + +static const int query_status[][2] = { + { STATUS_QUERY_HOSTCOUNT, QUERY_STATUS_RELEASED }, + { STATUS_QUERY_HOSTLIST, QUERY_STATUS_RELEASED }, + { STATUS_QUERY_HOST, QUERY_STATUS_RELEASED }, + { STATUS_QUERY_SERVICECOUNT, QUERY_STATUS_RELEASED }, + { STATUS_QUERY_SERVICELIST, QUERY_STATUS_RELEASED }, + { STATUS_QUERY_SERVICE, QUERY_STATUS_RELEASED }, +#if 0 + { STATUS_QUERY_CONTACTCOUNT, QUERY_STATUS_BETA }, + { STATUS_QUERY_CONTACTLIST, QUERY_STATUS_BETA }, + { STATUS_QUERY_CONTACT, QUERY_STATUS_BETA }, +#endif + { STATUS_QUERY_COMMENTCOUNT, QUERY_STATUS_RELEASED }, + { STATUS_QUERY_COMMENTLIST, QUERY_STATUS_RELEASED }, + { STATUS_QUERY_COMMENT, QUERY_STATUS_RELEASED }, + { STATUS_QUERY_DOWNTIMECOUNT, QUERY_STATUS_RELEASED }, + { STATUS_QUERY_DOWNTIMELIST, QUERY_STATUS_RELEASED }, + { STATUS_QUERY_DOWNTIME, QUERY_STATUS_RELEASED }, + { STATUS_QUERY_PROGRAMSTATUS, QUERY_STATUS_RELEASED }, + { STATUS_QUERY_PERFORMANCEDATA, QUERY_STATUS_RELEASED }, + { STATUS_QUERY_HELP, QUERY_STATUS_RELEASED }, + { -1, -1}, + }; + +const string_value_mapping svm_host_time_fields[] = { + { "lastupdate", STATUS_TIME_LAST_UPDATE, "Last Update" }, + { "lastcheck", STATUS_TIME_LAST_CHECK, "Last Check" }, + { "nextcheck", STATUS_TIME_NEXT_CHECK, "Next Check" }, + { "laststatechange", STATUS_TIME_LAST_STATE_CHANGE, "Last State Change" }, + { "lasthardstatechange", STATUS_TIME_LAST_HARD_STATE_CHANGE, + "Last Hard State Change" }, + { "lasttimeup", STATUS_TIME_LAST_TIME_UP, "Last Time Up" }, + { "lasttimedown", STATUS_TIME_LAST_TIME_DOWN, "Last Time Down" }, + { "lasttimeunreachable", STATUS_TIME_LAST_TIME_UNREACHABLE, + "Last Time Unreachable" }, + { "lastnotification", STATUS_TIME_LAST_NOTIFICATION, "Last Notification" }, + { "nextnotification", STATUS_TIME_NEXT_NOTIFICATION, "Next Notification" }, + { NULL, -1, NULL }, + }; + +const string_value_mapping svm_service_time_fields[] = { + { "lastupdate", STATUS_TIME_LAST_UPDATE, "Last Update" }, + { "lastcheck", STATUS_TIME_LAST_CHECK, "Last Check" }, + { "nextcheck", STATUS_TIME_NEXT_CHECK, "Next Check" }, + { "laststatechange", STATUS_TIME_LAST_STATE_CHANGE, "Last State Change" }, + { "lasthardstatechange", STATUS_TIME_LAST_HARD_STATE_CHANGE, + "Last Hard State Change" }, + { "lasttimeok", STATUS_TIME_LAST_TIME_OK, "Last Time OK" }, + { "lasttimewarning", STATUS_TIME_LAST_TIME_WARNING, "Last Time Warning" }, + { "lasttimecritical", STATUS_TIME_LAST_TIME_CRITICAL, + "Last Time Critical" }, + { "lasttimeunknown", STATUS_TIME_LAST_TIME_UNKNOWN, "Last Time Unknown" }, + { "lastnotification", STATUS_TIME_LAST_NOTIFICATION, "Last Notification" }, + { "nextnotification", STATUS_TIME_NEXT_NOTIFICATION, "Next Notification" }, + { NULL, -1, NULL }, + }; + +const string_value_mapping svm_valid_comment_types[] = { + { "host", COMMENT_TYPE_HOST, "Host Comment" }, + { "service", COMMENT_TYPE_SERVICE, "Service Comment" }, + { NULL, -1, NULL }, + }; + +const string_value_mapping svm_valid_comment_entry_types[] = { + { "user", COMMENT_ENTRY_USER, "User Comment" }, + { "downtime", COMMENT_ENTRY_DOWNTIME, "Downtime Comment" }, + { "flapping", COMMENT_ENTRY_FLAPPING, "Flapping Comment" }, + { "acknowledgement", COMMENT_ENTRY_ACKNOWLEDGEMENT, + "Acknowledgement Comment" }, + { NULL, -1, NULL }, + }; + +const string_value_mapping svm_valid_persistence[] = { + { "yes", BOOLEAN_TRUE, "Persistent Comment" }, + { "no", BOOLEAN_FALSE, "Non-Persistent Comment" }, + { NULL, -1, NULL }, + }; + +const string_value_mapping svm_valid_expiration[] = { + { "yes", BOOLEAN_TRUE, "Comment Expires" }, + { "no", BOOLEAN_FALSE, "Comment Does Not Expire" }, + { NULL, -1, NULL }, + }; + +const string_value_mapping svm_comment_time_fields[] = { + { "entrytime", STATUS_TIME_ENTRY_TIME, "Entry Time" }, + { "expiretime", STATUS_TIME_EXPIRE_TIME, "Expiration Time" }, + { NULL, -1, NULL }, + }; + +const string_value_mapping svm_downtime_time_fields[] = { + { "entrytime", STATUS_TIME_ENTRY_TIME, "Entry Time" }, + { "starttime", STATUS_TIME_START_TIME, "Start Time" }, + { "flexdowntimestart", STATUS_TIME_FLEX_DOWNTIME_START, + "Flex Downtime Start" }, + { "endtime", STATUS_TIME_END_TIME, "End Time" }, + { NULL, -1, NULL }, + }; + +const string_value_mapping svm_valid_downtime_object_types[] = { + { "host", DOWNTIME_OBJECT_TYPE_HOST, "Host Downtime" }, + { "service", DOWNTIME_OBJECT_TYPE_SERVICE, "Service Downtime" }, + { NULL, -1, NULL }, + }; + +const string_value_mapping svm_valid_downtime_types[] = { + { "fixed", DOWNTIME_TYPE_FIXED, "Fixed Downtime" }, + { "flexible", DOWNTIME_TYPE_FLEXIBLE, "Flexible Downtime" }, + { NULL, -1, NULL }, + }; + +const string_value_mapping svm_valid_triggered_status[] = { + { "yes", BOOLEAN_TRUE, "Downtime Triggered" }, + { "no", BOOLEAN_FALSE, "Downtime Not Triggered" }, + { NULL, -1, NULL }, + }; + +const string_value_mapping svm_valid_in_effect_status[] = { + { "yes", BOOLEAN_TRUE, "Downtime In Effect" }, + { "no", BOOLEAN_FALSE, "Downtime Not In Effect" }, + { NULL, -1, NULL }, + }; + +option_help status_json_help[] = { + { + "query", + "Query", + "enumeration", + { "all", NULL }, + { NULL }, + NULL, + "Specifies the type of query to be executed.", + valid_queries + }, + { + "formatoptions", + "Format Options", + "list", + { NULL }, + { "all", NULL }, + NULL, + "Specifies the formatting options to be used when displaying the results. Multiple options are allowed and are separated by a plus (+) sign..", + svm_format_options + }, + { + "start", + "Start", + "integer", + { NULL }, + { "hostlist", "servicelist", NULL }, + NULL, + "Specifies the index (zero-based) of the first object in the list to be returned.", + NULL + }, + { + "count", + "Count", + "integer", + { NULL }, + { "hostlist", "servicelist", NULL }, + NULL, + "Specifies the number of objects in the list to be returned.", + NULL + }, + { + "parenthost", + "Parent Host", + "nagios:objectjson/hostlist", + { NULL }, + { "hostcount", "hostlist", "servicecount", "servicelist", NULL }, + NULL, + "Limits the hosts or services returned to those whose host parent is specified. A value of 'none' returns all hosts or services reachable directly by the Nagios core host.", + parent_host_extras + }, + { + "childhost", + "Child Host", + "nagios:objectjson/hostlist", + { NULL }, + { "hostcount", "hostlist", "servicecount", "servicelist", NULL }, + NULL, + "Limits the hosts or services returned to those whose having the host specified as a child host. A value of 'none' returns all hosts or services with no child hosts.", + child_host_extras + }, + { + "details", + "Show Details", + "boolean", + { NULL }, + { "hostlist", "servicelist", "commentlist", "downtimelist", NULL }, + NULL, + "Returns the details for all entities in the list.", + NULL + }, + { + "dateformat", + "Date Format", + "string", + { NULL }, + { "all", NULL }, + NULL, + "strftime format string for values of type time_t. In the absence of a format, the Javascript default format of the number of milliseconds since the beginning of the Unix epoch is used. Because of URL encoding, percent signs must be encoded as %25 and a space must be encoded as a plus (+) sign.", + NULL + }, + { + "hostname", + "Host Name", + "nagios:objectjson/hostlist", + { "host", "service", NULL }, + { "servicecount", "servicelist", "commentcount", "commentlist", "downtimecount", "downtimelist", NULL }, + NULL, + "Name for the host requested.", + NULL + }, + { + "hostgroup", + "Host Group", + "nagios:objectjson/hostgrouplist", + { "hostgroup", NULL }, + { "hostcount", "hostlist", "servicecount", "servicelist", NULL }, + NULL, + "Returns information applicable to the hostgroup or the hosts in the hostgroup depending on the query.", + NULL + }, + { + "hoststatus", + "Host Status", + "list", + { NULL }, + { "hostcount", "hostlist", "servicecount", "servicelist", NULL }, + NULL, + "Limits returned information to those hosts whose status matches this list. Host statuses are space separated.", + svm_host_statuses + }, + { + "servicegroup", + "Service Group", + "nagios:objectjson/servicegrouplist", + { "servicegroup", NULL }, + { "servicecount", "servicelist", NULL }, + NULL, + "Returns information applicable to the servicegroup or the services in the servicegroup depending on the query.", + NULL + }, + { + "servicestatus", + "Service Status", + "list", + { NULL }, + { "servicecount", "servicelist" }, + NULL, + "Limits returned information to those services whose status matches this list. Service statuses are space separated.", + svm_service_statuses + }, + { + "parentservice", + "Parent Service", + "nagios:objectjson/servicelist", + { NULL }, + { "servicecount", "servicelist", NULL }, + NULL, + "Limits the services returned to those whose service parent has the name specified. A value of 'none' returns all services with no service parent.", + parent_service_extras + }, + { + "childservice", + "Child Service", + "nagios:objectjson/servicelist", + { NULL }, + { "servicecount", "servicelist", NULL }, + NULL, + "Limits the services returned to those whose having the named service as a child service. A value of 'none' returns all services with no child services.", + child_service_extras + }, + { + "contactgroup", + "Contact Group", + "nagios:objectjson/contactgrouplist", + { "contactgroup", NULL }, + { "hostcount", "hostlist", "servicecount", "servicelist", NULL }, + NULL, + "Returns information applicable to the contactgroup or the contacts in the contactgroup depending on the query.", + NULL + }, + { + "servicedescription", + "Service Description", + "nagios:objectjson/servicelist", + /* "for query: 'service'",*/ + { "service", NULL }, + { "servicecount", "servicelist", "commentcount", "commentlist", "downtimecount", "downtimelist", NULL }, + "hostname", + "Description for the service requested.", + NULL + }, + { + "checktimeperiod", + "Check Timeperiod Name", + "nagios:objectjson/timeperiodlist", + { NULL }, + { "hostcount","hostlist", "servicecount", "servicelist", NULL }, + NULL, + "Name of a check timeperiod to be used as selection criteria.", + NULL + }, + { + "hostnotificationtimeperiod", + "Host Notification Timeperiod Name", + "nagios:objectjson/timeperiodlist", + { NULL }, + { "hostcount","hostlist", NULL }, + NULL, + "Name of a host notification timeperiod to be used as selection criteria.", + NULL + }, + { + "servicenotificationtimeperiod", + "Service Notification Timeperiod Name", + "nagios:objectjson/timeperiodlist", + { NULL }, + { "servicecount", "servicelist", NULL }, + NULL, + "Name of a service notification timeperiod to be used as selection criteria.", + NULL + }, + { + "checkcommand", + "Check Command Name", + "nagios:objectjson/commandlist", + { NULL }, + { "hostcount", "hostlist", "servicecount", "servicelist", NULL }, + NULL, + "Name of a check command to be be used as a selector.", + NULL + }, + { + "eventhandler", + "Event Handler Name", + "nagios:objectjson/commandlist", + { NULL }, + { "hostcount", "hostlist", "servicecount", "servicelist", NULL }, + NULL, + "Name of an event handler to be be used as a selector.", + NULL + }, + { + "commenttypes", + "Comment Type", + "list", + { NULL }, + { "commentcount", "commentlist", NULL }, + NULL, + "Comment type for the comment requested.", + svm_valid_comment_types + }, + { + "entrytypes", + "Entry Type", + "list", + { NULL }, + { "commentcount", "commentlist", NULL }, + NULL, + "Entry type for the comment requested.", + svm_valid_comment_entry_types + }, + { + "persistence", + "Comment Persistence", + "list", + { NULL }, + { "commentcount", "commentlist", NULL }, + NULL, + "Persistence for the comment requested.", + svm_valid_persistence + }, + { + "expiring", + "Comment Expiration", + "list", + { NULL }, + { "commentcount", "commentlist", NULL }, + NULL, + "Whether or not the comment expires.", + svm_valid_expiration + }, + { + "downtimeobjecttypes", + "Downtime Object Type", + "list", + { NULL }, + { "downtimecount", "downtimelist", NULL }, + NULL, + "The type of object to which the downtime applies.", + svm_valid_downtime_object_types + }, + { + "downtimetypes", + "Downtime Type", + "list", + { NULL }, + { "downtimecount", "downtimelist", NULL }, + NULL, + "The type of the downtime.", + svm_valid_downtime_types + }, + { + "triggered", + "Downtime Triggered", + "list", + { NULL }, + { "downtimecount", "downtimelist", NULL }, + NULL, + "Whether or not the downtime is triggered.", + svm_valid_triggered_status + }, + { + "triggeredby", + "Triggered By", + "nagios:statusjson/downtimelist", + { NULL }, + { "downtimecount", "downtimelist", NULL }, + NULL, + "ID of the downtime which triggers other downtimes.", + NULL + }, + { + "ineffect", + "Downtime In Effect", + "list", + { NULL }, + { "downtimecount", "downtimelist", NULL }, + NULL, + "Whether or not the downtime is in effect.", + svm_valid_in_effect_status + }, + { + "commentid", + "Comment ID", + "nagios:statusjson/commentlist", + { "comment", NULL }, + { NULL }, + NULL, + "Comment ID for the comment requested.", + NULL + }, + { + "downtimeid", + "Downtime ID", + "nagios:statusjson/downtimelist", + { "downtime", NULL }, + { NULL }, + NULL, + "Downtime ID for the downtime requested.", + NULL + }, + { + "contactname", + "Contact Name", + "nagios:objectjson/contactlist", + { NULL }, + { "hostcount", "hostlist", "servicecount", "servicelist", NULL }, + NULL, + "Name for the contact requested.", + NULL + }, + { + "hosttimefield", + "Host Time Field", + "enumeration", + { NULL }, + { "hostcount", "hostlist", NULL }, + NULL, + "Field to use when comparing times on a hostlist query.", + svm_host_time_fields + }, + { + "servicetimefield", + "Service Time Field", + "enumeration", + { NULL }, + { "servicecount", "servicelist", NULL }, + NULL, + "Field to use when comparing times on a servicelist query.", + svm_service_time_fields + }, + { + "commenttimefield", + "Comment Time Field", + "enumeration", + { NULL }, + { "commentcount", "commentlist", NULL }, + NULL, + "Field to use when comparing times on a commentlist query.", + svm_comment_time_fields + }, + { + "downtimetimefield", + "Downtime Time Field", + "enumeration", + { NULL }, + { "downtimecount", "downtimelist", NULL }, + NULL, + "Field to use when comparing times on a downtimelist query.", + svm_downtime_time_fields + }, + { + "starttime", + "Start Time", + "integer", + { NULL }, + { "hostcount", "hostlist", "servicecount", "servicelist", "commentcount", + "commentlist", "downtimecount", "downtimelist", NULL }, + NULL, + "Starting time to use when querying based on a time range. Not specifying a start time implies all entries since the beginning of time. Supplying a plus or minus sign means times relative to the query time.", + NULL, + }, + { + "endtime", + "End Time", + "integer", + { NULL }, + { "hostcount", "hostlist", "servicecount", "servicelist", "commentcount", + "commentlist", "downtimecount", "downtimelist", NULL }, + NULL, + "Ending time to use when querying based on a time range. Not specifying an end time implies all entries until the time of the query. Specifying plus or minus sign means times relative to the query time.", + NULL, + }, + { /* The last entry must contain all NULL entries */ + NULL, + NULL, + NULL, + { NULL }, + { NULL }, + NULL, + NULL, + NULL + }, + }; + +extern const json_escape percent_escapes; + +int json_status_host_passes_selection(host *, int, host *, int, host *, + hostgroup *, contact *, hoststatus *, int, time_t, time_t, + contactgroup *, timeperiod *, timeperiod *, command *, command *); +json_object *json_status_host_display_selectors(unsigned, int, int, int, host *, + int, host *, hostgroup *, int, contact *, int, time_t, time_t, + contactgroup *, timeperiod *, timeperiod *, command *, command *); + +int json_status_service_passes_host_selection(host *, int, host *, int, host *, + hostgroup *, host *, int); +int json_status_service_passes_service_selection(service *, servicegroup *, + contact *, servicestatus *, int, time_t, time_t, char *, char *, + char *, contactgroup *, timeperiod *, timeperiod *, command *, + command *); +json_object *json_status_service_selectors(unsigned, int, int, int, host *, int, + host *, hostgroup *, host *, servicegroup *, int, int, contact *, int, + time_t, time_t, char *, char *, char *, contactgroup *, timeperiod *, + timeperiod *, command *, command *); + +int json_status_comment_passes_selection(nagios_comment *, int, time_t, time_t, + unsigned, unsigned, unsigned, unsigned, char *, char *); +json_object *json_status_comment_selectors(unsigned, int, int, int, time_t, + time_t, unsigned, unsigned, unsigned, unsigned, char *, char *); + +int json_status_downtime_passes_selection(scheduled_downtime *, int, time_t, + time_t, unsigned, unsigned, unsigned, int, unsigned, char *, char *); +json_object *json_status_downtime_selectors(unsigned, int, int, int, time_t, + time_t, unsigned, unsigned, unsigned, int, unsigned, char *, char *); + +int main(void) { + int result = OK; + time_t query_time; + status_json_cgi_data cgi_data; + json_object *json_root; + struct stat sdstat; + time_t last_status_data_update = (time_t)0; + hoststatus *temp_hoststatus = NULL; + servicestatus *temp_servicestatus = NULL; + + /* The official time of the query */ + time(&query_time); + + json_root = json_new_object(); + if(NULL == json_root) { + printf( "Failed to create new json object\n"); + exit( 1); + } + json_object_append_integer(json_root, "format_version", + OUTPUT_FORMAT_VERSION); + + /* Initialize shared configuration variables */ + init_shared_cfg_vars(1); + + init_cgi_data(&cgi_data); + + document_header(cgi_data.format_options & JSON_FORMAT_WHITESPACE); + + /* get the arguments passed in the URL */ + result = process_cgivars(json_root, &cgi_data, query_time); + if(result != RESULT_SUCCESS) { + json_object_append_object(json_root, "data", json_help(status_json_help)); + json_object_print(json_root, 0, 1, cgi_data.strftime_format, + cgi_data.format_options); + document_footer(); + return ERROR; + } + + /* reset internal variables */ + reset_cgi_vars(); + + /* read the CGI configuration file */ + result = read_cgi_config_file(get_cgi_config_location()); + if(result == ERROR) { + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + (time_t)-1, NULL, RESULT_FILE_OPEN_READ_ERROR, + "Error: Could not open CGI configuration file '%s' for reading!", + get_cgi_config_location())); + json_object_append_object(json_root, "data", json_help(status_json_help)); + json_object_print(json_root, 0, 1, cgi_data.strftime_format, + cgi_data.format_options); + document_footer(); + return ERROR; + } + + /* read the main configuration file */ + result = read_main_config_file(main_config_file); + if(result == ERROR) { + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + (time_t)-1, NULL, RESULT_FILE_OPEN_READ_ERROR, + "Error: Could not open main configuration file '%s' for reading!", + main_config_file)); + json_object_append_object(json_root, "data", json_help(status_json_help)); + json_object_print(json_root, 0, 1, cgi_data.strftime_format, + cgi_data.format_options); + document_footer(); + return ERROR; + } + + /* read all object configuration data */ + result = read_all_object_configuration_data(main_config_file, + READ_ALL_OBJECT_DATA); + if(result == ERROR) { + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + (time_t)-1, NULL, RESULT_FILE_OPEN_READ_ERROR, + "Error: Could not read some or all object configuration data!")); + json_object_append_object(json_root, "data", json_help(status_json_help)); + json_object_print(json_root, 0, 1, cgi_data.strftime_format, + cgi_data.format_options); + document_footer(); + return ERROR; + } + + /* Get the update time on the status data file. This needs to occur before + the status data is read because the read_all_status_data() function + clears the name of the status file */ + if(stat(status_file, &sdstat) < 0) { + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + (time_t)-1, NULL, RESULT_FILE_OPEN_READ_ERROR, + "Error: Could not obtain status data file status: %s!", + strerror(errno))); + json_object_append_object(json_root, "data", json_help(status_json_help)); + document_footer(); + return ERROR; + } + last_status_data_update = sdstat.st_mtime; + + /* read all status data */ + result = read_all_status_data(status_file, READ_ALL_STATUS_DATA); + if(result == ERROR) { + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + (time_t)-1, NULL, RESULT_FILE_OPEN_READ_ERROR, + "Error: Could not read host and service status information!")); + json_object_append_object(json_root, "data", json_help(status_json_help)); + json_object_print(json_root, 0, 1, cgi_data.strftime_format, + cgi_data.format_options); + document_footer(); + return ERROR; + } + + /* validate arguments in URL */ + result = validate_arguments(json_root, &cgi_data, query_time); + if(result != RESULT_SUCCESS) { + json_object_append_object(json_root, "data", json_help(status_json_help)); + json_object_print(json_root, 0, 1, cgi_data.strftime_format, + cgi_data.format_options); + document_footer(); + return ERROR; + } + + /* get authentication information */ + get_authentication_information(¤t_authdata); + + /* For most locales, floats get output with a comma instead of a + * decimal point, which messes up the JSON data structure. */ + setlocale(LC_NUMERIC, "C"); + + /* Return something to the user */ + switch( cgi_data.query) { + case STATUS_QUERY_HOSTCOUNT: + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + last_status_data_update, ¤t_authdata, + RESULT_SUCCESS, "")); + json_object_append_object(json_root, "data", + json_status_hostcount(cgi_data.format_options, + cgi_data.use_parent_host, cgi_data.parent_host, + cgi_data.use_child_host, cgi_data.child_host, + cgi_data.hostgroup, cgi_data.host_statuses, cgi_data.contact, + cgi_data.host_time_field, cgi_data.start_time, + cgi_data.end_time, cgi_data.contactgroup, + cgi_data.check_timeperiod, + cgi_data.host_notification_timeperiod, cgi_data.check_command, + cgi_data.event_handler)); + break; + case STATUS_QUERY_HOSTLIST: + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + last_status_data_update, ¤t_authdata, + RESULT_SUCCESS, "")); + json_object_append_object(json_root, "data", + json_status_hostlist(cgi_data.format_options, cgi_data.start, + cgi_data.count, cgi_data.details, cgi_data.use_parent_host, + cgi_data.parent_host, cgi_data.use_child_host, + cgi_data.child_host, cgi_data.hostgroup, cgi_data.host_statuses, + cgi_data.contact, cgi_data.host_time_field, cgi_data.start_time, + cgi_data.end_time, cgi_data.contactgroup, + cgi_data.check_timeperiod, + cgi_data.host_notification_timeperiod, cgi_data.check_command, + cgi_data.event_handler)); + break; + case STATUS_QUERY_HOST: + temp_hoststatus = find_hoststatus(cgi_data.host_name); + if( NULL == temp_hoststatus) { + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + (time_t)-1, ¤t_authdata, RESULT_OPTION_VALUE_INVALID, + "The status for host '%s' could not be found.", + cgi_data.host_name)); + result = ERROR; + } + else { + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + last_status_data_update, ¤t_authdata, + RESULT_SUCCESS, "")); + json_object_append_object(json_root, "data", + json_status_host(cgi_data.format_options, cgi_data.host, + temp_hoststatus)); + } + break; + case STATUS_QUERY_SERVICECOUNT: + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + last_status_data_update, ¤t_authdata, + RESULT_SUCCESS, "")); + json_object_append_object(json_root, "data", + json_status_servicecount(cgi_data.format_options, cgi_data.host, + cgi_data.use_parent_host, cgi_data.parent_host, + cgi_data.use_child_host, cgi_data.child_host, + cgi_data.hostgroup, cgi_data.servicegroup, + cgi_data.host_statuses, cgi_data.service_statuses, + cgi_data.contact, cgi_data.service_time_field, + cgi_data.start_time, cgi_data.end_time, + cgi_data.service_description, cgi_data.parent_service_name, + cgi_data.child_service_name, cgi_data.contactgroup, + cgi_data.check_timeperiod, + cgi_data.service_notification_timeperiod, + cgi_data.check_command, cgi_data.event_handler)); + break; + case STATUS_QUERY_SERVICELIST: + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + last_status_data_update, ¤t_authdata, + RESULT_SUCCESS, "")); + json_object_append_object(json_root, "data", + json_status_servicelist(cgi_data.format_options, cgi_data.start, + cgi_data.count, cgi_data.details, cgi_data.host, + cgi_data.use_parent_host, cgi_data.parent_host, + cgi_data.use_child_host, cgi_data.child_host, + cgi_data.hostgroup, cgi_data.servicegroup, + cgi_data.host_statuses, cgi_data.service_statuses, + cgi_data.contact, cgi_data.service_time_field, + cgi_data.start_time, cgi_data.end_time, + cgi_data.service_description, cgi_data.parent_service_name, + cgi_data.child_service_name, cgi_data.contactgroup, + cgi_data.check_timeperiod, + cgi_data.service_notification_timeperiod, + cgi_data.check_command, cgi_data.event_handler)); + break; + case STATUS_QUERY_SERVICE: + temp_servicestatus = find_servicestatus(cgi_data.host_name, + cgi_data.service_description); + if( NULL == temp_servicestatus) { + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + (time_t)-1, ¤t_authdata, RESULT_OPTION_VALUE_INVALID, + "The status for service '%s' on host '%s' could not be found.", + cgi_data.service_description, cgi_data.host_name)); + result = ERROR; + } + else { + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + last_status_data_update, ¤t_authdata, + RESULT_SUCCESS, "")); + json_object_append_object(json_root, "data", + json_status_service(cgi_data.format_options, + cgi_data.service, temp_servicestatus)); + } + break; +#if 0 + case STATUS_QUERY_CONTACTCOUNT: + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + last_status_data_update, ¤t_authdata, + RESULT_SUCCESS, "")); + json_status_contactcount(1, cgi_data.format_options, cgi_data.start, + cgi_data.count, cgi_data.details, cgi_data.contactgroup); + break; + case STATUS_QUERY_CONTACTLIST: + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + last_status_data_update, ¤t_authdata, + RESULT_SUCCESS, "")); + json_status_contactlist(1, cgi_data.format_options, cgi_data.start, + cgi_data.count, cgi_data.details, cgi_data.contactgroup); + break; + case STATUS_QUERY_CONTACT: + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + last_status_data_update, ¤t_authdata, + RESULT_SUCCESS, "")); + json_status_contact(1, cgi_data.format_options, cgi_data.contact); + break; +#endif + case STATUS_QUERY_COMMENTCOUNT: + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + last_status_data_update, ¤t_authdata, + RESULT_SUCCESS, "")); + json_object_append_object(json_root, "data", + json_status_commentcount(cgi_data.format_options, + cgi_data.comment_time_field, cgi_data.start_time, + cgi_data.end_time, cgi_data.comment_types, + cgi_data.entry_types, cgi_data.persistence, + cgi_data.expiring, cgi_data.host_name, + cgi_data.service_description)); + break; + case STATUS_QUERY_COMMENTLIST: + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + last_status_data_update, ¤t_authdata, + RESULT_SUCCESS, "")); + json_object_append_object(json_root, "data", + json_status_commentlist(cgi_data.format_options, cgi_data.start, + cgi_data.count, cgi_data.details, cgi_data.comment_time_field, + cgi_data.start_time, cgi_data.end_time, + cgi_data.comment_types, cgi_data.entry_types, + cgi_data.persistence, cgi_data.expiring, cgi_data.host_name, + cgi_data.service_description)); + break; + case STATUS_QUERY_COMMENT: + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + last_status_data_update, ¤t_authdata, + RESULT_SUCCESS, "")); + json_object_append_object(json_root, "data", + json_status_comment(cgi_data.format_options, cgi_data.comment)); + break; + case STATUS_QUERY_DOWNTIMECOUNT: + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + last_status_data_update, ¤t_authdata, + RESULT_SUCCESS, "")); + json_object_append_object(json_root, "data", + json_status_downtimecount(cgi_data.format_options, + cgi_data.downtime_time_field, cgi_data.start_time, + cgi_data.end_time, cgi_data.downtime_object_types, + cgi_data.downtime_types, cgi_data.triggered, + cgi_data.triggered_by, cgi_data.in_effect, cgi_data.host_name, + cgi_data.service_description)); + break; + case STATUS_QUERY_DOWNTIMELIST: + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + last_status_data_update, ¤t_authdata, + RESULT_SUCCESS, "")); + json_object_append_object(json_root, "data", + json_status_downtimelist(cgi_data.format_options, + cgi_data.start, cgi_data.count, cgi_data.details, + cgi_data.downtime_time_field, cgi_data.start_time, + cgi_data.end_time, cgi_data.downtime_object_types, + cgi_data.downtime_types, cgi_data.triggered, + cgi_data.triggered_by, cgi_data.in_effect, cgi_data.host_name, + cgi_data.service_description)); + break; + case STATUS_QUERY_DOWNTIME: + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + last_status_data_update, ¤t_authdata, + RESULT_SUCCESS, "")); + json_object_append_object(json_root, "data", + json_status_downtime(cgi_data.format_options, cgi_data.downtime)); + break; + case STATUS_QUERY_PROGRAMSTATUS: + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + last_status_data_update, ¤t_authdata, + RESULT_SUCCESS, "")); + json_object_append_object(json_root, "data", + json_status_program(cgi_data.format_options)); + break; + case STATUS_QUERY_PERFORMANCEDATA: + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + last_status_data_update, ¤t_authdata, + RESULT_SUCCESS, "")); + json_object_append_object(json_root, "data", json_status_performance()); + break; + case STATUS_QUERY_HELP: + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + compile_time(__DATE__, __TIME__), ¤t_authdata, + RESULT_SUCCESS, "")); + json_object_append_object(json_root, "data", json_help(status_json_help)); + break; + default: + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data.query, valid_queries), + get_query_status(query_status, cgi_data.query), + (time_t)-1, ¤t_authdata, RESULT_OPTION_MISSING, + "Error: Object Type not specified. See data for help.")); + json_object_append_object(json_root, "data", json_help(status_json_help)); + break; + } + + json_object_print(json_root, 0, 1, cgi_data.strftime_format, + cgi_data.format_options); + document_footer(); + + /* free all allocated memory */ + free_cgi_data( &cgi_data); + json_free_object(json_root, 1); + free_memory(); + + return OK; + } + +void document_header(int whitespace) { + char date_time[MAX_DATETIME_LENGTH]; + time_t expire_time; + time_t current_time; + + time(¤t_time); + + printf("Cache-Control: no-store\r\n"); + printf("Pragma: no-cache\r\n"); + + get_time_string(¤t_time, date_time, (int)sizeof(date_time), HTTP_DATE_TIME); + printf("Last-Modified: %s\r\n", date_time); + + expire_time = (time_t)0L; + get_time_string(&expire_time, date_time, (int)sizeof(date_time), HTTP_DATE_TIME); + printf("Expires: %s\r\n", date_time); + + printf("Content-type: application/json; charset=utf-8\r\n\r\n"); + + return; + } + + +void document_footer(void) { + + printf( "\n"); + + return; + } + + +void init_cgi_data(status_json_cgi_data *cgi_data) { + cgi_data->format_options = 0; + cgi_data->query = STATUS_QUERY_INVALID; + cgi_data->start = 0; + cgi_data->count = 0; + cgi_data->details = 0; + cgi_data->strftime_format = NULL; + cgi_data->parent_host_name = NULL; + cgi_data->use_parent_host = 0; + cgi_data->parent_host = NULL; + cgi_data->child_host_name = NULL; + cgi_data->use_child_host = 0; + cgi_data->child_host = NULL; + cgi_data->host_name = NULL; + cgi_data->host = NULL; + cgi_data->host_statuses = HOST_STATUS_ALL; + cgi_data->hostgroup_name = NULL; + cgi_data->hostgroup = NULL; + cgi_data->servicegroup_name = NULL; + cgi_data->servicegroup = NULL; + cgi_data->service_description = NULL; + cgi_data->service = NULL; + cgi_data->service_statuses = SERVICE_STATUS_ALL; + cgi_data->parent_service_name = NULL; + cgi_data->child_service_name = NULL; + cgi_data->contactgroup_name = NULL; + cgi_data->contactgroup = NULL; + cgi_data->contact_name = NULL; + cgi_data->contact = NULL; + cgi_data->check_timeperiod_name = NULL; + cgi_data->check_timeperiod = NULL; + cgi_data->host_notification_timeperiod_name = NULL; + cgi_data->host_notification_timeperiod = NULL; + cgi_data->service_notification_timeperiod_name = NULL; + cgi_data->service_notification_timeperiod = NULL; + cgi_data->check_command_name = NULL; + cgi_data->check_command = NULL; + cgi_data->event_handler_name = NULL; + cgi_data->event_handler = NULL; + cgi_data->comment_types = COMMENT_TYPE_ALL; + cgi_data->entry_types = COMMENT_ENTRY_ALL; + cgi_data->persistence = BOOLEAN_EITHER; + cgi_data->expiring = BOOLEAN_EITHER; + cgi_data->comment_id = -1; + cgi_data->comment = NULL; + cgi_data->downtime_id = -1; + cgi_data->downtime = NULL; + cgi_data->start_time = (time_t)0; + cgi_data->end_time = (time_t)0; + cgi_data->host_time_field = STATUS_TIME_INVALID; + cgi_data->service_time_field = STATUS_TIME_INVALID; + cgi_data->comment_time_field = STATUS_TIME_INVALID; + cgi_data->downtime_time_field = STATUS_TIME_INVALID; + cgi_data->downtime_object_types = DOWNTIME_OBJECT_TYPE_ALL; + cgi_data->downtime_types = DOWNTIME_TYPE_ALL; + cgi_data->triggered = BOOLEAN_EITHER; + cgi_data->triggered_by = -1; + cgi_data->in_effect = BOOLEAN_EITHER; +} + +void free_cgi_data( status_json_cgi_data *cgi_data) { + if( NULL != cgi_data->parent_host_name) free( cgi_data->parent_host_name); + if( NULL != cgi_data->child_host_name) free( cgi_data->child_host_name); + if( NULL != cgi_data->host_name) free( cgi_data->host_name); + if( NULL != cgi_data->hostgroup_name) free( cgi_data->hostgroup_name); + if( NULL != cgi_data->servicegroup_name) free(cgi_data->servicegroup_name); + if( NULL != cgi_data->service_description) free(cgi_data->service_description); + if( NULL != cgi_data->parent_service_name) free(cgi_data->parent_service_name); + if( NULL != cgi_data->child_service_name) free(cgi_data->child_service_name); + if( NULL != cgi_data->contactgroup_name) free(cgi_data->contactgroup_name); + if( NULL != cgi_data->contact_name) free(cgi_data->contact_name); + if( NULL != cgi_data->check_timeperiod_name) free(cgi_data->check_timeperiod_name); + if( NULL != cgi_data->host_notification_timeperiod_name) free(cgi_data->host_notification_timeperiod_name); + if( NULL != cgi_data->service_notification_timeperiod_name) free(cgi_data->service_notification_timeperiod_name); + if( NULL != cgi_data->check_command_name) free(cgi_data->check_command_name); + if( NULL != cgi_data->event_handler_name) free(cgi_data->event_handler_name); + } + + +int process_cgivars(json_object *json_root, status_json_cgi_data *cgi_data, + time_t query_time) { + char **variables; + int result = RESULT_SUCCESS; + int x; + authdata *authinfo = NULL; /* Currently always NULL because + get_authentication_information() hasn't + been called yet, but in case we want to + use it in the future... */ + + variables = getcgivars(); + + for(x = 0; variables[x] != NULL; x++) { + /* We set these each iteration because they could change with each + iteration */ + + /* we found the query argument */ + if(!strcmp(variables[x], "query")) { + if((result = parse_enumeration_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], valid_queries, &(cgi_data->query))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "formatoptions")) { + cgi_data->format_options = 0; + if((result = parse_bitmask_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], svm_format_options, + &(cgi_data->format_options))) != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "start")) { + if((result = parse_int_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->start))) != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "count")) { + if((result = parse_int_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->count))) != RESULT_SUCCESS) { + break; + } + + if(cgi_data->count == 0) { + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, + valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, RESULT_OPTION_VALUE_INVALID, + "The count option value is invalid. " + "It must be an integer greater than zero")); + result = RESULT_OPTION_VALUE_INVALID; + break; + } + x++; + } + + else if(!strcmp(variables[x], "parenthost")) { + if((result = parse_string_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->parent_host_name))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "childhost")) { + if((result = parse_string_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->child_host_name))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "hostname")) { + if((result = parse_string_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->host_name))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "hostgroup")) { + if((result = parse_string_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->hostgroup_name))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "hoststatus")) { + cgi_data->host_statuses = 0; + if((result = parse_bitmask_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], svm_host_statuses, + &(cgi_data->host_statuses))) != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "servicegroup")) { + if((result = parse_string_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->servicegroup_name))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "servicestatus")) { + cgi_data->service_statuses = 0; + if((result = parse_bitmask_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], svm_service_statuses, + &(cgi_data->service_statuses))) != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "parentservice")) { + if((result = parse_string_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->parent_service_name))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "childservice")) { + if((result = parse_string_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->child_service_name))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "checktimeperiod")) { + if((result = parse_string_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->check_timeperiod_name))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "hostnotificationtimeperiod")) { + if((result = parse_string_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], + &(cgi_data->host_notification_timeperiod_name))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "servicenotificationtimeperiod")) { + if((result = parse_string_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], + &(cgi_data->service_notification_timeperiod_name))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "checkcommand")) { + if((result = parse_string_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->check_command_name))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "eventhandler")) { + if((result = parse_string_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->event_handler_name))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "commenttypes")) { + cgi_data->comment_types = 0; + if((result = parse_bitmask_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], svm_valid_comment_types, + &(cgi_data->comment_types))) != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "entrytypes")) { + cgi_data->entry_types = 0; + if((result = parse_bitmask_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], svm_valid_comment_entry_types, + &(cgi_data->entry_types))) != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "persistence")) { + cgi_data->persistence = 0; + if((result = parse_bitmask_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], svm_valid_persistence, + &(cgi_data->persistence))) != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "expiring")) { + cgi_data->expiring = 0; + if((result = parse_bitmask_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], svm_valid_expiration, + &(cgi_data->expiring))) != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "commentid")) { + if((result = parse_int_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->comment_id))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "downtimeid")) { + if((result = parse_int_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->downtime_id))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "downtimeobjecttypes")) { + cgi_data->downtime_object_types = 0; + if((result = parse_bitmask_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], svm_valid_downtime_object_types, + &(cgi_data->downtime_object_types))) != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "downtimetypes")) { + cgi_data->downtime_types = 0; + if((result = parse_bitmask_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], svm_valid_downtime_types, + &(cgi_data->downtime_types))) != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "triggered")) { + cgi_data->triggered = 0; + if((result = parse_bitmask_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], svm_valid_triggered_status, + &(cgi_data->triggered))) != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "triggeredby")) { + if((result = parse_int_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->triggered_by))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "ineffect")) { + cgi_data->in_effect = 0; + if((result = parse_bitmask_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], svm_valid_in_effect_status, + &(cgi_data->in_effect))) != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "contactgroup")) { + if((result = parse_string_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->contactgroup_name))) + != RESULT_SUCCESS) { + result = ERROR; + break; + } + x++; + } + + else if(!strcmp(variables[x], "servicedescription")) { + if((result = parse_string_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->service_description))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "contactname")) { + if((result = parse_string_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->contact_name))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "details")) { + if((result = parse_boolean_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->details))) != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "dateformat")) { + if((result = parse_string_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->strftime_format))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "hosttimefield")) { + if((result = parse_enumeration_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], svm_host_time_fields, + &(cgi_data->host_time_field))) != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "servicetimefield")) { + if((result = parse_enumeration_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], svm_service_time_fields, + &(cgi_data->service_time_field))) != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "commenttimefield")) { + if((result = parse_enumeration_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], svm_comment_time_fields, + &(cgi_data->comment_time_field))) != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "downtimetimefield")) { + if((result = parse_enumeration_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], svm_downtime_time_fields, + &(cgi_data->downtime_time_field))) != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "starttime")) { + if((result = parse_time_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->start_time))) + != RESULT_SUCCESS) { + break; + } + x++; + } + + else if(!strcmp(variables[x], "endtime")) { + if((result = parse_time_cgivar(THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + json_root, query_time, authinfo, variables[x], + variables[x+1], &(cgi_data->end_time))) != RESULT_SUCCESS) { + result = ERROR; + break; + } + x++; + } + + else if(!strcmp(variables[x], "NagFormId")) + ++x; + + else if(!strcmp(variables[x], "")); + + else { + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, RESULT_OPTION_INVALID, + "Invalid option: '%s'.", variables[x])); + result = RESULT_OPTION_INVALID; + break; + } + } + + /* free memory allocated to the CGI variables */ + free_cgivars(variables); + + return result; + } + +int validate_arguments(json_object *json_root, status_json_cgi_data *cgi_data, + time_t query_time) { + int result = RESULT_SUCCESS; + host *temp_host = NULL; + hostgroup *temp_hostgroup = NULL; + servicegroup *temp_servicegroup = NULL; + service *temp_service = NULL; + contactgroup *temp_contactgroup = NULL; + timeperiod *temp_timeperiod = NULL; + command *temp_command = NULL; + contact *temp_contact = NULL; + nagios_comment *temp_comment = NULL; + scheduled_downtime *temp_downtime = NULL; + authdata *authinfo = NULL; /* Currently always NULL because + get_authentication_information() hasn't + been called yet, but in case we want to + use it in the future... */ + + /* Validate that required parameters were supplied */ + switch(cgi_data->query) { + case STATUS_QUERY_HOSTCOUNT: + break; + case STATUS_QUERY_HOSTLIST: + if(((cgi_data->start_time > 0) || (cgi_data->end_time > 0)) && + (STATUS_TIME_INVALID == cgi_data->host_time_field)) { + result = RESULT_OPTION_MISSING; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "Start and/or end time supplied, but time field specified.")); + } + break; + case STATUS_QUERY_HOST: + if( NULL == cgi_data->host_name) { + result = RESULT_OPTION_MISSING; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "Host information requested, but no host name specified.")); + } + break; + case STATUS_QUERY_SERVICECOUNT: + break; + case STATUS_QUERY_SERVICELIST: + if(((cgi_data->start_time > 0) || (cgi_data->end_time > 0)) && + (STATUS_TIME_INVALID == cgi_data->service_time_field)) { + result = RESULT_OPTION_MISSING; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "Start and/or end time supplied, but time field specified.")); + } + break; + case STATUS_QUERY_SERVICE: + if( NULL == cgi_data->host_name) { + result = RESULT_OPTION_MISSING; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "Service information requested, but no host name specified.")); + } + if( NULL == cgi_data->service_description) { + result = RESULT_OPTION_MISSING; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "Service information requested, but no service description specified.")); + } + break; + case STATUS_QUERY_COMMENTCOUNT: + break; + case STATUS_QUERY_COMMENTLIST: + if(((cgi_data->start_time > 0) || (cgi_data->end_time > 0)) && + (STATUS_TIME_INVALID == cgi_data->comment_time_field)) { + result = RESULT_OPTION_MISSING; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "Start and/or end time supplied, but time field specified.")); + } + break; + case STATUS_QUERY_COMMENT: + if( -1 == cgi_data->comment_id) { + result = RESULT_OPTION_MISSING; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "Comment information requested, but no id specified.")); + } + break; + case STATUS_QUERY_DOWNTIMECOUNT: + break; + case STATUS_QUERY_DOWNTIMELIST: + if(((cgi_data->start_time > 0) || (cgi_data->end_time > 0)) && + (STATUS_TIME_INVALID == cgi_data->downtime_time_field)) { + result = RESULT_OPTION_MISSING; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "Start and/or end time supplied, but time field specified.")); + } + break; + case STATUS_QUERY_DOWNTIME: + if( -1 == cgi_data->downtime_id) { + result = RESULT_OPTION_MISSING; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "Downtime information requested, but no id specified.")); + } + break; + case STATUS_QUERY_PROGRAMSTATUS: + break; + case STATUS_QUERY_PERFORMANCEDATA: + break; +#if 0 + case STATUS_QUERY_CONTACTCOUNT: + break; + case STATUS_QUERY_CONTACTLIST: + break; + case STATUS_QUERY_CONTACT: + if( NULL == cgi_data->contact_name) { + result = RESULT_OPTION_MISSING; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "Contact information requested, but no contact name specified.")); + } + break; +#endif + case STATUS_QUERY_HELP: + break; + default: + result = RESULT_OPTION_MISSING; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, "Missing validation for object type %u.", + cgi_data->query)); + break; + } + + /* Validate the requested parent host */ + if( NULL != cgi_data->parent_host_name) { + cgi_data->use_parent_host = 1; + cgi_data->parent_host = NULL; + if(strcmp(cgi_data->parent_host_name, "none")) { + temp_host = find_host(cgi_data->parent_host_name); + if( NULL == temp_host) { + cgi_data->use_parent_host = 0; + result = RESULT_OPTION_VALUE_INVALID; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, + valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "The parenthost '%s' could not be found.", + cgi_data->parent_host_name)); + } + else { + cgi_data->parent_host = temp_host; + } + } + } + + /* Validate the requested child host */ + if( NULL != cgi_data->child_host_name) { + cgi_data->use_child_host = 1; + cgi_data->child_host = NULL; + if(strcmp(cgi_data->child_host_name, "none")) { + temp_host = find_host(cgi_data->child_host_name); + if( NULL == temp_host) { + cgi_data->use_child_host = 0; + result = RESULT_OPTION_VALUE_INVALID; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, + valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "The childhost '%s' could not be found.", + cgi_data->child_host_name)); + } + else { + cgi_data->child_host = temp_host; + } + } + } + + /* Validate the requested host */ + if( NULL != cgi_data->host_name) { + temp_host = find_host(cgi_data->host_name); + if( NULL == temp_host) { + result = RESULT_OPTION_VALUE_INVALID; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "The host '%s' could not be found.", cgi_data->host_name)); + } + else { + cgi_data->host = temp_host; + } + } + + /* Validate the requested hostgroup */ + if( NULL != cgi_data->hostgroup_name) { + temp_hostgroup = find_hostgroup(cgi_data->hostgroup_name); + if( NULL == temp_hostgroup) { + result = RESULT_OPTION_VALUE_INVALID; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "The hostgroup '%s' could not be found.", + cgi_data->hostgroup_name)); + } + else { + cgi_data->hostgroup = temp_hostgroup; + } + } + + /* Validate the requested servicegroup */ + if( NULL != cgi_data->servicegroup_name) { + temp_servicegroup = find_servicegroup(cgi_data->servicegroup_name); + if( NULL == temp_servicegroup) { + result = RESULT_OPTION_VALUE_INVALID; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "The servicegroup '%s' could not be found.", + cgi_data->servicegroup_name)); + } + else { + cgi_data->servicegroup = temp_servicegroup; + } + } + + /* Validate the requested contactgroup */ + if( NULL != cgi_data->contactgroup_name) { + temp_contactgroup = find_contactgroup(cgi_data->contactgroup_name); + if( NULL == temp_contactgroup) { + result = RESULT_OPTION_VALUE_INVALID; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "The contactgroup '%s' could not be found.", + cgi_data->contactgroup_name)); + } + else { + cgi_data->contactgroup = temp_contactgroup; + } + } + + /* Validate the requested service. Because a service description may be + requested without specifying a host name, it may not make sense + to look for a specific service object */ + if((NULL != cgi_data->service_description) && + (NULL != cgi_data->host_name)) { + temp_service = find_service(cgi_data->host_name, + cgi_data->service_description); + if( NULL == temp_service) { + result = RESULT_OPTION_VALUE_INVALID; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "The service '%s' on host '%s' could not be found.", + cgi_data->service_description, cgi_data->host_name)); + } + else { + cgi_data->service = temp_service; + } + } + + /* Validate the requested check timeperiod */ + if( NULL != cgi_data->check_timeperiod_name) { + temp_timeperiod = find_timeperiod(cgi_data->check_timeperiod_name); + if( NULL == temp_timeperiod) { + result = RESULT_OPTION_VALUE_INVALID; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "The check timeperiod '%s' could not be found.", + cgi_data->check_timeperiod_name)); + } + else { + cgi_data->check_timeperiod = temp_timeperiod; + } + } + + /* Validate the requested host notification timeperiod */ + if( NULL != cgi_data->host_notification_timeperiod_name) { + temp_timeperiod = + find_timeperiod(cgi_data->host_notification_timeperiod_name); + if( NULL == temp_timeperiod) { + result = RESULT_OPTION_VALUE_INVALID; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "The host notification timeperiod '%s' could not be found.", + cgi_data->host_notification_timeperiod_name)); + } + else { + cgi_data->host_notification_timeperiod = temp_timeperiod; + } + } + + /* Validate the requested service notification timeperiod */ + if( NULL != cgi_data->service_notification_timeperiod_name) { + temp_timeperiod = + find_timeperiod(cgi_data->service_notification_timeperiod_name); + if( NULL == temp_timeperiod) { + result = RESULT_OPTION_VALUE_INVALID; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "The service notification timeperiod '%s' could not be found.", + cgi_data->service_notification_timeperiod_name)); + } + else { + cgi_data->service_notification_timeperiod = temp_timeperiod; + } + } + + /* Validate the requested check command */ + if( NULL != cgi_data->check_command_name) { + temp_command = find_command(cgi_data->check_command_name); + if( NULL == temp_command) { + result = RESULT_OPTION_VALUE_INVALID; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "The check command '%s' could not be found.", + cgi_data->check_command_name)); + } + else { + cgi_data->check_command = temp_command; + } + } + + /* Validate the requested event_handler */ + if( NULL != cgi_data->event_handler_name) { + temp_command = find_command(cgi_data->event_handler_name); + if( NULL == temp_command) { + result = RESULT_OPTION_VALUE_INVALID; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "The event_handler '%s' could not be found.", + cgi_data->event_handler_name)); + } + else { + cgi_data->event_handler = temp_command; + } + } + + /* Validate the requested comment */ + if(-1 != cgi_data->comment_id) { + temp_comment = find_host_comment(cgi_data->comment_id); + if(NULL == temp_comment) { + temp_comment = find_service_comment(cgi_data->comment_id); + } + if(NULL == temp_comment) { + result = RESULT_OPTION_VALUE_INVALID; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "The comment with ID '%d' could not be found.", + cgi_data->comment_id)); + } + else { + cgi_data->comment = temp_comment; + } + } + + /* Validate the requested downtime */ + if(-1 != cgi_data->downtime_id) { + temp_downtime = find_downtime(ANY_DOWNTIME, cgi_data->downtime_id); + if(NULL == temp_downtime) { + result = RESULT_OPTION_VALUE_INVALID; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "The downtime with ID '%d' could not be found.", + cgi_data->downtime_id)); + } + else { + cgi_data->downtime = temp_downtime; + } + } + + /* Validate the requested triggered-by downtime */ + if(-1 != cgi_data->triggered_by) { + temp_downtime = find_downtime(ANY_DOWNTIME, cgi_data->triggered_by); + if(NULL == temp_downtime) { + result = RESULT_OPTION_VALUE_INVALID; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "The triggering downtime with ID '%d' could not be found.", + cgi_data->triggered_by)); + } + } + + /* Validate the requested contact */ + if( NULL != cgi_data->contact_name) { + temp_contact = find_contact(cgi_data->contact_name); + if( NULL == temp_contact) { + result = RESULT_OPTION_VALUE_INVALID; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, "The contact '%s' could not be found.", + cgi_data->contact_name)); + } + else { + cgi_data->contact = temp_contact; + } + } + + /* Validate the requested start time is before the requested end time */ + if((cgi_data->start_time > 0) && (cgi_data->end_time > 0) && ( + cgi_data->start_time >= cgi_data->end_time)) { + result = RESULT_OPTION_VALUE_INVALID; + json_object_append_object(json_root, "result", + json_result(query_time, THISCGI, + svm_get_string_from_value(cgi_data->query, valid_queries), + get_query_status(query_status, cgi_data->query), + (time_t)-1, authinfo, result, + "The requested start time must be before the end time.")); + } + + return result; + } + +int json_status_host_passes_selection(host *temp_host, int use_parent_host, + host *parent_host, int use_child_host, host *child_host, + hostgroup *temp_hostgroup, contact *temp_contact, + hoststatus *temp_hoststatus, int time_field, time_t start_time, + time_t end_time, contactgroup *temp_contactgroup, + timeperiod *check_timeperiod, timeperiod *notification_timeperiod, + command *check_command, command *event_handler) { + + host *temp_host2; + + /* Skip if user is not authorized for this host */ + if(FALSE == is_authorized_for_host(temp_host, ¤t_authdata)) { + return 0; + } + + /* If the host parent was specified, skip the hosts whose parent is + not the parent host specified */ + if( 1 == use_parent_host && + FALSE == is_host_immediate_child_of_host(parent_host, temp_host)) { + return 0; + } + + /* If the hostgroup was specified, skip the hosts that are not members + of the hostgroup specified */ + if( NULL != temp_hostgroup && + ( FALSE == is_host_member_of_hostgroup(temp_hostgroup, + temp_host))) { + return 0; + } + + /* If the contact was specified, skip the hosts that do not have + the contact specified */ + if( NULL != temp_contact && + ( FALSE == is_contact_for_host(temp_host, temp_contact))) { + return 0; + } + + /* If a contactgroup was specified, skip the hosts that do not have + the contactgroup specified */ + if(NULL != temp_contactgroup && + (FALSE == is_contactgroup_for_host(temp_host, temp_contactgroup))) { + return 0; + } + + switch(time_field) { + case STATUS_TIME_INVALID: + break; + case STATUS_TIME_LAST_UPDATE: + if((start_time > 0) && (temp_hoststatus->last_update < start_time)) { + return 0; + } + if((end_time > 0) && (temp_hoststatus->last_update > end_time)) { + return 0; + } + break; + case STATUS_TIME_LAST_CHECK: + if((start_time > 0) && (temp_hoststatus->last_check < start_time)) { + return 0; + } + if((end_time > 0) && (temp_hoststatus->last_check > end_time)) { + return 0; + } + break; + case STATUS_TIME_NEXT_CHECK: + if((start_time > 0) && (temp_hoststatus->next_check < start_time)) { + return 0; + } + if((end_time > 0) && (temp_hoststatus->next_check > end_time)) { + return 0; + } + break; + case STATUS_TIME_LAST_STATE_CHANGE: + if((start_time > 0) && (temp_hoststatus->last_state_change < + start_time)) { + return 0; + } + if((end_time > 0) && (temp_hoststatus->last_state_change > end_time)) { + return 0; + } + break; + case STATUS_TIME_LAST_HARD_STATE_CHANGE: + if((start_time > 0) && (temp_hoststatus->last_hard_state_change < + start_time)) { + return 0; + } + if((end_time > 0) && (temp_hoststatus->last_hard_state_change > + end_time)) { + return 0; + } + break; + case STATUS_TIME_LAST_TIME_UP: + if((start_time > 0) && (temp_hoststatus->last_time_up < start_time)) { + return 0; + } + if((end_time > 0) && (temp_hoststatus->last_time_up > end_time)) { + return 0; + } + break; + case STATUS_TIME_LAST_TIME_DOWN: + if((start_time > 0) && (temp_hoststatus->last_time_down < start_time)) { + return 0; + } + if((end_time > 0) && (temp_hoststatus->last_time_down > end_time)) { + return 0; + } + break; + case STATUS_TIME_LAST_TIME_UNREACHABLE: + if((start_time > 0) && (temp_hoststatus->last_time_unreachable < + start_time)) { + return 0; + } + if((end_time > 0) && (temp_hoststatus->last_time_unreachable > + end_time)) { + return 0; + } + break; + case STATUS_TIME_LAST_NOTIFICATION: + if((start_time > 0) && (temp_hoststatus->last_notification < + start_time)) { + return 0; + } + if((end_time > 0) && (temp_hoststatus->last_notification > end_time)) { + return 0; + } + break; + case STATUS_TIME_NEXT_NOTIFICATION: + if((start_time > 0) && (temp_hoststatus->next_notification < + start_time)) { + return 0; + } + if((end_time > 0) && (temp_hoststatus->next_notification > end_time)) { + return 0; + } + break; + default: + return 0; + } + + /* If a check timeperiod was specified, skip this host if it does not have + the check timeperiod specified */ + if(NULL != check_timeperiod && + (check_timeperiod != temp_host->check_period_ptr)) { + return 0; + } + + /* If a notification timeperiod was specified, skip this host if it + does not have the notification timeperiod specified */ + if(NULL != notification_timeperiod && + (notification_timeperiod != temp_host->notification_period_ptr)) { + return 0; + } + + /* If a check command was specified, skip this host if it does not + have the check command specified */ + if(NULL != check_command && + (check_command != temp_host->check_command_ptr)) { + return 0; + } + + /* If an event handler was specified, skip this host if it does not + have the event handler specified */ + if(NULL != event_handler && + (event_handler != temp_host->event_handler_ptr)) { + return 0; + } + + /* If a child host was specified... (leave this for last since it is the + most expensive check) */ + if(1 == use_child_host) { + /* If the child host is "none", skip this host if it has children */ + if(NULL == child_host) { + for(temp_host2 = host_list; temp_host2 != NULL; + temp_host2 = temp_host2->next) { + if(TRUE == is_host_immediate_child_of_host(temp_host, + temp_host2)) { + return 0; + } + } + } + /* Otherwise, skip this host if it does not have the specified host + as a child */ + else if(FALSE == is_host_immediate_child_of_host(temp_host, child_host)) { + return 0; + } + } + + return 1; + + } + +json_object *json_status_host_selectors(unsigned format_options, int start, + int count, int use_parent_host, host *parent_host, int use_child_host, + host *child_host, hostgroup *temp_hostgroup, int host_statuses, + contact *temp_contact, int time_field, time_t start_time, + time_t end_time, contactgroup *temp_contactgroup, + timeperiod *check_timeperiod, timeperiod *notification_timeperiod, + command *check_command, command *event_handler) { + + json_object *json_selectors; + + json_selectors = json_new_object(); + + if(start > 0) { + json_object_append_integer(json_selectors, "start", start); + } + if(count > 0) { + json_object_append_integer(json_selectors, "count", count); + } + if(1 == use_parent_host) { + json_object_append_string(json_selectors, "parenthost", + &percent_escapes, + ( NULL == parent_host ? "none" : parent_host->name)); + } + if(1 == use_child_host) { + json_object_append_string(json_selectors, "childhost", &percent_escapes, + ( NULL == child_host ? "none" : child_host->name)); + } + if(NULL != temp_hostgroup) { + json_object_append_string(json_selectors, "hostgroup", &percent_escapes, + temp_hostgroup->group_name); + } + if(HOST_STATUS_ALL != host_statuses) { + json_bitmask(json_selectors, format_options, "hoststatus", + host_statuses, svm_host_statuses); + } + if(NULL != temp_contact) { + json_object_append_string(json_selectors, "contact",&percent_escapes, + temp_contact->name); + } + if(NULL != temp_contactgroup) { + json_object_append_string(json_selectors, "contactgroup", + &percent_escapes, temp_contactgroup->group_name); + } + if(time_field > 0) { + json_enumeration(json_selectors, format_options, "hosttimefield", + time_field, svm_host_time_fields); + } + if(start_time > 0) { + json_object_append_time_t(json_selectors, "starttime", start_time); + } + if(end_time > 0) { + json_object_append_time_t(json_selectors, "endtime", end_time); + } + if( NULL != check_timeperiod) { + json_object_append_string(json_selectors, "checktimeperiod", + &percent_escapes, check_timeperiod->name); + } + if( NULL != notification_timeperiod) { + json_object_append_string(json_selectors, "hostnotificationtimeperiod", + &percent_escapes, notification_timeperiod->name); + } + if( NULL != check_command) { + json_object_append_string(json_selectors, "checkcommand", + &percent_escapes, check_command->name); + } + if( NULL != event_handler) { + json_object_append_string(json_selectors, "eventhandler", + &percent_escapes, event_handler->name); + } + + return json_selectors; + } + +json_object *json_status_hostcount(unsigned format_options, int use_parent_host, + host *parent_host, int use_child_host, host *child_host, + hostgroup *temp_hostgroup, int host_statuses, contact *temp_contact, + int time_field, time_t start_time, time_t end_time, + contactgroup *temp_contactgroup, timeperiod *check_timeperiod, + timeperiod *notification_timeperiod, command *check_command, + command *event_handler) { + + json_object *json_data; + json_object *json_count; + host *temp_host; + hoststatus *temp_hoststatus; + int up = 0; + int down = 0; + int unreachable = 0; + int pending = 0; + + json_data = json_new_object(); + json_object_append_object(json_data, "selectors", + json_status_host_selectors(format_options, 0, 0, use_parent_host, + parent_host, use_child_host, child_host, temp_hostgroup, + host_statuses, temp_contact, time_field, start_time, end_time, + temp_contactgroup, check_timeperiod, notification_timeperiod, + check_command, event_handler)); + + json_count = json_new_object(); + + for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) { + + /* If we cannot get the status of the host, skip it. This should + probably return an error and doing so is in the todo list. */ + temp_hoststatus = find_hoststatus(temp_host->name); + if( NULL == temp_hoststatus) { + continue; + } + + if(json_status_host_passes_selection(temp_host, use_parent_host, + parent_host, use_child_host, child_host, temp_hostgroup, + temp_contact, temp_hoststatus, time_field, start_time, + end_time, temp_contactgroup, check_timeperiod, + notification_timeperiod, check_command, event_handler) == 0) { + continue; + } + + /* Count the hosts in each state */ + switch(temp_hoststatus->status) { + case HOST_PENDING: + pending++; + break; +#ifdef JSON_NAGIOS_4X + case SD_HOST_UP: +#else + case HOST_UP: +#endif + up++; + break; +#ifdef JSON_NAGIOS_4X + case SD_HOST_UNREACHABLE: +#else + case HOST_UNREACHABLE: +#endif + unreachable++; + break; +#ifdef JSON_NAGIOS_4X + case SD_HOST_DOWN: +#else + case HOST_DOWN: +#endif + down++; + break; + } + } + +#ifdef JSON_NAGIOS_4X + if( host_statuses & SD_HOST_UP) +#else + if( host_statuses & HOST_UP) +#endif + json_object_append_integer(json_count, "up", up); +#ifdef JSON_NAGIOS_4X + if( host_statuses & SD_HOST_DOWN) +#else + if( host_statuses & HOST_DOWN) +#endif + json_object_append_integer(json_count, "down", down); +#ifdef JSON_NAGIOS_4X + if( host_statuses & SD_HOST_UNREACHABLE) +#else + if( host_statuses & HOST_UNREACHABLE) +#endif + json_object_append_integer(json_count, "unreachable", unreachable); + if( host_statuses & HOST_PENDING) + json_object_append_integer(json_count, "pending", pending); + + json_object_append_object(json_data, "count", json_count); + + return json_data; + } + +json_object *json_status_hostlist(unsigned format_options, int start, int count, + int details, int use_parent_host, host *parent_host, int use_child_host, + host *child_host, hostgroup *temp_hostgroup, int host_statuses, + contact *temp_contact, int time_field, time_t start_time, + time_t end_time, contactgroup *temp_contactgroup, + timeperiod *check_timeperiod, timeperiod *notification_timeperiod, + command *check_command, command *event_handler) { + + json_object *json_data; + json_object *json_hostlist; + json_object *json_host_details; + host *temp_host; + hoststatus *temp_hoststatus; + int current = 0; + int counted = 0; + + json_data = json_new_object(); + json_object_append_object(json_data, "selectors", + json_status_host_selectors(format_options, start, count, + use_parent_host, parent_host, use_child_host, child_host, + temp_hostgroup, host_statuses, temp_contact, time_field, start_time, + end_time, temp_contactgroup, check_timeperiod, + notification_timeperiod, check_command, event_handler)); + + json_hostlist = json_new_object(); + + for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) { + + /* If we cannot get the status of the host, skip it. This should + probably return an error and doing so is in the todo list. */ + temp_hoststatus = find_hoststatus(temp_host->name); + if( NULL == temp_hoststatus) { + continue; + } + + if(json_status_host_passes_selection(temp_host, use_parent_host, + parent_host, use_child_host, child_host, temp_hostgroup, + temp_contact, temp_hoststatus, time_field, start_time, + end_time, temp_contactgroup, check_timeperiod, + notification_timeperiod, check_command, event_handler) == 0) { + continue; + } + + /* If the status of the host does not match one of the status the + user requested, skip the host */ + if(!(temp_hoststatus->status & host_statuses)) { + continue; + } + + /* If the current item passes the start and limit tests, display it */ + if( passes_start_and_count_limits(start, count, current, counted)) { + if( details > 0) { + json_host_details = json_new_object(); + json_status_host_details(json_host_details, format_options, + temp_host, temp_hoststatus); + json_object_append_object(json_hostlist, temp_host->name, + json_host_details); + } + else { + json_enumeration(json_hostlist, format_options, temp_host->name, + temp_hoststatus->status, svm_host_statuses); + } + counted++; + } + current++; + } + + json_object_append_object(json_data, "hostlist", json_hostlist); + + return json_data; + } + +json_object *json_status_host(unsigned format_options, host *temp_host, + hoststatus *temp_hoststatus) { + + json_object *json_host = json_new_object(); + json_object *json_details = json_new_object(); + + json_object_append_string(json_details, "name", &percent_escapes, + temp_host->name); + json_status_host_details(json_details, format_options, temp_host, + temp_hoststatus); + json_object_append_object(json_host, "host", json_details); + + return json_host; + } + +void json_status_host_details(json_object *json_details, unsigned format_options, + host *temp_host, hoststatus *temp_hoststatus) { + + json_object_append_string(json_details, "name", &percent_escapes, + temp_host->name); + json_object_append_string(json_details, "plugin_output", + &percent_escapes, temp_hoststatus->plugin_output); + json_object_append_string(json_details, "long_plugin_output", + &percent_escapes, temp_hoststatus->long_plugin_output); + json_object_append_string(json_details, "perf_data", + &percent_escapes, temp_hoststatus->perf_data); + json_enumeration(json_details, format_options, "status", + temp_hoststatus->status, svm_host_statuses); + json_object_append_time_t(json_details, "last_update", + temp_hoststatus->last_update); + json_object_append_boolean(json_details, "has_been_checked", + temp_hoststatus->has_been_checked); + json_object_append_boolean(json_details, "should_be_scheduled", + temp_hoststatus->should_be_scheduled); + json_object_append_integer(json_details, "current_attempt", + temp_hoststatus->current_attempt); + json_object_append_integer(json_details, "max_attempts", + temp_hoststatus->max_attempts); + json_object_append_time_t(json_details, "last_check", + temp_hoststatus->last_check); + json_object_append_time_t(json_details, "next_check", + temp_hoststatus->next_check); + json_bitmask(json_details, format_options, "check_options", + temp_hoststatus->check_options, svm_check_options); + json_enumeration(json_details, format_options, "check_type", + temp_hoststatus->check_type, svm_host_check_types); + json_object_append_time_t(json_details, "last_state_change", + temp_hoststatus->last_state_change); + json_object_append_time_t(json_details, "last_hard_state_change", + temp_hoststatus->last_hard_state_change); + json_enumeration(json_details, format_options, "last_hard_state", + temp_hoststatus->last_hard_state, svm_host_states); + json_object_append_time_t(json_details, "last_time_up", + temp_hoststatus->last_time_up); + json_object_append_time_t(json_details, "last_time_down", + temp_hoststatus->last_time_down); + json_object_append_time_t(json_details, "last_time_unreachable", + temp_hoststatus->last_time_unreachable); + json_enumeration(json_details, format_options, "state_type", + temp_hoststatus->state_type, svm_state_types); + json_object_append_time_t(json_details, "last_notification", + temp_hoststatus->last_notification); + json_object_append_time_t(json_details, "next_notification", + temp_hoststatus->next_notification); + json_object_append_boolean(json_details, "no_more_notifications", + temp_hoststatus->no_more_notifications); + json_object_append_boolean(json_details, "notifications_enabled", + temp_hoststatus->notifications_enabled); + json_object_append_boolean(json_details, "problem_has_been_acknowledged", + temp_hoststatus->problem_has_been_acknowledged); + json_enumeration(json_details, format_options, "acknowledgement_type", + temp_hoststatus->acknowledgement_type, svm_acknowledgement_types); + json_object_append_integer(json_details, "current_notification_number", + temp_hoststatus->current_notification_number); +#ifdef JSON_NAGIOS_4X + json_object_append_boolean(json_details, "accept_passive_checks", + temp_hoststatus->accept_passive_checks); +#else + json_object_append_boolean(json_details, "accept_passive_host_checks", + temp_hoststatus->accept_passive_host_checks); +#endif + json_object_append_boolean(json_details, "event_handler_enabled", + temp_hoststatus->event_handler_enabled); + json_object_append_boolean(json_details, "checks_enabled", + temp_hoststatus->checks_enabled); + json_object_append_boolean(json_details, "flap_detection_enabled", + temp_hoststatus->flap_detection_enabled); + json_object_append_boolean(json_details, "is_flapping", + temp_hoststatus->is_flapping); + json_object_append_real(json_details, "percent_state_change", + temp_hoststatus->percent_state_change); + json_object_append_real(json_details, "latency", temp_hoststatus->latency); + json_object_append_real(json_details, "execution_time", + temp_hoststatus->execution_time); + json_object_append_integer(json_details, "scheduled_downtime_depth", + temp_hoststatus->scheduled_downtime_depth); +#ifndef JSON_NAGIOS_4X + json_object_append_boolean(json_details, "failure_prediction_enabled", + temp_hoststatus->failure_prediction_enabled); +#endif + json_object_append_boolean(json_details, "process_performance_data", + temp_hoststatus->process_performance_data); +#ifdef JSON_NAGIOS_4X + json_object_append_boolean(json_details, "obsess", temp_hoststatus->obsess); +#else + json_object_append_boolean(json_details, "obsess_over_host", + temp_hoststatus->obsess_over_host); +#endif + } + +int json_status_service_passes_host_selection(host *temp_host, + int use_parent_host, host *parent_host, int use_child_host, + host *child_host, hostgroup *temp_hostgroup, host *match_host, + int host_statuses) { + + hoststatus *temp_hoststatus; + host *temp_host2; + + /* Skip if user is not authorized for this service */ + if(FALSE == is_authorized_for_host(temp_host, ¤t_authdata)) { + return 0; + } + + /* If the host parent was specified, skip the services whose host is + not a child of the parent host specified */ + if( 1 == use_parent_host && NULL != temp_host && + FALSE == is_host_immediate_child_of_host(parent_host, + temp_host)) { + return 0; + } + + /* If the hostgroup was specified, skip the services on hosts that + are not members of the hostgroup specified */ + if( NULL != temp_hostgroup && NULL != temp_host && + ( FALSE == is_host_member_of_hostgroup(temp_hostgroup, + temp_host))) { + return 0; + } + + /* If the host was specified, skip the services not on the host + specified */ + if( NULL != match_host && NULL != temp_host && + temp_host != match_host) { + return 0; + } + + /* If we cannot get the status of the host, skip it. This should + probably return an error and doing so is in the todo list. */ + temp_hoststatus = find_hoststatus(temp_host->name); + if( NULL == temp_hoststatus) { + return 0; + } + + /* If a child host was specified... */ + if(1 == use_child_host) { + /* If the child host is "none", skip this host if it has children */ + if(NULL == child_host) { + for(temp_host2 = host_list; temp_host2 != NULL; + temp_host2 = temp_host2->next) { + if(TRUE == is_host_immediate_child_of_host(temp_host, + temp_host2)) { + return 0; + } + } + } + /* Otherwise, skip this host if it does not have the specified host + as a child */ + else if(FALSE == is_host_immediate_child_of_host(temp_host, child_host)) { + return 0; + } + } + + return 1; + } + +int json_status_service_passes_service_selection(service *temp_service, + servicegroup *temp_servicegroup, contact *temp_contact, + servicestatus *temp_servicestatus, int time_field, time_t start_time, + time_t end_time, char *service_description, char *parent_service_name, + char *child_service_name, contactgroup *temp_contactgroup, + timeperiod *check_timeperiod, timeperiod *notification_timeperiod, + command *check_command, command *event_handler) { + + servicesmember *temp_servicesmember; + + /* Skip if user is not authorized for this service */ + if(FALSE == is_authorized_for_service(temp_service, + ¤t_authdata)) { + return 0; + } + + /* If the servicegroup was specified, skip the services that are not + members of the servicegroup specified */ + if( NULL != temp_servicegroup && + ( FALSE == is_service_member_of_servicegroup(temp_servicegroup, + temp_service))) { + return 0; + } + + /* If the contact was specified, skip the services that do not have + the contact specified */ + if( NULL != temp_contact && + ( FALSE == is_contact_for_service(temp_service, temp_contact))) { + return 0; + } + + /* If a contactgroup was specified, skip the services that do not have + the contactgroup specified */ + if(NULL != temp_contactgroup && + (FALSE == is_contactgroup_for_service(temp_service, + temp_contactgroup))) { + return 0; + } + + switch(time_field) { + case STATUS_TIME_INVALID: + break; + case STATUS_TIME_LAST_UPDATE: + if((start_time > 0) && (temp_servicestatus->last_update < start_time)) { + return 0; + } + if((end_time > 0) && (temp_servicestatus->last_update > end_time)) { + return 0; + } + break; + case STATUS_TIME_LAST_CHECK: + if((start_time > 0) && (temp_servicestatus->last_check < start_time)) { + return 0; + } + if((end_time > 0) && (temp_servicestatus->last_check > end_time)) { + return 0; + } + break; + case STATUS_TIME_NEXT_CHECK: + if((start_time > 0) && (temp_servicestatus->next_check < start_time)) { + return 0; + } + if((end_time > 0) && (temp_servicestatus->next_check > end_time)) { + return 0; + } + break; + case STATUS_TIME_LAST_STATE_CHANGE: + if((start_time > 0) && (temp_servicestatus->last_state_change < + start_time)) { + return 0; + } + if((end_time > 0) && (temp_servicestatus->last_state_change > end_time)) { + return 0; + } + break; + case STATUS_TIME_LAST_HARD_STATE_CHANGE: + if((start_time > 0) && (temp_servicestatus->last_hard_state_change < + start_time)) { + return 0; + } + if((end_time > 0) && (temp_servicestatus->last_hard_state_change > + end_time)) { + return 0; + } + break; + case STATUS_TIME_LAST_TIME_OK: + if((start_time > 0) && (temp_servicestatus->last_time_ok < start_time)) { + return 0; + } + if((end_time > 0) && (temp_servicestatus->last_time_ok > end_time)) { + return 0; + } + break; + case STATUS_TIME_LAST_TIME_WARNING: + if((start_time > 0) && (temp_servicestatus->last_time_warning < + start_time)) { + return 0; + } + if((end_time > 0) && (temp_servicestatus->last_time_warning > end_time)) { + return 0; + } + break; + case STATUS_TIME_LAST_TIME_CRITICAL: + if((start_time > 0) && (temp_servicestatus->last_time_critical < + start_time)) { + return 0; + } + if((end_time > 0) && (temp_servicestatus->last_time_critical > + end_time)) { + return 0; + } + break; + case STATUS_TIME_LAST_TIME_UNKNOWN: + if((start_time > 0) && (temp_servicestatus->last_time_unknown < + start_time)) { + return 0; + } + if((end_time > 0) && (temp_servicestatus->last_time_unknown > end_time)) { + return 0; + } + break; + case STATUS_TIME_LAST_NOTIFICATION: + if((start_time > 0) && (temp_servicestatus->last_notification < + start_time)) { + return 0; + } + if((end_time > 0) && (temp_servicestatus->last_notification > end_time)) { + return 0; + } + break; + case STATUS_TIME_NEXT_NOTIFICATION: + if((start_time > 0) && (temp_servicestatus->next_notification < + start_time)) { + return 0; + } + if((end_time > 0) && (temp_servicestatus->next_notification > end_time)) { + return 0; + } + break; + default: + return 0; + } + + /* If a service description was specified, skip the services that do not + have the service description specified */ + if(NULL != service_description && + strcmp(temp_service->description, service_description)) { + return 0; + } + + /* If a check timeperiod was specified, skip this service if it does + not have the check timeperiod specified */ + if(NULL != check_timeperiod && + (check_timeperiod != temp_service->check_period_ptr)) { + return 0; + } + + /* If a notification timeperiod was specified, skip this service if it does + not have the notification timeperiod specified */ + if(NULL != notification_timeperiod && (notification_timeperiod != + temp_service->notification_period_ptr)) { + return 0; + } + + /* If a check command was specified, skip this service if it does not + have the check command specified */ + if(NULL != check_command && + (check_command != temp_service->check_command_ptr)) { + return 0; + } + + /* If a event handler was specified, skip this service if it does not + have the event handler specified */ + if(NULL != event_handler && + (event_handler != temp_service->event_handler_ptr)) { + return 0; + } + + /* If a parent service was specified... */ + if(NULL != parent_service_name) { + /* If the parent service is "none", skip this service if it has + parentren */ + if(!strcmp(parent_service_name,"none")) { + if(NULL != temp_service->parents) { + return 0; + } + } + /* Otherwise, skip this service if it does not have the specified + service as a parent */ + else { + int found = 0; + for(temp_servicesmember = temp_service->parents; + temp_servicesmember != NULL; + temp_servicesmember = temp_servicesmember->next) { + if(!strcmp(temp_servicesmember->service_description, + parent_service_name)) { + found = 1; + } + } + if(0 == found) { + return 0; + } + } + } + + /* If a child service was specified... */ + if(NULL != child_service_name) { + /* If the child service is "none", skip this service if it has + children */ + if(!strcmp(child_service_name,"none")) { + if(NULL != temp_service->children) { + return 0; + } + } + /* Otherwise, skip this service if it does not have the specified + service as a child */ + else { + int found = 0; + for(temp_servicesmember = temp_service->children; + temp_servicesmember != NULL; + temp_servicesmember = temp_servicesmember->next) { + if(!strcmp(temp_servicesmember->service_description, + child_service_name)) { + found = 1; + } + } + if(0 == found) { + return 0; + } + } + } + + return 1; + } + +json_object *json_status_service_selectors(unsigned format_options, + int start, int count, int use_parent_host, host *parent_host, + int use_child_host, host *child_host, hostgroup *temp_hostgroup, + host *match_host, servicegroup *temp_servicegroup, int host_statuses, + int service_statuses, contact *temp_contact, int time_field, + time_t start_time, time_t end_time, char *service_description, + char *parent_service_name, char *child_service_name, + contactgroup *temp_contactgroup, timeperiod *check_timeperiod, + timeperiod *notification_timeperiod, command *check_command, + command *event_handler) { + + json_object *json_selectors; + + json_selectors = json_new_object(); + + if( start > 0) { + json_object_append_integer(json_selectors, "start", start); + } + if( count > 0) { + json_object_append_integer(json_selectors, "count", count); + } + if( 1 == use_parent_host) { + json_object_append_string(json_selectors, "parenthost", + &percent_escapes, + ( NULL == parent_host ? "none" : parent_host->name)); + } + if( 1 == use_child_host) { + json_object_append_string(json_selectors, "childhost", &percent_escapes, + ( NULL == child_host ? "none" : child_host->name)); + } + if( NULL != temp_hostgroup) { + json_object_append_string(json_selectors, "hostgroup", &percent_escapes, + temp_hostgroup->group_name); + } + if( NULL != temp_servicegroup) { + json_object_append_string(json_selectors, "servicegroup", + &percent_escapes, temp_servicegroup->group_name); + } + if(HOST_STATUS_ALL != host_statuses) { + json_bitmask(json_selectors, format_options, "host_status", + host_statuses, svm_host_statuses); + } + if(SERVICE_STATUS_ALL != service_statuses) { + json_bitmask(json_selectors, format_options, "service_status", + service_statuses, svm_service_statuses); + } + if(NULL != temp_contact) { + json_object_append_string(json_selectors, "contact",&percent_escapes, + temp_contact->name); + } + if(NULL != temp_contactgroup) { + json_object_append_string(json_selectors, "contactgroup", + &percent_escapes, temp_contactgroup->group_name); + } + if(time_field > 0) { + json_enumeration(json_selectors, format_options, "servicetimefield", + time_field, svm_service_time_fields); + } + if(start_time > 0) { + json_object_append_time_t(json_selectors, "starttime", start_time); + } + if(end_time > 0) { + json_object_append_time_t(json_selectors, "endtime", end_time); + } + if(NULL != service_description) { + json_object_append_string(json_selectors, "servicedescription", + &percent_escapes, service_description); + } + if( NULL != parent_service_name) { + json_object_append_string(json_selectors, "parentservice", + &percent_escapes, parent_service_name); + } + if( NULL != child_service_name) { + json_object_append_string(json_selectors, "childservice", + &percent_escapes, child_service_name); + } + if( NULL != check_timeperiod) { + json_object_append_string(json_selectors, "checktimeperiod", + &percent_escapes, check_timeperiod->name); + } + if( NULL != notification_timeperiod) { + json_object_append_string(json_selectors, + "servicenotificationtimeperiod", &percent_escapes, + notification_timeperiod->name); + } + if( NULL != check_command) { + json_object_append_string(json_selectors, "checkcommand", + &percent_escapes, check_command->name); + } + if( NULL != event_handler) { + json_object_append_string(json_selectors, "eventhandler", + &percent_escapes, event_handler->name); + } + + return json_selectors; + } + +json_object *json_status_servicecount(unsigned format_options, host *match_host, + int use_parent_host, host *parent_host, int use_child_host, + host *child_host, hostgroup *temp_hostgroup, + servicegroup *temp_servicegroup, int host_statuses, + int service_statuses, contact *temp_contact, int time_field, + time_t start_time, time_t end_time, char *service_description, + char *parent_service_name, char *child_service_name, + contactgroup *temp_contactgroup, timeperiod *check_timeperiod, + timeperiod *notification_timeperiod, command *check_command, + command *event_handler) { + + json_object *json_data; + json_object *json_count; + host *temp_host; + service *temp_service; + servicestatus *temp_servicestatus; + int ok = 0; + int warning = 0; + int critical = 0; + int unknown = 0; + int pending = 0; + + json_data = json_new_object(); + json_object_append_object(json_data, "selectors", + json_status_service_selectors(format_options, 0, 0, use_parent_host, + parent_host, use_child_host, child_host, temp_hostgroup, match_host, + temp_servicegroup, host_statuses, service_statuses, temp_contact, + time_field, start_time, end_time, service_description, + parent_service_name, child_service_name, temp_contactgroup, + check_timeperiod, notification_timeperiod, check_command, + event_handler)); + + json_count = json_new_object(); + + for(temp_service = service_list; temp_service != NULL; + temp_service = temp_service->next) { + + temp_host = find_host(temp_service->host_name); + if(NULL == temp_host) { + continue; + } + + if(!json_status_service_passes_host_selection(temp_host, + use_parent_host, parent_host, use_child_host, child_host, + temp_hostgroup, match_host, host_statuses)) { + continue; + } + + /* Get the service status. If we cannot get the status of + the service, skip it. This should probably return an + error and doing so is in the todo list. */ + temp_servicestatus = find_servicestatus(temp_service->host_name, + temp_service->description); + if( NULL == temp_servicestatus) { + continue; + } + + if(!json_status_service_passes_service_selection(temp_service, + temp_servicegroup, temp_contact, temp_servicestatus, + time_field, start_time, end_time, service_description, + parent_service_name, child_service_name, temp_contactgroup, + check_timeperiod, notification_timeperiod, check_command, + event_handler)) { + continue; + } + + /* Count the services in each state */ + switch(temp_servicestatus->status) { + case SERVICE_PENDING: + pending++; + break; + case SERVICE_OK: + ok++; + break; + case SERVICE_WARNING: + warning++; + break; + case SERVICE_CRITICAL: + critical++; + break; + case SERVICE_UNKNOWN: + unknown++; + break; + } + } + + if( service_statuses & SERVICE_OK) + json_object_append_integer(json_count, "ok", ok); + if( service_statuses & SERVICE_WARNING) + json_object_append_integer(json_count, "warning", warning); + if( service_statuses & SERVICE_CRITICAL) + json_object_append_integer(json_count, "critical", critical); + if( service_statuses & SERVICE_UNKNOWN) + json_object_append_integer(json_count, "unknown", unknown); + if( service_statuses & SERVICE_PENDING) + json_object_append_integer(json_count, "pending", pending); + + json_object_append_object(json_data, "count", json_count); + + return json_data; + } + +json_object *json_status_servicelist(unsigned format_options, int start, + int count, int details, host *match_host, int use_parent_host, + host *parent_host, int use_child_host, host *child_host, + hostgroup *temp_hostgroup, servicegroup *temp_servicegroup, + int host_statuses, int service_statuses, contact *temp_contact, + int time_field, time_t start_time, time_t end_time, + char *service_description, char *parent_service_name, + char *child_service_name, contactgroup *temp_contactgroup, + timeperiod *check_timeperiod, timeperiod *notification_timeperiod, + command *check_command, command *event_handler) { + + json_object *json_data; + json_object *json_hostlist; + json_object *json_servicelist; + json_object *json_service_details; + host *temp_host; + service *temp_service; + servicestatus *temp_servicestatus; + int current = 0; + int counted = 0; + int service_count; /* number of services on a host */ + + json_data = json_new_object(); + json_object_append_object(json_data, "selectors", + json_status_service_selectors(format_options, start, count, + use_parent_host, parent_host, use_child_host, child_host, + temp_hostgroup, match_host, temp_servicegroup, host_statuses, + service_statuses, temp_contact, time_field, start_time, end_time, + service_description, parent_service_name, child_service_name, + temp_contactgroup, check_timeperiod, notification_timeperiod, + check_command, event_handler)); + + json_hostlist = json_new_object(); + + for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) { + + if(json_status_service_passes_host_selection(temp_host, + use_parent_host, parent_host, use_child_host, child_host, + temp_hostgroup, match_host, host_statuses) == 0) { + continue; + } + + json_servicelist = json_new_object(); + + service_count = 0; + + for(temp_service = service_list; temp_service != NULL; + temp_service = temp_service->next) { + + /* If this service isn't on the host we're currently working with, + skip it */ + if( strcmp( temp_host->name, temp_service->host_name)) continue; + + /* Get the service status. If we cannot get the status of + the service, skip it. This should probably return an + error and doing so is in the todo list. */ + temp_servicestatus = find_servicestatus(temp_service->host_name, + temp_service->description); + if( NULL == temp_servicestatus) { + continue; + } + + if(json_status_service_passes_service_selection(temp_service, + temp_servicegroup, temp_contact, temp_servicestatus, + time_field, start_time, end_time, + service_description, parent_service_name, + child_service_name, temp_contactgroup, + check_timeperiod, notification_timeperiod, + check_command, event_handler) == 0) { + continue; + } + + /* If the status of the service does not match one of the status the + user requested, skip the service */ + if(!(temp_servicestatus->status & service_statuses)) { + continue; + } + + service_count++; + + /* If the current item passes the start and limit tests, display it */ + if( passes_start_and_count_limits(start, count, current, counted)) { + if( details > 0) { + json_service_details = json_new_object(); + json_status_service_details(json_service_details, + format_options, + temp_service, temp_servicestatus); + json_object_append_object(json_servicelist, + temp_service->description, + json_service_details); + } + else { + json_enumeration(json_servicelist, format_options, + temp_service->description, + temp_servicestatus->status, + svm_service_statuses); + } + counted++; + } + current++; + } + + if( service_count > 0) { + json_object_append_object(json_hostlist, temp_host->name, + json_servicelist); + } + } + + json_object_append_object(json_data, "servicelist", json_hostlist); + + return json_data; + } + +json_object *json_status_service(unsigned format_options, service *temp_service, + servicestatus *temp_servicestatus) { + + json_object *json_service = json_new_object(); + json_object *json_details = json_new_object(); + + json_object_append_string(json_details, "host_name", &percent_escapes, + temp_service->host_name); + json_object_append_string(json_details, "description", &percent_escapes, + temp_service->description); + json_status_service_details(json_details, format_options, temp_service, + temp_servicestatus); + json_object_append_object(json_service, "service", json_details); + + return json_service; + } + +void json_status_service_details(json_object *json_details, + unsigned format_options, service *temp_service, + servicestatus *temp_servicestatus) { + + json_object_append_string(json_details, "host_name", &percent_escapes, + temp_service->host_name); + json_object_append_string(json_details, "description", &percent_escapes, + temp_service->description); + json_object_append_string(json_details, "plugin_output", &percent_escapes, + temp_servicestatus->plugin_output); + json_object_append_string(json_details, "long_plugin_output", + &percent_escapes, temp_servicestatus->long_plugin_output); + json_object_append_string(json_details, "perf_data", &percent_escapes, + temp_servicestatus->perf_data); + json_object_append_integer(json_details, "max_attempts", + temp_servicestatus->max_attempts); + json_object_append_integer(json_details, "current_attempt", + temp_servicestatus->current_attempt); + json_enumeration(json_details, format_options, "status", + temp_servicestatus->status, svm_service_statuses); + json_object_append_time_t(json_details, "last_update", + temp_servicestatus->last_update); + json_object_append_boolean(json_details, "has_been_checked", + temp_servicestatus->has_been_checked); + json_object_append_boolean(json_details, "should_be_scheduled", + temp_servicestatus->should_be_scheduled); + json_object_append_time_t(json_details, "last_check", + temp_servicestatus->last_check); + json_bitmask(json_details, format_options, "check_options", + temp_servicestatus->check_options, svm_check_options); + json_enumeration(json_details, format_options, "check_type", + temp_servicestatus->check_type, svm_service_check_types); + json_object_append_boolean(json_details, "checks_enabled", + temp_servicestatus->checks_enabled); + json_object_append_time_t(json_details, "last_state_change", + temp_servicestatus->last_state_change); + json_object_append_time_t(json_details, "last_hard_state_change", + temp_servicestatus->last_hard_state_change); + json_enumeration(json_details, format_options, "last_hard_state", + temp_servicestatus->last_hard_state, svm_service_states); + json_object_append_time_t(json_details, "last_time_ok", + temp_servicestatus->last_time_ok); + json_object_append_time_t(json_details, "last_time_warning", + temp_servicestatus->last_time_warning); + json_object_append_time_t(json_details, "last_time_unknown", + temp_servicestatus->last_time_unknown); + json_object_append_time_t(json_details, "last_time_critical", + temp_servicestatus->last_time_critical); + json_enumeration(json_details, format_options, "state_type", + temp_servicestatus->state_type, svm_state_types); + json_object_append_time_t(json_details, "last_notification", + temp_servicestatus->last_notification); + json_object_append_time_t(json_details, "next_notification", + temp_servicestatus->next_notification); + json_object_append_time_t(json_details, "next_check", + temp_servicestatus->next_check); + json_object_append_boolean(json_details, "no_more_notifications", + temp_servicestatus->no_more_notifications); + json_object_append_boolean(json_details, "notifications_enabled", + temp_servicestatus->notifications_enabled); + json_object_append_boolean(json_details, "problem_has_been_acknowledged", + temp_servicestatus->problem_has_been_acknowledged); + json_enumeration(json_details, format_options, "acknowledgement_type", + temp_servicestatus->acknowledgement_type, + svm_acknowledgement_types); + json_object_append_integer(json_details, "current_notification_number", + temp_servicestatus->current_notification_number); +#ifdef JSON_NAGIOS_4X + json_object_append_boolean(json_details, "accept_passive_checks", + temp_servicestatus->accept_passive_checks); +#else + json_object_append_boolean(json_details, "accept_passive_service_checks", + temp_servicestatus->accept_passive_service_checks); +#endif + json_object_append_boolean(json_details, "event_handler_enabled", + temp_servicestatus->event_handler_enabled); + json_object_append_boolean(json_details, "flap_detection_enabled", + temp_servicestatus->flap_detection_enabled); + json_object_append_boolean(json_details, "is_flapping", + temp_servicestatus->is_flapping); + json_object_append_real(json_details, "percent_state_change", + temp_servicestatus->percent_state_change); + json_object_append_real(json_details, "latency", temp_servicestatus->latency); + json_object_append_real(json_details, "execution_time", + temp_servicestatus->execution_time); + json_object_append_integer(json_details, "scheduled_downtime_depth", + temp_servicestatus->scheduled_downtime_depth); +#ifndef JSON_NAGIOS_4X + json_object_append_boolean(json_details, "failure_prediction_enabled", + temp_servicestatus->failure_prediction_enabled); +#endif + json_object_append_boolean(json_details, "process_performance_data", + temp_servicestatus->process_performance_data); +#ifdef JSON_NAGIOS_4X + json_object_append_boolean(json_details, "obsess", + temp_servicestatus->obsess); +#else + json_object_append_boolean(json_details, "obsess_over_service", + temp_servicestatus->obsess_over_service); +#endif + } + +int json_status_comment_passes_selection(nagios_comment *temp_comment, + int time_field, time_t start_time, time_t end_time, + unsigned comment_types, unsigned entry_types, unsigned persistence, + unsigned expiring, char *host_name, char *service_description) { + + switch(time_field) { + case STATUS_TIME_INVALID: + break; + case STATUS_TIME_ENTRY_TIME: + if((start_time > 0) && (temp_comment->entry_time < start_time)) { + return 0; + } + if((end_time > 0) && (temp_comment->entry_time > end_time)) { + return 0; + } + break; + case STATUS_TIME_EXPIRE_TIME: + if((start_time > 0) && (temp_comment->expire_time < start_time)) { + return 0; + } + if((end_time > 0) && (temp_comment->expire_time > end_time)) { + return 0; + } + break; + default: + return 0; + } + + if(comment_types != COMMENT_TYPE_ALL) { + switch(temp_comment->comment_type) { + case HOST_COMMENT: + if(!(comment_types & COMMENT_TYPE_HOST)) { + return 0; + } + break; + case SERVICE_COMMENT: + if(!(comment_types & COMMENT_TYPE_SERVICE)) { + return 0; + } + break; + } + } + + if(entry_types != COMMENT_ENTRY_ALL) { + switch(temp_comment->entry_type) { + case USER_COMMENT: + if(!(entry_types & COMMENT_ENTRY_USER)) { + return 0; + } + break; + case DOWNTIME_COMMENT: + if(!(entry_types & COMMENT_ENTRY_DOWNTIME)) { + return 0; + } + break; + case FLAPPING_COMMENT: + if(!(entry_types & COMMENT_ENTRY_FLAPPING)) { + return 0; + } + break; + case ACKNOWLEDGEMENT_COMMENT: + if(!(entry_types & COMMENT_ENTRY_ACKNOWLEDGEMENT)) { + return 0; + } + break; + } + } + + if(persistence != BOOLEAN_EITHER) { + switch(temp_comment->persistent) { + case 0: /* false */ + if(!(persistence & BOOLEAN_FALSE)) { + return 0; + } + break; + case 1: /* true */ + if(!(persistence & BOOLEAN_TRUE)) { + return 0; + } + break; + } + } + + if(expiring != BOOLEAN_EITHER) { + switch(temp_comment->expires) { + case 0: /* false */ + if(!(expiring & BOOLEAN_FALSE)) { + return 0; + } + break; + case 1: /* true */ + if(!(expiring & BOOLEAN_TRUE)) { + return 0; + } + break; + } + } + + if(NULL != host_name) { + if((NULL == temp_comment->host_name) || + strcmp(temp_comment->host_name, host_name)) { + return 0; + } + } + + if(NULL != service_description) { + if((NULL == temp_comment->service_description) || + strcmp(temp_comment->service_description, + service_description)) { + return 0; + } + } + + return 1; + } + +json_object *json_status_comment_selectors(unsigned format_options, int start, + int count, int time_field, time_t start_time, time_t end_time, + unsigned comment_types, unsigned entry_types, unsigned persistence, + unsigned expiring, char *host_name, char *service_description) { + + json_object *json_selectors; + + json_selectors = json_new_object(); + + if( start > 0) { + json_object_append_integer(json_selectors, "start", start); + } + if( count > 0) { + json_object_append_integer(json_selectors, "count", count); + } + if(time_field > 0) { + json_enumeration(json_selectors, format_options, "commenttimefield", + time_field, svm_comment_time_fields); + } + if(start_time > 0) { + json_object_append_time_t(json_selectors, "starttime", start_time); + } + if(end_time > 0) { + json_object_append_time_t(json_selectors, "endtime", end_time); + } + if(comment_types != COMMENT_TYPE_ALL) { + json_bitmask(json_selectors, format_options, "commenttypes", + comment_types, svm_valid_comment_types); + } + if(entry_types != COMMENT_ENTRY_ALL) { + json_bitmask(json_selectors, format_options, "entrytypes", + entry_types, svm_valid_comment_entry_types); + } + if(persistence != BOOLEAN_EITHER) { + json_bitmask(json_selectors, format_options, "persistence", + persistence, svm_valid_persistence); + } + if(expiring != BOOLEAN_EITHER) { + json_bitmask(json_selectors, format_options, "expiring", + expiring, svm_valid_expiration); + } + if(NULL != host_name) { + json_object_append_string(json_selectors, "hostname", &percent_escapes, + host_name); + } + if(NULL != service_description) { + json_object_append_string(json_selectors, "servicedescription", + &percent_escapes, service_description); + } + + return json_selectors; + } + +json_object *json_status_commentcount(unsigned format_options, int time_field, + time_t start_time, time_t end_time, unsigned comment_types, + unsigned entry_types, unsigned persistence, unsigned expiring, + char *host_name, char *service_description) { + + json_object *json_data; + nagios_comment *temp_comment; + int count = 0; + + json_data = json_new_object(); + json_object_append_object(json_data, "selectors", + json_status_comment_selectors(format_options, 0, 0, time_field, + start_time, end_time, comment_types, entry_types, persistence, + expiring, host_name, service_description)); + + for(temp_comment = comment_list; temp_comment != NULL; + temp_comment = temp_comment->next) { + if(json_status_comment_passes_selection(temp_comment, time_field, + start_time, end_time, comment_types, entry_types, + persistence, expiring, host_name, service_description) == 0) { + continue; + } + count++; + } + + json_object_append_integer(json_data, "count", count); + + return json_data; + } + +json_object *json_status_commentlist(unsigned format_options, int start, + int count, int details, int time_field, time_t start_time, + time_t end_time, unsigned comment_types, unsigned entry_types, + unsigned persistence, unsigned expiring, char *host_name, + char *service_description) { + + json_object *json_data; + json_object *json_commentlist_object = NULL; + json_object *json_commentlist_array = NULL; + json_object *json_comment_details; + nagios_comment *temp_comment; + int current = 0; + int counted = 0; + char *buf; + + json_data = json_new_object(); + json_object_append_object(json_data, "selectors", + json_status_comment_selectors(format_options, start, count, + time_field, start_time, end_time, comment_types, entry_types, + persistence, expiring, host_name, service_description)); + + if(details > 0) { + json_commentlist_object = json_new_object(); + } + else { + json_commentlist_array = json_new_array(); + } + + for(temp_comment = comment_list; temp_comment != NULL; + temp_comment = temp_comment->next) { + + if(json_status_comment_passes_selection(temp_comment, time_field, + start_time, end_time, comment_types, entry_types, + persistence, expiring, host_name, service_description) == 0) { + continue; + } + + /* If the current item passes the start and limit tests, display it */ + if( passes_start_and_count_limits(start, count, current, counted)) { + if( details > 0) { + asprintf(&buf, "%lu", temp_comment->comment_id); + json_comment_details = json_new_object(); + json_status_comment_details(json_comment_details, format_options, + temp_comment); + json_object_append_object(json_commentlist_object, buf, + json_comment_details); + } + else { + json_array_append_integer(json_commentlist_array, + temp_comment->comment_id); + } + counted++; + } + current++; + } + + if(details > 0) { + json_object_append_object(json_data, "commentlist", + json_commentlist_object); + } + else { + json_object_append_array(json_data, "commentlist", + json_commentlist_array); + } + + return json_data; + } + +json_object *json_status_comment(unsigned format_options, + nagios_comment *temp_comment) { + + json_object *json_comment = json_new_object(); + json_object *json_details = json_new_object(); + + json_object_append_integer(json_details, "comment_id", + temp_comment->comment_id); + json_status_comment_details(json_details, format_options, temp_comment); + json_object_append_object(json_comment, "comment", json_details); + + return json_comment; + } + +void json_status_comment_details(json_object *json_details, + unsigned format_options, nagios_comment *temp_comment) { + + json_object_append_integer(json_details, "comment_id", + temp_comment->comment_id); + json_enumeration(json_details, format_options, "comment_type", + temp_comment->comment_type, svm_comment_types); + json_enumeration(json_details, format_options, "entry_type", + temp_comment->entry_type, svm_comment_entry_types); + json_object_append_integer(json_details, "source", temp_comment->source); + json_object_append_boolean(json_details, "persistent", + temp_comment->persistent); + json_object_append_time_t(json_details, "entry_time", + temp_comment->entry_time); + json_object_append_boolean(json_details, "expires", temp_comment->expires); + json_object_append_time_t(json_details, "expire_time", + temp_comment->expire_time); + json_object_append_string(json_details, "host_name", &percent_escapes, + temp_comment->host_name); + if(SERVICE_COMMENT == temp_comment->comment_type) { + json_object_append_string(json_details, "service_description", + &percent_escapes, temp_comment->service_description); + } + json_object_append_string(json_details, "author", &percent_escapes, + temp_comment->author); + json_object_append_string(json_details, "comment_data", &percent_escapes, + temp_comment->comment_data); + } + +int json_status_downtime_passes_selection(scheduled_downtime *temp_downtime, + int time_field, time_t start_time, time_t end_time, + unsigned object_types, unsigned downtime_types, unsigned triggered, + int triggered_by, unsigned in_effect, char *host_name, + char *service_description) { + + switch(time_field) { + case STATUS_TIME_INVALID: + break; + case STATUS_TIME_ENTRY_TIME: + if((start_time > 0) && (temp_downtime->entry_time < start_time)) { + return 0; + } + if((end_time > 0) && (temp_downtime->entry_time > end_time)) { + return 0; + } + break; + case STATUS_TIME_START_TIME: + if((start_time > 0) && (temp_downtime->start_time < start_time)) { + return 0; + } + if((end_time > 0) && (temp_downtime->start_time > end_time)) { + return 0; + } + break; + case STATUS_TIME_FLEX_DOWNTIME_START: + if((start_time > 0) && (temp_downtime->flex_downtime_start < + start_time)) { + return 0; + } + if((end_time > 0) && (temp_downtime->flex_downtime_start > end_time)) { + return 0; + } + break; + case STATUS_TIME_END_TIME: + if((start_time > 0) && (temp_downtime->end_time < start_time)) { + return 0; + } + if((end_time > 0) && (temp_downtime->end_time > end_time)) { + return 0; + } + break; + default: + return 0; + } + + if(object_types != DOWNTIME_OBJECT_TYPE_ALL) { + switch(temp_downtime->type) { + case HOST_DOWNTIME: + if(!(object_types & DOWNTIME_OBJECT_TYPE_HOST)) { + return 0; + } + break; + case SERVICE_DOWNTIME: + if(!(object_types & DOWNTIME_OBJECT_TYPE_SERVICE)) { + return 0; + } + break; + } + } + + if(downtime_types != DOWNTIME_TYPE_ALL) { + if(temp_downtime->fixed) { + if(!(downtime_types & DOWNTIME_TYPE_FIXED)) { + return 0; + } + } + else { + if(!(downtime_types & DOWNTIME_TYPE_FLEXIBLE)) { + return 0; + } + } + } + + if(triggered != BOOLEAN_EITHER) { + if(0 == temp_downtime->triggered_by) { + if(!(triggered & BOOLEAN_FALSE)) { + return 0; + } + } + else { + if(!(triggered & BOOLEAN_TRUE)) { + return 0; + } + } + } + + if(triggered_by != -1) { + if(temp_downtime->triggered_by != (unsigned long)triggered_by) { + return 0; + } + } + + if(in_effect != BOOLEAN_EITHER) { + if(0 == temp_downtime->is_in_effect) { + if(!(in_effect & BOOLEAN_FALSE)) { + return 0; + } + } + else { + if(!(in_effect & BOOLEAN_TRUE)) { + return 0; + } + } + } + + if(NULL != host_name) { + if((NULL == temp_downtime->host_name) || + strcmp(temp_downtime->host_name, host_name)) { + return 0; + } + } + + if(NULL != service_description) { + if((NULL == temp_downtime->service_description) || + strcmp(temp_downtime->service_description, + service_description)) { + return 0; + } + } + + return 1; + } + +json_object *json_status_downtime_selectors(unsigned format_options, int start, + int count, int time_field, time_t start_time, time_t end_time, + unsigned object_types, unsigned downtime_types, unsigned triggered, + int triggered_by, unsigned in_effect, char *host_name, + char *service_description) { + + json_object *json_selectors; + + json_selectors = json_new_object(); + + if( start > 0) { + json_object_append_integer(json_selectors, "start", start); + } + if( count > 0) { + json_object_append_integer(json_selectors, "count", count); + } + if(time_field > 0) { + json_enumeration(json_selectors, format_options, "downtimetimefield", + time_field, svm_downtime_time_fields); + } + if(start_time > 0) { + json_object_append_time_t(json_selectors, "starttime", start_time); + } + if(end_time > 0) { + json_object_append_time_t(json_selectors, "endtime", end_time); + } + if(object_types != DOWNTIME_OBJECT_TYPE_ALL) { + json_bitmask(json_selectors, format_options, "downtimeobjecttypes", + object_types, svm_valid_downtime_object_types); + } + if(downtime_types != DOWNTIME_TYPE_ALL) { + json_bitmask(json_selectors, format_options, "downtimetypes", + downtime_types, svm_valid_downtime_types); + } + if(triggered != BOOLEAN_EITHER) { + json_bitmask(json_selectors, format_options, "triggered", + triggered, svm_valid_triggered_status); + } + if(triggered_by != -1) { + json_object_append_integer(json_selectors, "triggeredby", triggered_by); + } + if(in_effect != BOOLEAN_EITHER) { + json_bitmask(json_selectors, format_options, "ineffect", + in_effect, svm_valid_in_effect_status); + } + if(NULL != host_name) { + json_object_append_string(json_selectors, "hostname", &percent_escapes, + host_name); + } + if(NULL != service_description) { + json_object_append_string(json_selectors, "servicedescription", + &percent_escapes, service_description); + } + + return json_selectors; + } + +json_object *json_status_downtimecount(unsigned format_options, int time_field, + time_t start_time, time_t end_time, unsigned object_types, + unsigned downtime_types, unsigned triggered, int triggered_by, + unsigned in_effect, char *host_name, char *service_description) { + + json_object *json_data; + scheduled_downtime *temp_downtime; + int count = 0; + + json_data = json_new_object(); + json_object_append_object(json_data, "selectors", + json_status_downtime_selectors(format_options, 0, 0, time_field, + start_time, end_time, object_types, downtime_types, triggered, + triggered_by, in_effect, host_name, service_description)); + + for(temp_downtime = scheduled_downtime_list; temp_downtime != NULL; + temp_downtime = temp_downtime->next) { + if(!json_status_downtime_passes_selection(temp_downtime, time_field, + start_time, end_time, object_types, downtime_types, + triggered, triggered_by, in_effect, host_name, + service_description)) { + continue; + } + count++; + } + + json_object_append_integer(json_data, "count", count); + + return json_data; + } + +json_object *json_status_downtimelist(unsigned format_options, int start, + int count, int details, int time_field, time_t start_time, + time_t end_time, unsigned object_types, unsigned downtime_types, + unsigned triggered, int triggered_by, unsigned in_effect, + char *host_name, char *service_description) { + + json_object *json_data; + json_object *json_downtimelist_object = NULL; + json_object *json_downtimelist_array = NULL; + json_object *json_downtime_details; + scheduled_downtime *temp_downtime; + int current = 0; + int counted = 0; + char *buf; + + json_data = json_new_object(); + json_object_append_object(json_data, "selectors", + json_status_downtime_selectors(format_options, start, count, + time_field, start_time, end_time, object_types, downtime_types, + triggered, triggered_by, in_effect, host_name, + service_description)); + + if(details > 0) { + json_downtimelist_object = json_new_object(); + } + else { + json_downtimelist_array = json_new_array(); + } + + for(temp_downtime = scheduled_downtime_list; temp_downtime != NULL; + temp_downtime = temp_downtime->next) { + + if(!json_status_downtime_passes_selection(temp_downtime, time_field, + start_time, end_time, object_types, downtime_types, + triggered, triggered_by, in_effect, host_name, + service_description)) { + continue; + } + + /* If the current item passes the start and limit tests, display it */ + if( passes_start_and_count_limits(start, count, current, counted)) { + if( details > 0) { + asprintf(&buf, "%lu", temp_downtime->downtime_id); + json_downtime_details = json_new_object(); + json_status_downtime_details(json_downtime_details, + format_options, temp_downtime); + json_object_append_object(json_downtimelist_object, buf, + json_downtime_details); + } + else { + json_array_append_integer(json_downtimelist_array, + temp_downtime->downtime_id); + } + counted++; + } + current++; + } + + if(details > 0) { + json_object_append_object(json_data, "downtimelist", + json_downtimelist_object); + } + else { + json_object_append_array(json_data, "downtimelist", + json_downtimelist_array); + } + + return json_data; + } + +json_object *json_status_downtime(unsigned format_options, + scheduled_downtime *temp_downtime) { + + json_object *json_downtime = json_new_object(); + json_object *json_details = json_new_object(); + + json_object_append_integer(json_details, "downtime_id", + temp_downtime->downtime_id); + json_status_downtime_details(json_details, format_options, temp_downtime); + json_object_append_object(json_downtime, "downtime", json_details); + + return json_downtime; + } + +void json_status_downtime_details(json_object *json_details, + unsigned format_options, scheduled_downtime *temp_downtime) { + + json_object_append_integer(json_details, "downtime_id", + temp_downtime->downtime_id); + json_enumeration(json_details, format_options, "type", temp_downtime->type, + svm_downtime_types); + json_object_append_string(json_details, "host_name", &percent_escapes, + temp_downtime->host_name); + if(SERVICE_DOWNTIME == temp_downtime->type) { + json_object_append_string(json_details, "service_description", + &percent_escapes, temp_downtime->service_description); + } + json_object_append_time_t(json_details, "entry_time", + temp_downtime->entry_time); + json_object_append_time_t(json_details, "start_time", + temp_downtime->start_time); + json_object_append_time_t(json_details, "flex_downtime_start", + temp_downtime->flex_downtime_start); + json_object_append_time_t(json_details, "end_time", temp_downtime->end_time); + json_object_append_boolean(json_details, "fixed", temp_downtime->fixed); + json_object_append_integer(json_details, "triggered_by", + (int)temp_downtime->triggered_by); + json_object_append_integer(json_details, "duration", + (int)temp_downtime->duration); + json_object_append_boolean(json_details, "is_in_effect", + temp_downtime->is_in_effect); + json_object_append_boolean(json_details, "start_notification_sent", + temp_downtime->start_notification_sent); + json_object_append_string(json_details, "author", &percent_escapes, + temp_downtime->author); + json_object_append_string(json_details, "comment", &percent_escapes, + temp_downtime->comment); + } + +json_object *json_status_program(unsigned format_options) { + + json_object *json_data; + json_object *json_status; + + json_data = json_new_object(); + + json_status = json_new_object(); + +#if 0 + json_object_append_unsigned(json_status, "modified_host_attributes", + (unsigned long long)modified_host_process_attributes); + json_object_append_unsigned(json_status, + "modified_service_process_attributes", + (unsigned long long)modified_service_process_attributes); +#endif + json_object_append_string(json_status, "version", NULL, PROGRAM_VERSION); + json_object_append_integer(json_status, "nagios_pid", nagios_pid); + json_object_append_boolean(json_status, "daemon_mode", daemon_mode); + json_object_append_time_t(json_status, "program_start", program_start); +#ifndef JSON_NAGIOS_4X + json_object_append_time_t(json_status, "last_command_check", + last_command_check); +#endif + json_object_append_time_t(json_status, "last_log_rotation", + last_log_rotation); + json_object_append_boolean(json_status, "enable_notifications", + enable_notifications); + json_object_append_boolean(json_status, "execute_service_checks", + execute_service_checks); + json_object_append_boolean(json_status, "accept_passive_service_checks", + accept_passive_service_checks); + json_object_append_boolean(json_status, "execute_host_checks", + execute_host_checks); + json_object_append_boolean(json_status, "accept_passive_host_checks", + accept_passive_host_checks); + json_object_append_boolean(json_status, "enable_event_handlers", + enable_event_handlers); + json_object_append_boolean(json_status, "obsess_over_services", + obsess_over_services); + json_object_append_boolean(json_status, "obsess_over_hosts", + obsess_over_hosts); + json_object_append_boolean(json_status, "check_service_freshness", + check_service_freshness); + json_object_append_boolean(json_status, "check_host_freshness", + check_host_freshness); + json_object_append_boolean(json_status, "enable_flap_detection", + enable_flap_detection); +#ifndef JSON_NAGIOS_4X + json_object_append_boolean(json_status, "enable_failure_prediction", + enable_failure_prediction); +#endif + json_object_append_boolean(json_status, "process_performance_data", + process_performance_data); +#if 0 + json_object_append_string(json_status, "global_host_event_handler", + &percent_escapes, global_host_event_handler); + json_object_append_string(json_status, "global_service_event_handler", + &percent_escapes, global_service_event_handler); + json_object_append_unsigned(json_status, "next_comment_id", + (unsigned long long)next_comment_id); + json_object_append_unsigned(json_status, "next_downtime_id", + (unsigned long long)next_downtime_id); + json_object_append_unsigned(json_status, "next_event_id", + (unsigned long long)next_event_id); + json_object_append_unsigned(json_status, "next_problem_id", + (unsigned long long)next_problem_id); + json_object_append_unsigned(json_status, "next_notification_id", + (unsigned long long)next_notification_id); + json_object_append_unsigned(json_status, + "total_external_command_buffer_slots", + (unsigned long long)external_command_buffer_slots); + json_object_append_unsigned(json_status, "used_external_command_buffer_slots", + (unsigned long long)used_external_command_buffer_slots); + json_object_append_unsigned(json_status, "high_external_command_buffer_slots", + (unsigned long long)high_external_command_buffer_slots); + json_object_append_string(json_status, "active_scheduled_host_check_stats", + NULL, "%d,%d,%d", + 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]); + json_object_append_string(json_status, "active_ondemand_host_check_stats", + NULL, "%d,%d,%d", + 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]); + json_object_append_string(json_status, "passive_host_check_stats", NULL, + "%d,%d,%d", + 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]); + json_object_append_string(json_status, + "active_scheduled_service_check_stats", NULL, "%d,%d,%d", + 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]); + json_object_append_string(json_status, "active_ondemand_service_check_stats", + NULL, "%d,%d,%d", + 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]); + json_object_append_string(json_status, "passive_service_check_stats", + NULL, "%d,%d,%d", + 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]); + json_object_append_string(json_status, "cached_host_check_stats", NULL, + "%d,%d,%d", + 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]); + json_object_append_string(json_status, "cached_service_check_stats", + NULL, "%d,%d,%d", + 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]); + json_object_append_string(json_status, "external_command_stats", NULL, + "%d,%d,%d", + check_statistics[EXTERNAL_COMMAND_STATS].minute_stats[0], + check_statistics[EXTERNAL_COMMAND_STATS].minute_stats[1], + check_statistics[EXTERNAL_COMMAND_STATS].minute_stats[2]); + json_object_append_string(json_status, "parallel_host_check_stats", + NULL, "%d,%d,%d", + 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]); + json_object_append_string(json_status, "serial_host_check_stats", NULL, + "%d,%d,%d", + 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]); +#endif + + json_object_append_object(json_data, "programstatus", json_status); + + return json_data; + } + +json_object *json_status_performance(void) { + + service *temp_service = NULL; + servicestatus *temp_servicestatus = NULL; + host *temp_host = NULL; + hoststatus *temp_hoststatus = NULL; + int total_active_service_checks = 0; + int total_passive_service_checks = 0; + double min_service_execution_time = 0.0; + double max_service_execution_time = 0.0; + double total_service_execution_time = 0.0; + int have_min_service_execution_time = FALSE; + int have_max_service_execution_time = FALSE; + double min_service_latency = 0.0; + double max_service_latency = 0.0; + double long total_service_latency = 0.0; + int have_min_service_latency = FALSE; + int have_max_service_latency = FALSE; + double min_host_latency = 0.0; + double max_host_latency = 0.0; + double total_host_latency = 0.0; + int have_min_host_latency = FALSE; + int have_max_host_latency = FALSE; + double min_service_percent_change_a = 0.0; + double max_service_percent_change_a = 0.0; + double total_service_percent_change_a = 0.0; + int have_min_service_percent_change_a = FALSE; + int have_max_service_percent_change_a = FALSE; + double min_service_percent_change_b = 0.0; + double max_service_percent_change_b = 0.0; + double total_service_percent_change_b = 0.0; + int have_min_service_percent_change_b = FALSE; + int have_max_service_percent_change_b = FALSE; + int active_service_checks_1min = 0; + int active_service_checks_5min = 0; + int active_service_checks_15min = 0; + int active_service_checks_1hour = 0; + int active_service_checks_start = 0; + int active_service_checks_ever = 0; + int passive_service_checks_1min = 0; + int passive_service_checks_5min = 0; + int passive_service_checks_15min = 0; + int passive_service_checks_1hour = 0; + int passive_service_checks_start = 0; + int passive_service_checks_ever = 0; + int total_active_host_checks = 0; + int total_passive_host_checks = 0; + double min_host_execution_time = 0.0; + double max_host_execution_time = 0.0; + double total_host_execution_time = 0.0; + int have_min_host_execution_time = FALSE; + int have_max_host_execution_time = FALSE; + double min_host_percent_change_a = 0.0; + double max_host_percent_change_a = 0.0; + double total_host_percent_change_a = 0.0; + int have_min_host_percent_change_a = FALSE; + int have_max_host_percent_change_a = FALSE; + double min_host_percent_change_b = 0.0; + double max_host_percent_change_b = 0.0; + double total_host_percent_change_b = 0.0; + int have_min_host_percent_change_b = FALSE; + int have_max_host_percent_change_b = FALSE; + int active_host_checks_1min = 0; + int active_host_checks_5min = 0; + int active_host_checks_15min = 0; + int active_host_checks_1hour = 0; + int active_host_checks_start = 0; + int active_host_checks_ever = 0; + int passive_host_checks_1min = 0; + int passive_host_checks_5min = 0; + int passive_host_checks_15min = 0; + int passive_host_checks_1hour = 0; + int passive_host_checks_start = 0; + int passive_host_checks_ever = 0; + time_t current_time; + + json_object *json_data; + json_object *json_programstatus; + json_object *json_service_checks; + json_object *json_host_checks; + json_object *json_check_statistics; + json_object *json_buffer_usage; + json_object *json_active; + json_object *json_passive; + json_object *json_checks; + json_object *json_metrics; + json_object *json_temp; + + time(¤t_time); + + /* check all services */ + for(temp_servicestatus = servicestatus_list; temp_servicestatus != NULL; + temp_servicestatus = temp_servicestatus->next) { + + /* find the service */ + temp_service = find_service(temp_servicestatus->host_name, + temp_servicestatus->description); + if(NULL == temp_service) { + continue; + } + + /* make sure the user has rights to view service information */ + if(FALSE == is_authorized_for_service(temp_service, + ¤t_authdata)) { + continue; + } + + /* is this an active or passive check? */ + if(SERVICE_CHECK_ACTIVE == temp_servicestatus->check_type) { + + total_active_service_checks++; + + total_service_execution_time += temp_servicestatus->execution_time; + if(have_min_service_execution_time == FALSE || + temp_servicestatus->execution_time < + min_service_execution_time) { + have_min_service_execution_time = TRUE; + min_service_execution_time = temp_servicestatus->execution_time; + } + if(have_max_service_execution_time == FALSE || + temp_servicestatus->execution_time > + max_service_execution_time) { + have_max_service_execution_time = TRUE; + max_service_execution_time = temp_servicestatus->execution_time; + } + + total_service_percent_change_a += + temp_servicestatus->percent_state_change; + if(have_min_service_percent_change_a == FALSE || + temp_servicestatus->percent_state_change < + min_service_percent_change_a) { + have_min_service_percent_change_a = TRUE; + min_service_percent_change_a = + temp_servicestatus->percent_state_change; + } + if(have_max_service_percent_change_a == FALSE || + temp_servicestatus->percent_state_change > + max_service_percent_change_a) { + have_max_service_percent_change_a = TRUE; + max_service_percent_change_a = + temp_servicestatus->percent_state_change; + } + + total_service_latency += temp_servicestatus->latency; + if(have_min_service_latency == FALSE || + temp_servicestatus->latency < min_service_latency) { + have_min_service_latency = TRUE; + min_service_latency = temp_servicestatus->latency; + } + if(have_max_service_latency == FALSE || + temp_servicestatus->latency > max_service_latency) { + have_max_service_latency = TRUE; + max_service_latency = temp_servicestatus->latency; + } + + if(temp_servicestatus->last_check >= (current_time - 60)) + active_service_checks_1min++; + if(temp_servicestatus->last_check >= (current_time - 300)) + active_service_checks_5min++; + if(temp_servicestatus->last_check >= (current_time - 900)) + active_service_checks_15min++; + if(temp_servicestatus->last_check >= (current_time - 3600)) + active_service_checks_1hour++; + if(temp_servicestatus->last_check >= program_start) + active_service_checks_start++; + if(temp_servicestatus->last_check != (time_t)0) + active_service_checks_ever++; + } + + else { + total_passive_service_checks++; + + total_service_percent_change_b += + temp_servicestatus->percent_state_change; + if(have_min_service_percent_change_b == FALSE || + temp_servicestatus->percent_state_change < + min_service_percent_change_b) { + have_min_service_percent_change_b = TRUE; + min_service_percent_change_b = + temp_servicestatus->percent_state_change; + } + if(have_max_service_percent_change_b == FALSE || + temp_servicestatus->percent_state_change > + max_service_percent_change_b) { + have_max_service_percent_change_b = TRUE; + max_service_percent_change_b = + temp_servicestatus->percent_state_change; + } + + if(temp_servicestatus->last_check >= (current_time - 60)) + passive_service_checks_1min++; + if(temp_servicestatus->last_check >= (current_time - 300)) + passive_service_checks_5min++; + if(temp_servicestatus->last_check >= (current_time - 900)) + passive_service_checks_15min++; + if(temp_servicestatus->last_check >= (current_time - 3600)) + passive_service_checks_1hour++; + if(temp_servicestatus->last_check >= program_start) + passive_service_checks_start++; + if(temp_servicestatus->last_check != (time_t)0) + passive_service_checks_ever++; + } + } + + /* check all hosts */ + for(temp_hoststatus = hoststatus_list; temp_hoststatus != NULL; + temp_hoststatus = temp_hoststatus->next) { + + /* find the host */ + temp_host = find_host(temp_hoststatus->host_name); + if(NULL == temp_host) { + continue; + } + + /* make sure the user has rights to view host information */ + if(FALSE == is_authorized_for_host(temp_host, ¤t_authdata)) { + continue; + } + + /* is this an active or passive check? */ + if(temp_hoststatus->check_type == HOST_CHECK_ACTIVE) { + + total_active_host_checks++; + + total_host_execution_time += temp_hoststatus->execution_time; + if(have_min_host_execution_time == FALSE || + temp_hoststatus->execution_time < min_host_execution_time) { + have_min_host_execution_time = TRUE; + min_host_execution_time = temp_hoststatus->execution_time; + } + if(have_max_host_execution_time == FALSE || + temp_hoststatus->execution_time > max_host_execution_time) { + have_max_host_execution_time = TRUE; + max_host_execution_time = temp_hoststatus->execution_time; + } + + total_host_percent_change_a += + temp_hoststatus->percent_state_change; + if(have_min_host_percent_change_a == FALSE || + temp_hoststatus->percent_state_change < + min_host_percent_change_a) { + have_min_host_percent_change_a = TRUE; + min_host_percent_change_a = + temp_hoststatus->percent_state_change; + } + if(have_max_host_percent_change_a == FALSE || + temp_hoststatus->percent_state_change > + max_host_percent_change_a) { + have_max_host_percent_change_a = TRUE; + max_host_percent_change_a = + temp_hoststatus->percent_state_change; + } + + total_host_latency += temp_hoststatus->latency; + if(have_min_host_latency == FALSE || + temp_hoststatus->latency < min_host_latency) { + have_min_host_latency = TRUE; + min_host_latency = temp_hoststatus->latency; + } + if(have_max_host_latency == FALSE || + temp_hoststatus->latency > max_host_latency) { + have_max_host_latency = TRUE; + max_host_latency = temp_hoststatus->latency; + } + + if(temp_hoststatus->last_check >= (current_time - 60)) + active_host_checks_1min++; + if(temp_hoststatus->last_check >= (current_time - 300)) + active_host_checks_5min++; + if(temp_hoststatus->last_check >= (current_time - 900)) + active_host_checks_15min++; + if(temp_hoststatus->last_check >= (current_time - 3600)) + active_host_checks_1hour++; + if(temp_hoststatus->last_check >= program_start) + active_host_checks_start++; + if(temp_hoststatus->last_check != (time_t)0) + active_host_checks_ever++; + } + + else { + total_passive_host_checks++; + + total_host_percent_change_b += temp_hoststatus->percent_state_change; + if(have_min_host_percent_change_b == FALSE || + temp_hoststatus->percent_state_change < + min_host_percent_change_b) { + have_min_host_percent_change_b = TRUE; + min_host_percent_change_b = + temp_hoststatus->percent_state_change; + } + if(have_max_host_percent_change_b == FALSE || + temp_hoststatus->percent_state_change > + max_host_percent_change_b) { + have_max_host_percent_change_b = TRUE; + max_host_percent_change_b = + temp_hoststatus->percent_state_change; + } + + if(temp_hoststatus->last_check >= (current_time - 60)) + passive_host_checks_1min++; + if(temp_hoststatus->last_check >= (current_time - 300)) + passive_host_checks_5min++; + if(temp_hoststatus->last_check >= (current_time - 900)) + passive_host_checks_15min++; + if(temp_hoststatus->last_check >= (current_time - 3600)) + passive_host_checks_1hour++; + if(temp_hoststatus->last_check >= program_start) + passive_host_checks_start++; + if(temp_hoststatus->last_check != (time_t)0) + passive_host_checks_ever++; + } + } + + /* Avoid divide by zero errors */ + if(0 == total_active_service_checks) { + total_active_service_checks = 1; + } + if(0 == total_passive_service_checks) { + total_passive_service_checks = 1; + } + if(0 == total_active_host_checks) { + total_active_host_checks = 1; + } + if(0 == total_passive_host_checks) { + total_passive_host_checks = 1; + } + + json_data = json_new_object(); + + json_programstatus = json_new_object(); + + json_service_checks = json_new_object(); + + /* Active Service Checks */ + + json_active = json_new_object(); + + json_checks = json_new_object(); + + json_object_append_integer(json_checks, "1min", active_service_checks_1min); + json_object_append_integer(json_checks, "5min", active_service_checks_5min); + json_object_append_integer(json_checks, "15min", active_service_checks_15min); + json_object_append_integer(json_checks, "1hour", active_service_checks_1hour); + json_object_append_integer(json_checks, "start", active_service_checks_start); + + json_object_append_object(json_active, "checks", json_checks); + + json_metrics = json_new_object(); + + json_temp = json_new_object(); + json_object_append_real(json_temp, "min", min_service_execution_time); + json_object_append_real(json_temp, "max", max_service_execution_time); + json_object_append_real(json_temp, "average", + (double)((double)total_service_execution_time / (double)total_active_service_checks)); + json_object_append_object(json_metrics, "check_execution_time", json_temp); + + json_temp = json_new_object(); + json_object_append_real(json_temp, "min", min_service_latency); + json_object_append_real(json_temp, "max", max_service_latency); + json_object_append_real(json_temp, "average", + (double)((double)total_service_latency / (double)total_active_service_checks)); + json_object_append_object(json_metrics, "check_latency", json_temp); + + json_temp = json_new_object(); + json_object_append_real(json_temp, "min", min_service_percent_change_a); + json_object_append_real(json_temp, "max", max_service_percent_change_a); + json_object_append_real(json_temp, "average", + (double)((double)total_service_percent_change_a / (double)total_active_service_checks)); + json_object_append_object(json_metrics, "percent_state_change", json_temp); + + json_object_append_object(json_active, "metrics", json_metrics); + + json_object_append_object(json_service_checks, "active", json_active); + + /* Passive Service Checks */ + + json_passive = json_new_object(); + + json_checks = json_new_object(); + json_object_append_integer(json_checks, "1min", passive_service_checks_1min); + json_object_append_integer(json_checks, "5min", passive_service_checks_5min); + json_object_append_integer(json_checks, "15min", + passive_service_checks_15min); + json_object_append_integer(json_checks, "1hour", + passive_service_checks_1hour); + json_object_append_integer(json_checks, "start", + passive_service_checks_start); + json_object_append_object(json_passive, "checks", json_checks); + + json_metrics = json_new_object(); + + json_temp = json_new_object(); + json_object_append_real(json_temp, "min", min_service_percent_change_b); + json_object_append_real(json_temp, "max", max_service_percent_change_b); + json_object_append_real(json_temp, "average", + (double)((double)total_service_percent_change_b / (double)total_active_service_checks)); + json_object_append_object(json_metrics, "percent_state_change", json_temp); + + json_object_append_object(json_passive, "metrics", json_metrics); + + json_object_append_object(json_service_checks, "passive", json_passive); + + json_object_append_object(json_programstatus, "service_checks", + json_service_checks); + + json_host_checks = json_new_object(); + + /* Active Host Checks */ + + json_active = json_new_object(); + + json_checks = json_new_object(); + json_object_append_integer(json_checks, "1min", active_host_checks_1min); + json_object_append_integer(json_checks, "5min", active_host_checks_5min); + json_object_append_integer(json_checks, "15min", active_host_checks_15min); + json_object_append_integer(json_checks, "1hour", active_host_checks_1hour); + json_object_append_integer(json_checks, "start", active_host_checks_start); + json_object_append_object(json_active, "checks", json_checks); + + json_metrics = json_new_object(); + + json_temp = json_new_object(); + json_object_append_real(json_temp, "min", min_host_execution_time); + json_object_append_real(json_temp, "max", max_host_execution_time); + json_object_append_real(json_temp, "average", + (double)((double)total_host_execution_time / (double)total_active_host_checks)); + json_object_append_object(json_metrics, "check_execution_time", json_temp); + + json_temp = json_new_object(); + json_object_append_real(json_temp, "min", min_host_latency); + json_object_append_real(json_temp, "max", max_host_latency); + json_object_append_real(json_temp, "average", + (double)((double)total_host_latency / (double)total_active_host_checks)); + json_object_append_object(json_metrics, "check_latency", json_temp); + + json_temp = json_new_object(); + json_object_append_real(json_temp, "min", min_host_percent_change_a); + json_object_append_real(json_temp, "max", max_host_percent_change_a); + json_object_append_real(json_temp, "average", + (double)((double)total_host_percent_change_a / (double)total_active_host_checks)); + json_object_append_object(json_metrics, "percent_state_change", json_temp); + + json_object_append_object(json_active, "metrics", json_metrics); + + json_object_append_object(json_host_checks, "active", json_active); + + /* Passive Host Checks */ + + json_passive = json_new_object(); + + json_checks = json_new_object(); + json_object_append_integer(json_checks, "1min", passive_host_checks_1min); + json_object_append_integer(json_checks, "5min", passive_host_checks_5min); + json_object_append_integer(json_checks, "15min", passive_host_checks_15min); + json_object_append_integer(json_checks, "1hour", passive_host_checks_1hour); + json_object_append_integer(json_checks, "start", passive_host_checks_start); + json_object_append_object(json_passive, "checks", json_checks); + + json_metrics = json_new_object(); + + json_temp = json_new_object(); + json_object_append_real(json_temp, "min", min_host_percent_change_b); + json_object_append_real(json_temp, "max", max_host_percent_change_b); + json_object_append_real(json_temp, "average", + (double)((double)total_host_percent_change_b / (double)total_active_host_checks)); + json_object_append_object(json_metrics, "percent_state_change", json_temp); + + json_object_append_object(json_passive, "metrics", json_metrics); + + json_object_append_object(json_host_checks, "passive", json_passive); + + json_object_append_object(json_programstatus, "host_checks", + json_host_checks); + + /* Check Stats */ + + json_check_statistics = json_new_object(); + + json_temp = json_new_object(); + json_object_append_integer(json_temp, "1min", + program_stats[ACTIVE_SCHEDULED_HOST_CHECK_STATS][0]); + json_object_append_integer(json_temp, "5min", + program_stats[ACTIVE_SCHEDULED_HOST_CHECK_STATS][1]); + json_object_append_integer(json_temp, "15min", + program_stats[ACTIVE_SCHEDULED_HOST_CHECK_STATS][2]); + json_object_append_object(json_check_statistics, + "active_scheduled_host_checks", json_temp); + + json_temp = json_new_object(); + json_object_append_integer(json_temp, "1min", + program_stats[ACTIVE_ONDEMAND_HOST_CHECK_STATS][0]); + json_object_append_integer(json_temp, "5min", + program_stats[ACTIVE_ONDEMAND_HOST_CHECK_STATS][1]); + json_object_append_integer(json_temp, "15min", + program_stats[ACTIVE_ONDEMAND_HOST_CHECK_STATS][2]); + json_object_append_object(json_check_statistics, + "active_ondemand_host_checks", json_temp); + + json_temp = json_new_object(); + json_object_append_integer(json_temp, "1min", + program_stats[PARALLEL_HOST_CHECK_STATS][0]); + json_object_append_integer(json_temp, "5min", + program_stats[PARALLEL_HOST_CHECK_STATS][1]); + json_object_append_integer(json_temp, "15min", + program_stats[PARALLEL_HOST_CHECK_STATS][2]); + json_object_append_object(json_check_statistics, + "parallel_host_checks", json_temp); + + json_temp = json_new_object(); + json_object_append_integer(json_temp, "1min", + program_stats[SERIAL_HOST_CHECK_STATS][0]); + json_object_append_integer(json_temp, "5min", + program_stats[SERIAL_HOST_CHECK_STATS][1]); + json_object_append_integer(json_temp, "15min", + program_stats[SERIAL_HOST_CHECK_STATS][2]); + json_object_append_object(json_check_statistics, + "serial_host_checks", json_temp); + + json_temp = json_new_object(); + json_object_append_integer(json_temp, "1min", + program_stats[ACTIVE_CACHED_HOST_CHECK_STATS][0]); + json_object_append_integer(json_temp, "5min", + program_stats[ACTIVE_CACHED_HOST_CHECK_STATS][1]); + json_object_append_integer(json_temp, "15min", + program_stats[ACTIVE_CACHED_HOST_CHECK_STATS][2]); + json_object_append_object(json_check_statistics, + "cached_host_checks", json_temp); + + json_temp = json_new_object(); + json_object_append_integer(json_temp, "1min", + program_stats[PASSIVE_HOST_CHECK_STATS][0]); + json_object_append_integer(json_temp, "5min", + program_stats[PASSIVE_HOST_CHECK_STATS][1]); + json_object_append_integer(json_temp, "15min", + program_stats[PASSIVE_HOST_CHECK_STATS][2]); + json_object_append_object(json_check_statistics, + "passive_host_checks", json_temp); + + json_temp = json_new_object(); + json_object_append_integer(json_temp, "1min", + program_stats[ACTIVE_SCHEDULED_SERVICE_CHECK_STATS][0]); + json_object_append_integer(json_temp, "5min", + program_stats[ACTIVE_SCHEDULED_SERVICE_CHECK_STATS][1]); + json_object_append_integer(json_temp, "15min", + program_stats[ACTIVE_SCHEDULED_SERVICE_CHECK_STATS][2]); + json_object_append_object(json_check_statistics, + "active_scheduled_service_checks", json_temp); + + json_temp = json_new_object(); + json_object_append_integer(json_temp, "1min", + program_stats[ACTIVE_ONDEMAND_SERVICE_CHECK_STATS][0]); + json_object_append_integer(json_temp, "5min", + program_stats[ACTIVE_ONDEMAND_SERVICE_CHECK_STATS][1]); + json_object_append_integer(json_temp, "15min", + program_stats[ACTIVE_ONDEMAND_SERVICE_CHECK_STATS][2]); + json_object_append_object(json_check_statistics, + "active_ondemand_service_checks", json_temp); + + json_temp = json_new_object(); + json_object_append_integer(json_temp, "1min", + program_stats[ACTIVE_CACHED_SERVICE_CHECK_STATS][0]); + json_object_append_integer(json_temp, "5min", + program_stats[ACTIVE_CACHED_SERVICE_CHECK_STATS][1]); + json_object_append_integer(json_temp, "15min", + program_stats[ACTIVE_CACHED_SERVICE_CHECK_STATS][2]); + json_object_append_object(json_check_statistics, + "cached_service_checks", json_temp); + + json_temp = json_new_object(); + json_object_append_integer(json_temp, "1min", + program_stats[PASSIVE_SERVICE_CHECK_STATS][0]); + json_object_append_integer(json_temp, "5min", + program_stats[PASSIVE_SERVICE_CHECK_STATS][1]); + json_object_append_integer(json_temp, "15min", + program_stats[PASSIVE_SERVICE_CHECK_STATS][2]); + json_object_append_object(json_check_statistics, + "passive_service_checks", json_temp); + + json_temp = json_new_object(); + json_object_append_integer(json_temp, "1min", + program_stats[EXTERNAL_COMMAND_STATS][0]); + json_object_append_integer(json_temp, "5min", + program_stats[EXTERNAL_COMMAND_STATS][1]); + json_object_append_integer(json_temp, "15min", + program_stats[EXTERNAL_COMMAND_STATS][2]); + json_object_append_object(json_check_statistics, + "external_commands", json_temp); + + json_object_append_object(json_programstatus, "check_statistics", + json_check_statistics); + + /* Buffer Stats */ + + json_buffer_usage = json_new_object(); + + json_temp = json_new_object(); + json_object_append_integer(json_temp, "in_use", buffer_stats[0][1]); + json_object_append_integer(json_temp, "max_used", buffer_stats[0][2]); + json_object_append_integer(json_temp, "total_available", buffer_stats[0][0]); + json_object_append_object(json_buffer_usage, "external_commands", json_temp); + + json_object_append_object(json_programstatus, "buffer_usage", + json_buffer_usage); + + json_object_append_object(json_data, "programstatus", json_programstatus); + + return json_data; + } diff --git a/cgi/statusmap.c b/cgi/statusmap.c index 72f1cf3..9ffe533 100644 --- a/cgi/statusmap.c +++ b/cgi/statusmap.c @@ -2,8 +2,6 @@ * * STATUSMAP.C - Nagios Network Status Map CGI * - * Copyright (c) 1999-2008 Ethan Galstad (egalstad@nagios.org) - * Last Modified: 05-19-2008 * * Description: * @@ -55,10 +53,8 @@ extern char physical_images_path[MAX_FILENAME_LENGTH]; extern char url_images_path[MAX_FILENAME_LENGTH]; extern char url_logo_images_path[MAX_FILENAME_LENGTH]; extern char url_stylesheets_path[MAX_FILENAME_LENGTH]; +extern char *status_file; -extern host *host_list; -extern hostgroup *hostgroup_list; -extern service *service_list; extern hoststatus *hoststatus_list; extern servicestatus *servicestatus_list; @@ -95,10 +91,10 @@ extern int default_statusmap_layout_method; #define LAYOUT_CIRCULAR_BALLOON 6 -typedef struct layer_struct { +struct layer { char *layer_name; - struct layer_struct *next; - } layer; + struct layer *next; +}; void document_header(int); @@ -222,9 +218,7 @@ int nagios_icon_y = 0; extern hoststatus *hoststatus_list; -extern time_t program_start; - -layer *layer_list = NULL; +struct layer *layer_list = NULL; int exclude_layers = TRUE; int all_layers = FALSE; @@ -240,6 +234,9 @@ int main(int argc, char **argv) { /* reset internal variables */ reset_cgi_vars(); + /* Initialize shared configuration variables */ + init_shared_cfg_vars(1); + /* read the CGI configuration file */ result = read_cgi_config_file(get_cgi_config_location()); if(result == ERROR) { @@ -277,7 +274,7 @@ int main(int argc, char **argv) { } /* read all status data */ - result = read_all_status_data(get_cgi_config_location(), READ_ALL_STATUS_DATA); + result = read_all_status_data(status_file, READ_ALL_STATUS_DATA); if(result == ERROR) { document_header(FALSE); if(create_type == CREATE_HTML) @@ -328,7 +325,7 @@ void document_header(int use_stylesheet) { get_time_string(&expire_time, date_time, sizeof(date_time), HTTP_DATE_TIME); printf("Expires: %s\r\n", date_time); - printf("Content-Type: text/html\r\n\r\n"); + printf("Content-Type: text/html; charset=utf-8\r\n\r\n"); if(embedded == TRUE) return; @@ -353,7 +350,11 @@ void document_header(int use_stylesheet) { printf("\n"); /* include user SSI header */ +#ifdef LEGACY_GRAPHICAL_CGIS include_ssi_files(STATUSMAP_CGI, SSI_HEADER); +#else + include_ssi_files(LEGACY_STATUSMAP_CGI, SSI_HEADER); +#endif printf("
\n"); } @@ -385,7 +386,11 @@ void document_footer(void) { if(create_type == CREATE_HTML) { /* include user SSI footer */ +#ifdef LEGACY_GRAPHICAL_CGIS include_ssi_files(STATUSMAP_CGI, SSI_FOOTER); +#else + include_ssi_files(LEGACY_STATUSMAP_CGI, SSI_FOOTER); +#endif printf("\n"); printf("\n"); @@ -407,7 +412,6 @@ int process_cgivars(void) { /* do some basic length checking on the variable identifier to prevent buffer overflows */ if(strlen(variables[x]) >= MAX_INPUT_BUFFER - 1) { - x++; continue; } @@ -603,7 +607,7 @@ void display_page_header(void) { int zoom_height_granularity = 0; int current_zoom_granularity = 0; hostgroup *temp_hostgroup; - layer *temp_layer; + struct layer *temp_layer; int found = 0; @@ -630,7 +634,11 @@ void display_page_header(void) { printf("
%d Unhandled
%d Unhandled
%d on Problem Hosts
%d on Problem Hosts
%d Scheduled
\n"); +#ifdef LEGACY_GRAPHICAL_CGIS printf("\n", STATUSMAP_CGI); +#else + printf("\n", LEGACY_STATUSMAP_CGI); +#endif printf("\n"); printf("
\n"); printf("\n", escape_string(host_name)); @@ -843,7 +859,11 @@ void display_map(void) { /* write the URL location for the image we just generated - the web browser will come and get it... */ if(create_type == CREATE_HTML) { printf("

\n"); - printf("\n", (int)(canvas_width * scaling_factor), (int)(canvas_height * scaling_factor)); @@ -1249,13 +1269,13 @@ void calculate_canvas_bounds(void) { /* calculates canvas coordinates/dimensions around a particular host */ -void calculate_canvas_bounds_from_host(char *host_name) { +void calculate_canvas_bounds_from_host(char *hname) { host *temp_host; int zoom_width; int zoom_height; /* find the extended host info */ - temp_host = find_host(host_name); + temp_host = find_host(hname); if(temp_host == NULL) return; @@ -1480,7 +1500,7 @@ void draw_host_links(void) { /* determine color to use when drawing links to children */ this_hoststatus = find_hoststatus(this_host->name); if(this_hoststatus != NULL) { - if(this_hoststatus->status == HOST_DOWN || this_hoststatus->status == HOST_UNREACHABLE) + if(this_hoststatus->status == SD_HOST_DOWN || this_hoststatus->status == SD_HOST_UNREACHABLE) status_color = color_red; else status_color = color_black; @@ -1545,7 +1565,7 @@ void draw_host_links(void) { /* determine color to use when drawing links to parent host */ parent_hoststatus = find_hoststatus(parent_host->name); if(parent_hoststatus != NULL) { - if(parent_hoststatus->status == HOST_DOWN || parent_hoststatus->status == HOST_UNREACHABLE) + if(parent_hoststatus->status == SD_HOST_DOWN || parent_hoststatus->status == SD_HOST_UNREACHABLE) status_color = color_red; else status_color = color_black; @@ -1571,7 +1591,7 @@ void draw_host_links(void) { void draw_hosts(void) { host *temp_host; int x1, x2; - int y1, y2; + int y1; int has_image = FALSE; char image_input_file[MAX_INPUT_BUFFER]; int current_radius = 0; @@ -1607,7 +1627,6 @@ void draw_hosts(void) { x1 = nagios_icon_x - canvas_x; x2 = x1 + DEFAULT_NODE_WIDTH; y1 = nagios_icon_y - canvas_y; - y2 = y1 + DEFAULT_NODE_HEIGHT; /* get the name of the image file to open for the logo */ snprintf(image_input_file, sizeof(image_input_file) - 1, "%s%s", physical_logo_images_path, NAGIOS_GD2_ICON); @@ -1653,18 +1672,17 @@ void draw_hosts(void) { x1 = temp_host->x_2d - canvas_x; x2 = x1 + DEFAULT_NODE_WIDTH; y1 = temp_host->y_2d - canvas_y; - y2 = y1 + DEFAULT_NODE_HEIGHT; if(create_type == CREATE_IMAGE) { temp_hoststatus = find_hoststatus(temp_host->name); if(temp_hoststatus != NULL) { - if(temp_hoststatus->status == HOST_DOWN) + if(temp_hoststatus->status == SD_HOST_DOWN) status_color = color_red; - else if(temp_hoststatus->status == HOST_UNREACHABLE) + else if(temp_hoststatus->status == SD_HOST_UNREACHABLE) status_color = color_red; - else if(temp_hoststatus->status == HOST_UP) + else if(temp_hoststatus->status == SD_HOST_UP) status_color = color_green; else if(temp_hoststatus->status == HOST_PENDING) status_color = color_grey; @@ -1699,7 +1717,7 @@ void draw_hosts(void) { /* calculate width of border */ if(temp_hoststatus == NULL) inner_radius = outer_radius; - else if((temp_hoststatus->status == HOST_DOWN || temp_hoststatus->status == HOST_UNREACHABLE) && temp_hoststatus->problem_has_been_acknowledged == FALSE) + else if((temp_hoststatus->status == SD_HOST_DOWN || temp_hoststatus->status == SD_HOST_UNREACHABLE) && temp_hoststatus->problem_has_been_acknowledged == FALSE) inner_radius = outer_radius - 3; else inner_radius = outer_radius; @@ -1813,7 +1831,11 @@ void draw_hosts(void) { if(!strcmp(host_name, temp_host->name)) printf("href='%s?host=%s' ", STATUS_CGI, url_encode(temp_host->name)); else { +#ifdef LEGACY_GRAPHICAL_CGIS printf("href='%s?host=%s&layout=%d&max_width=%d&max_height=%d&proximity_width=%d&proximity_height=%d%s%s%s%s%s", STATUSMAP_CGI, url_encode(temp_host->name), layout_method, max_image_width, max_image_height, proximity_width, proximity_height, (display_header == TRUE) ? "" : "&noheader", (use_links == FALSE) ? "&nolinks" : "", (use_text == FALSE) ? "¬ext" : "", (use_highlights == FALSE) ? "&nohighlights" : "", (display_popups == FALSE) ? "&nopopups" : ""); +#else + printf("href='%s?host=%s&layout=%d&max_width=%d&max_height=%d&proximity_width=%d&proximity_height=%d%s%s%s%s%s", LEGACY_STATUSMAP_CGI, url_encode(temp_host->name), layout_method, max_image_width, max_image_height, proximity_width, proximity_height, (display_header == TRUE) ? "" : "&noheader", (use_links == FALSE) ? "&nolinks" : "", (use_text == FALSE) ? "¬ext" : "", (use_highlights == FALSE) ? "&nohighlights" : "", (display_popups == FALSE) ? "&nopopups" : ""); +#endif if(user_supplied_scaling == TRUE) printf("&scaling_factor=%2.1f", user_scaling_factor); print_layer_url(TRUE); @@ -1875,15 +1897,15 @@ void draw_host_text(char *name, int x, int y) { if(temp_hoststatus != NULL) { /* draw the status string */ - if(temp_hoststatus->status == HOST_DOWN) { + if(temp_hoststatus->status == SD_HOST_DOWN) { strncpy(temp_buffer, "Down", sizeof(temp_buffer)); status_color = color_red; } - else if(temp_hoststatus->status == HOST_UNREACHABLE) { + else if(temp_hoststatus->status == SD_HOST_UNREACHABLE) { strncpy(temp_buffer, "Unreachable", sizeof(temp_buffer)); status_color = color_red; } - else if(temp_hoststatus->status == HOST_UP) { + else if(temp_hoststatus->status == SD_HOST_UP) { strncpy(temp_buffer, "Up", sizeof(temp_buffer)); status_color = color_green; } @@ -1958,21 +1980,21 @@ void write_host_popup_text(host *hst) { printf("
State:"); /* get the status of the host (pending, up, down, or unreachable) */ - if(temp_status->status == HOST_DOWN) { + if(temp_status->status == SD_HOST_DOWN) { printf("Down"); if(temp_status->problem_has_been_acknowledged == TRUE) printf(" (Acknowledged)"); printf(""); } - else if(temp_status->status == HOST_UNREACHABLE) { + else if(temp_status->status == SD_HOST_UNREACHABLE) { printf("Unreachable"); if(temp_status->problem_has_been_acknowledged == TRUE) printf(" (Acknowledged)"); printf(""); } - else if(temp_status->status == HOST_UP) + else if(temp_status->status == SD_HOST_UP) printf("Up"); else if(temp_status->status == HOST_PENDING) @@ -2333,13 +2355,13 @@ void write_popup_code(void) { /* adds a layer to the list in memory */ int add_layer(char *group_name) { - layer *new_layer; + struct layer *new_layer; if(group_name == NULL) return ERROR; /* allocate memory for a new layer */ - new_layer = (layer *)malloc(sizeof(layer)); + new_layer = (struct layer *)malloc(sizeof(struct layer)); if(new_layer == NULL) return ERROR; @@ -2362,8 +2384,7 @@ int add_layer(char *group_name) { /* frees memory allocated to the layer list */ void free_layer_list(void) { - layer *this_layer; - layer *next_layer; + struct layer *this_layer, *next_layer; return; @@ -2380,7 +2401,7 @@ void free_layer_list(void) { /* checks to see if a host is in the layer list */ int is_host_in_layer_list(host *hst) { hostgroup *temp_hostgroup; - layer *temp_layer; + struct layer *temp_layer; if(hst == NULL) return FALSE; @@ -2404,7 +2425,7 @@ int is_host_in_layer_list(host *hst) { /* print layer url info */ void print_layer_url(int get_method) { - layer *temp_layer; + struct layer *temp_layer; for(temp_layer = layer_list; temp_layer != NULL; temp_layer = temp_layer->next) { if(get_method == TRUE) @@ -2650,7 +2671,6 @@ void calculate_circular_layer_coords(host *parent, double start_angle, double us double this_drawing_angle = 0.0; double available_angle = 0.0; double clipped_available_angle = 0.0; - double average_child_angle = 0.0; double x_coord = 0.0; double y_coord = 0.0; host *temp_host; @@ -2666,9 +2686,6 @@ void calculate_circular_layer_coords(host *parent, double start_angle, double us /* calculate total drawing "width" of parent host */ parent_drawing_width = max_child_host_drawing_width(parent); - /* calculate average angle given to each child host */ - average_child_angle = (double)(useable_angle / (double)immediate_children); - /* calculate initial drawing angle */ current_drawing_angle = start_angle; @@ -2739,7 +2756,6 @@ void draw_circular_layer_markup(host *parent, double start_angle, double useable double current_drawing_angle = 0.0; double available_angle = 0.0; double clipped_available_angle = 0.0; - double average_child_angle = 0.0; double x_coord[4] = {0.0, 0.0, 0.0, 0.0}; double y_coord[4] = {0.0, 0.0, 0.0, 0.0}; hoststatus *temp_hoststatus; @@ -2764,9 +2780,6 @@ void draw_circular_layer_markup(host *parent, double start_angle, double useable /* calculate total drawing "width" of parent host */ parent_drawing_width = max_child_host_drawing_width(parent); - /* calculate average angle given to each child host */ - average_child_angle = (double)(useable_angle / (double)immediate_children); - /* calculate initial drawing angle */ current_drawing_angle = start_angle; @@ -2836,7 +2849,7 @@ void draw_circular_layer_markup(host *parent, double start_angle, double useable temp_hoststatus = find_hoststatus(temp_host->name); if(temp_hoststatus == NULL) bgcolor = color_lightgrey; - else if(temp_hoststatus->status == HOST_DOWN || temp_hoststatus->status == HOST_UNREACHABLE) + else if(temp_hoststatus->status == SD_HOST_DOWN || temp_hoststatus->status == SD_HOST_UNREACHABLE) bgcolor = color_lightred; else bgcolor = color_lightgreen; @@ -2856,4 +2869,3 @@ void draw_circular_layer_markup(host *parent, double start_angle, double useable return; } - diff --git a/cgi/statuswml.c b/cgi/statuswml.c index 2d608f0..f54f737 100644 --- a/cgi/statuswml.c +++ b/cgi/statuswml.c @@ -2,8 +2,6 @@ * * STATUSWML.C - Nagios Status CGI for WAP-enabled devices * - * Copyright (c) 2001-2008 Ethan Galstad (egalstad@nagios.org) - * Last Modified: 10-15-2008 * * License: * @@ -30,19 +28,13 @@ #include "../include/getcgi.h" #include "../include/cgiauth.h" -extern time_t program_start; - extern char main_config_file[MAX_FILENAME_LENGTH]; +extern char *status_file; -extern host *host_list; -extern hostgroup *hostgroup_list; -extern service *service_list; extern hoststatus *hoststatus_list; extern servicestatus *servicestatus_list; extern int use_ssl_authentication; -extern int enable_notifications; -extern int execute_service_checks; extern int nagios_process_state; extern char *ping_syntax; @@ -108,6 +100,9 @@ int main(void) { /* reset internal variables */ reset_cgi_vars(); + /* Initialize shared configuration variables */ + init_shared_cfg_vars(1); + document_header(); /* validate arguments in URL */ @@ -142,7 +137,7 @@ int main(void) { } /* read all status data */ - result = read_all_status_data(get_cgi_config_location(), READ_ALL_STATUS_DATA); + result = read_all_status_data(status_file, READ_ALL_STATUS_DATA); if(result == ERROR) { printf("

Error: Could not read host and service status information!

\n"); document_footer(); @@ -235,8 +230,13 @@ int process_cgivars(void) { for(x = 0; variables[x] != NULL; x++) { + /* do some basic length checking on the variable identifier to prevent buffer overflows */ + if(strlen(variables[x]) >= MAX_INPUT_BUFFER - 1) { + continue; + } + /* we found the hostgroup argument */ - if(!strcmp(variables[x], "hostgroup")) { + else if(!strcmp(variables[x], "hostgroup")) { display_type = DISPLAY_HOSTGROUP; x++; if(variables[x] == NULL) { @@ -564,9 +564,9 @@ void display_quick_stats(void) { if(temp_hoststatus == NULL) continue; - if(temp_hoststatus->status == HOST_UNREACHABLE) + if(temp_hoststatus->status == SD_HOST_UNREACHABLE) hosts_unreachable++; - else if(temp_hoststatus->status == HOST_DOWN) + else if(temp_hoststatus->status == SD_HOST_DOWN) hosts_down++; else if(temp_hoststatus->status == HOST_PENDING) hosts_pending++; @@ -664,13 +664,13 @@ void display_hostgroup_overview(void) { continue; printf("
", temp_host->name); - if(temp_hoststatus->status == HOST_UP) + if(temp_hoststatus->status == SD_HOST_UP) printf("UP"); else if(temp_hoststatus->status == HOST_PENDING) printf("PND"); - else if(temp_hoststatus->status == HOST_DOWN) + else if(temp_hoststatus->status == SD_HOST_DOWN) printf("DWN"); - else if(temp_hoststatus->status == HOST_UNREACHABLE) + else if(temp_hoststatus->status == SD_HOST_UNREACHABLE) printf("UNR"); else printf("???"); @@ -757,9 +757,9 @@ void display_hostgroup_summary(void) { if(temp_hoststatus == NULL) continue; - if(temp_hoststatus->status == HOST_UNREACHABLE) + if(temp_hoststatus->status == SD_HOST_UNREACHABLE) hosts_unreachable++; - else if(temp_hoststatus->status == HOST_DOWN) + else if(temp_hoststatus->status == SD_HOST_DOWN) hosts_down++; else if(temp_hoststatus->status == HOST_PENDING) hosts_pending++; @@ -889,13 +889,13 @@ void display_host(void) { printf("\n"); printf("
Status:"); - if(temp_hoststatus->status == HOST_UP) + if(temp_hoststatus->status == SD_HOST_UP) printf("UP"); else if(temp_hoststatus->status == HOST_PENDING) printf("PENDING"); - else if(temp_hoststatus->status == HOST_DOWN) + else if(temp_hoststatus->status == SD_HOST_DOWN) printf("DOWN"); - else if(temp_hoststatus->status == HOST_UNREACHABLE) + else if(temp_hoststatus->status == SD_HOST_UNREACHABLE) printf("UNREACHABLE"); else printf("?"); @@ -954,7 +954,7 @@ void display_host(void) { printf("Ping Host\n", STATUSWML_CGI, temp_host->address); printf("Traceroute\n", STATUSWML_CGI, temp_host->address); - if(temp_hoststatus->status != HOST_UP && temp_hoststatus->status != HOST_PENDING) + if(temp_hoststatus->status != SD_HOST_UP && temp_hoststatus->status != HOST_PENDING) printf("Acknowledge Problem\n"); if(temp_hoststatus->checks_enabled == FALSE) @@ -1180,7 +1180,7 @@ void display_service(void) { printf("
\n", escape_string(service_desc), CMD_DISABLE_SVC_CHECK, CMDMODE_COMMIT); printf("Schedule Immediate Check", COMMAND_CGI, escape_string(host_name)); - printf("
\n", escape_string(service_desc), (unsigned long)current_time, CMD_SCHEDULE_SVC_CHECK, CMDMODE_COMMIT); + printf("
\n", escape_string(service_desc), (unsigned long long)current_time, CMD_SCHEDULE_SVC_CHECK, CMDMODE_COMMIT); } if(temp_servicestatus->notifications_enabled == FALSE) { @@ -1419,7 +1419,7 @@ void display_problems(void) { if(is_authorized_for_host(temp_host, ¤t_authdata) == FALSE) continue; - if(temp_hoststatus->status == HOST_UP || temp_hoststatus->status == HOST_PENDING) + if(temp_hoststatus->status == SD_HOST_UP || temp_hoststatus->status == HOST_PENDING) continue; if(display_type == DISPLAY_UNHANDLED_PROBLEMS) { @@ -1434,9 +1434,9 @@ void display_problems(void) { total_host_problems++; printf("
", temp_host->name); - if(temp_hoststatus->status == HOST_DOWN) + if(temp_hoststatus->status == SD_HOST_DOWN) printf("DWN"); - else if(temp_hoststatus->status == HOST_UNREACHABLE) + else if(temp_hoststatus->status == SD_HOST_UNREACHABLE) printf("UNR"); else printf("???"); @@ -1510,6 +1510,3 @@ void display_problems(void) { return; } - - - diff --git a/cgi/statuswrl.c b/cgi/statuswrl.c index 6e5ef2b..8220c05 100644 --- a/cgi/statuswrl.c +++ b/cgi/statuswrl.c @@ -2,8 +2,6 @@ * * STATUSWRL.C - Nagios 3-D (VRML) Network Status View * - * Copyright (c) 1999-2007 Ethan Galstad (egalstad@nagios.org) - * Last Modified: 07-16-2007 * * Description: * @@ -40,12 +38,10 @@ extern char main_config_file[MAX_FILENAME_LENGTH]; extern char url_html_path[MAX_FILENAME_LENGTH]; extern char url_images_path[MAX_FILENAME_LENGTH]; extern char url_logo_images_path[MAX_FILENAME_LENGTH]; +extern char *status_file; extern char *statuswrl_include; -extern host *host_list; -extern service *service_list; - extern int default_statuswrl_layout_method; @@ -139,6 +135,9 @@ int main(int argc, char **argv) { /* reset internal variables */ reset_cgi_vars(); + /* Initialize shared configuration variables */ + init_shared_cfg_vars(1); + /* read the CGI configuration file */ result = read_cgi_config_file(get_cgi_config_location()); if(result == ERROR) { @@ -165,7 +164,7 @@ int main(int argc, char **argv) { return ERROR; /* read all status data */ - result = read_all_status_data(get_cgi_config_location(), READ_ALL_STATUS_DATA); + result = read_all_status_data(status_file, READ_ALL_STATUS_DATA); if(result == ERROR) { free_memory(); return ERROR; @@ -950,7 +949,7 @@ void draw_host(host *temp_host) { printf("material DEF HostMat%s Material{\n", vrml_safe_hostname); if(temp_hoststatus == NULL) printf("emissiveColor 0.2 0.2 0.2\ndiffuseColor 0.2 0.2 0.2\n"); - else if(temp_hoststatus->status == HOST_UP) + else if(temp_hoststatus->status == SD_HOST_UP) printf("emissiveColor 0.2 1.0 0.2\ndiffuseColor 0.2 1.0 0.2\n"); else printf("emissiveColor 1.0 0.2 0.2\ndiffuseColor 1.0 0.2 0.2\n"); @@ -986,18 +985,18 @@ void draw_host(host *temp_host) { printf("HostText{\n"); if(temp_hoststatus != NULL) { - if(temp_hoststatus->status == HOST_UP) + if(temp_hoststatus->status == SD_HOST_UP) printf("font_color 0 1 0\n"); - else if(temp_hoststatus->status == HOST_DOWN || temp_hoststatus->status == HOST_UNREACHABLE) + else if(temp_hoststatus->status == SD_HOST_DOWN || temp_hoststatus->status == SD_HOST_UNREACHABLE) printf("font_color 1 0 0\n"); } printf("the_text [\"%s\", \"%s\", ", temp_host->name, temp_host->alias); if(temp_hoststatus == NULL) strcpy(state_string, "UNKNOWN"); else { - if(temp_hoststatus->status == HOST_DOWN) + if(temp_hoststatus->status == SD_HOST_DOWN) strcpy(state_string, "DOWN"); - else if(temp_hoststatus->status == HOST_UNREACHABLE) + else if(temp_hoststatus->status == SD_HOST_UNREACHABLE) strcpy(state_string, "UNREACHABLE"); else if(temp_hoststatus->status == HOST_PENDING) strcpy(state_string, "PENDING"); @@ -1012,7 +1011,7 @@ void draw_host(host *temp_host) { } /* host is down or unreachable, so make it fade in and out */ - if(temp_hoststatus != NULL && (temp_hoststatus->status == HOST_DOWN || temp_hoststatus->status == HOST_UNREACHABLE)) + if(temp_hoststatus != NULL && (temp_hoststatus->status == SD_HOST_DOWN || temp_hoststatus->status == SD_HOST_UNREACHABLE)) printf("ROUTE ProblemTimer.fraction_changed TO HostMat%s.set_transparency\n", vrml_safe_hostname); free(vrml_safe_hostname); @@ -1229,7 +1228,6 @@ void calculate_circular_layer_coords(host *parent, double start_angle, double us double this_drawing_angle = 0.0; double available_angle = 0.0; double clipped_available_angle = 0.0; - double average_child_angle = 0.0; double x_coord = 0.0; double y_coord = 0.0; host *temp_host; @@ -1245,9 +1243,6 @@ void calculate_circular_layer_coords(host *parent, double start_angle, double us /* calculate total drawing "width" of parent host */ parent_drawing_width = max_child_host_drawing_width(parent); - /* calculate average angle given to each child host */ - average_child_angle = (double)(useable_angle / (double)immediate_children); - /* calculate initial drawing angle */ current_drawing_angle = start_angle; @@ -1297,5 +1292,3 @@ void calculate_circular_layer_coords(host *parent, double start_angle, double us return; } - - diff --git a/cgi/summary.c b/cgi/summary.c index 810b1af..33f8342 100644 --- a/cgi/summary.c +++ b/cgi/summary.c @@ -2,8 +2,6 @@ * * SUMMARY.C - Nagios Alert Summary CGI * - * Copyright (c) 2002-2008 Ethan Galstad (egalstad@nagios.org) - * Last Modified: 01-23-2008 * * License: * @@ -37,14 +35,6 @@ extern char url_html_path[MAX_FILENAME_LENGTH]; extern char url_images_path[MAX_FILENAME_LENGTH]; extern char url_stylesheets_path[MAX_FILENAME_LENGTH]; -extern host *host_list; -extern hostgroup *hostgroup_list; -extern service *service_list; -extern servicegroup *servicegroup_list; - -extern int log_rotation_method; - - /* output types */ #define HTML_OUTPUT 0 #define CSV_OUTPUT 1 @@ -205,7 +195,6 @@ int generate_report = FALSE; int main(int argc, char **argv) { - int result = OK; char temp_buffer[MAX_INPUT_BUFFER]; char start_timestring[MAX_DATETIME_LENGTH]; char end_timestring[MAX_DATETIME_LENGTH]; @@ -221,32 +210,7 @@ int main(int argc, char **argv) { /* reset internal CGI variables */ reset_cgi_vars(); - /* read the CGI configuration file */ - result = read_cgi_config_file(get_cgi_config_location()); - if(result == ERROR) { - document_header(FALSE); - cgi_config_file_error(get_cgi_config_location()); - document_footer(); - return ERROR; - } - - /* read the main configuration file */ - result = read_main_config_file(main_config_file); - if(result == ERROR) { - document_header(FALSE); - main_config_file_error(main_config_file); - document_footer(); - return ERROR; - } - - /* read all object configuration data */ - result = read_all_object_configuration_data(main_config_file, READ_ALL_OBJECT_DATA); - if(result == ERROR) { - document_header(FALSE); - object_data_error(); - document_footer(); - return ERROR; - } + cgi_init(document_header, document_footer, READ_ALL_OBJECT_DATA, 0); /* initialize report time period to last 24 hours */ time(&t2); @@ -698,7 +662,7 @@ void document_header(int use_stylesheet) { printf("Expires: %s\r\n", date_time); if(output_format == HTML_OUTPUT) - printf("Content-type: text/html\r\n\r\n"); + printf("Content-type: text/html; charset=utf-8\r\n\r\n"); else { printf("Content-type: text/plain\r\n\r\n"); return; @@ -761,7 +725,6 @@ int process_cgivars(void) { /* do some basic length checking on the variable identifier to prevent buffer overflows */ if(strlen(variables[x]) >= MAX_INPUT_BUFFER - 1) { - x++; continue; } @@ -1564,9 +1527,9 @@ void add_archived_event(int event_type, time_t time_stamp, int entry_type, int s #ifdef DEBUG if(event_type == AE_HOST_ALERT) - printf("Adding host alert (%s) @ %lu
\n", host_name, (unsigned long)time_stamp); + printf("Adding host alert (%s) @ %llu
\n", host_name, (unsigned long long)time_stamp); else - printf("Adding service alert (%s/%s) @ %lu
\n", host_name, svc_description, (unsigned long)time_stamp); + printf("Adding service alert (%s/%s) @ %llu
\n", host_name, svc_description, (unsigned long long)time_stamp); #endif /* allocate memory for the new entry */ @@ -1734,9 +1697,9 @@ void display_recent_alerts(void) { archived_event *temp_event; int current_item = 0; int odd = 0; - char *bgclass = ""; - char *status_bgclass = ""; - char *status = ""; + const char *bgclass = ""; + const char *status_bgclass = ""; + const char *status = ""; char date_time[MAX_DATETIME_LENGTH]; @@ -2694,7 +2657,7 @@ void display_top_alerts(void) { int producer_type = AE_HOST_PRODUCER; int current_item = 0; int odd = 0; - char *bgclass = ""; + const char *bgclass = ""; /* process all events */ for(temp_event = event_list; temp_event != NULL; temp_event = temp_event->next) { diff --git a/cgi/tac.c b/cgi/tac.c index 3418448..8f04c20 100644 --- a/cgi/tac.c +++ b/cgi/tac.c @@ -2,8 +2,6 @@ * * TAC.C - Nagios Tactical Monitoring Overview CGI * - * Copyright (c) 2001-2010 Ethan Galstad (egalstad@nagios.org) - * Last Modified: 08-05-2010 * * This CGI program will display the contents of the Nagios * log file. @@ -51,8 +49,10 @@ extern char url_html_path[MAX_FILENAME_LENGTH]; extern char url_images_path[MAX_FILENAME_LENGTH]; extern char url_stylesheets_path[MAX_FILENAME_LENGTH]; extern char url_media_path[MAX_FILENAME_LENGTH]; +extern char url_js_path[MAX_FILENAME_LENGTH]; extern int refresh_rate; +extern int tac_cgi_hard_only; extern char *service_critical_sound; extern char *service_warning_sound; @@ -61,17 +61,9 @@ extern char *host_down_sound; extern char *host_unreachable_sound; extern char *normal_sound; -extern host *host_list; -extern hostgroup *hostgroup_list; extern hoststatus *hoststatus_list; extern servicestatus *servicestatus_list; -extern int enable_notifications; -extern int execute_service_checks; -extern int accept_passive_service_checks; -extern int enable_event_handlers; -extern int enable_flap_detection; - extern int nagios_process_state; @@ -190,16 +182,7 @@ int services_critical = 0; /*efine DEBUG 1*/ int main(void) { - int result = OK; char *sound = NULL; -#ifdef DEBUG - time_t t1, t2, t3, t4, t5, t6, t7, t8, t9; -#endif - - -#ifdef DEBUG - time(&t1); -#endif /* get the CGI variables passed in the URL */ process_cgivars(); @@ -207,64 +190,13 @@ int main(void) { /* reset internal variables */ reset_cgi_vars(); - /* read the CGI configuration file */ - result = read_cgi_config_file(get_cgi_config_location()); - if(result == ERROR) { - document_header(FALSE); - cgi_config_file_error(get_cgi_config_location()); - document_footer(); - return ERROR; - } - -#ifdef DEBUG - time(&t2); -#endif - - /* read the main configuration file */ - result = read_main_config_file(main_config_file); - if(result == ERROR) { - document_header(FALSE); - main_config_file_error(main_config_file); - document_footer(); - return ERROR; - } - -#ifdef DEBUG - time(&t3); -#endif - - /* read all object configuration data */ - result = read_all_object_configuration_data(main_config_file, READ_ALL_OBJECT_DATA); - if(result == ERROR) { - document_header(FALSE); - object_data_error(); - document_footer(); - return ERROR; - } - -#ifdef DEBUG - time(&t4); -#endif - - /* read all status data */ - result = read_all_status_data(get_cgi_config_location(), READ_ALL_STATUS_DATA); - if(result == ERROR) { - document_header(FALSE); - status_data_error(); - document_footer(); - free_memory(); - return ERROR; - } - -#ifdef DEBUG - time(&t5); -#endif - - document_header(TRUE); + cgi_init(document_header, document_footer, READ_ALL_OBJECT_DATA, READ_ALL_STATUS_DATA); /* get authentication information */ get_authentication_information(¤t_authdata); + document_header(TRUE); + if(display_header == TRUE) { /* begin top table */ @@ -291,26 +223,12 @@ int main(void) { } - -#ifdef DEBUG - time(&t6); -#endif - /* analyze current host and service status data for tac overview */ analyze_status_data(); -#ifdef DEBUG - time(&t7); -#endif - /* find all hosts that are causing network outages */ find_hosts_causing_outages(); - -#ifdef DEBUG - time(&t8); -#endif - /* embed sound tag if necessary... */ if(hosts_unreachable_unacknowledged > 0 && host_unreachable_sound != NULL) sound = host_unreachable_sound; @@ -323,7 +241,7 @@ int main(void) { else if(services_unknown_unacknowledged == 0 && services_warning_unacknowledged == 0 && services_critical_unacknowledged == 0 && hosts_down_unacknowledged == 0 && hosts_unreachable_unacknowledged == 0 && normal_sound != NULL) sound = normal_sound; if(sound != NULL) { - printf("", url_media_path, sound); + printf("", url_media_path, sound); printf("", url_media_path, sound); printf(""); printf(""); @@ -334,10 +252,6 @@ int main(void) { /**** display main tac screen ****/ display_tac_overview(); -#ifdef DEBUG - time(&t9); -#endif - document_footer(); /* free memory allocated to the host outage list */ @@ -346,18 +260,6 @@ int main(void) { /* free allocated memory */ free_memory(); -#ifdef DEBUG - printf("T1: %lu\n", (unsigned long)t1); - printf("T2: %lu\n", (unsigned long)t2); - printf("T3: %lu\n", (unsigned long)t3); - printf("T4: %lu\n", (unsigned long)t4); - printf("T5: %lu\n", (unsigned long)t5); - printf("T6: %lu\n", (unsigned long)t6); - printf("T7: %lu\n", (unsigned long)t7); - printf("T8: %lu\n", (unsigned long)t8); - printf("T9: %lu\n", (unsigned long)t9); -#endif - return OK; } @@ -381,7 +283,7 @@ void document_header(int use_stylesheet) { get_time_string(&expire_time, date_time, (int)sizeof(date_time), HTTP_DATE_TIME); printf("Expires: %s\r\n", date_time); - printf("Content-type: text/html\r\n\r\n"); + printf("Content-type: text/html; charset=utf-8\r\n\r\n"); if(embedded == TRUE) return; @@ -396,8 +298,22 @@ void document_header(int use_stylesheet) { if(use_stylesheet == TRUE) { printf("\n", url_stylesheets_path, COMMON_CSS); printf("\n", url_stylesheets_path, TAC_CSS); + printf("\n", url_stylesheets_path, NAGFUNCS_CSS); } + printf("\n", url_js_path, JQUERY_JS); + printf("\n", url_js_path, NAGFUNCS_JS); + + printf("\n"); + printf("\n"); printf("\n"); @@ -496,7 +412,7 @@ void analyze_status_data(void) { active_checks_disabled_services++; /* passive check acceptance */ - if(temp_servicestatus->accept_passive_service_checks == FALSE) + if(temp_servicestatus->accept_passive_checks == FALSE) passive_checks_disabled_services++; @@ -514,7 +430,7 @@ void analyze_status_data(void) { else if(temp_servicestatus->status == SERVICE_WARNING) { temp_hoststatus = find_hoststatus(temp_servicestatus->host_name); - if(temp_hoststatus != NULL && (temp_hoststatus->status == HOST_DOWN || temp_hoststatus->status == HOST_UNREACHABLE)) { + if(temp_hoststatus != NULL && (temp_hoststatus->status == SD_HOST_DOWN || temp_hoststatus->status == SD_HOST_UNREACHABLE)) { services_warning_host_problem++; problem = FALSE; } @@ -530,14 +446,16 @@ void analyze_status_data(void) { services_warning_disabled++; problem = FALSE; } - if(problem == TRUE) - services_warning_unacknowledged++; + if(problem == TRUE) { + if (temp_servicestatus->state_type == HARD_STATE || tac_cgi_hard_only == FALSE) + services_warning_unacknowledged++; + } services_warning++; } else if(temp_servicestatus->status == SERVICE_UNKNOWN) { temp_hoststatus = find_hoststatus(temp_servicestatus->host_name); - if(temp_hoststatus != NULL && (temp_hoststatus->status == HOST_DOWN || temp_hoststatus->status == HOST_UNREACHABLE)) { + if(temp_hoststatus != NULL && (temp_hoststatus->status == SD_HOST_DOWN || temp_hoststatus->status == SD_HOST_UNREACHABLE)) { services_unknown_host_problem++; problem = FALSE; } @@ -553,14 +471,16 @@ void analyze_status_data(void) { services_unknown_disabled++; problem = FALSE; } - if(problem == TRUE) - services_unknown_unacknowledged++; + if(problem == TRUE) { + if (temp_servicestatus->state_type == HARD_STATE || tac_cgi_hard_only == FALSE) + services_unknown_unacknowledged++; + } services_unknown++; } else if(temp_servicestatus->status == SERVICE_CRITICAL) { temp_hoststatus = find_hoststatus(temp_servicestatus->host_name); - if(temp_hoststatus != NULL && (temp_hoststatus->status == HOST_DOWN || temp_hoststatus->status == HOST_UNREACHABLE)) { + if(temp_hoststatus != NULL && (temp_hoststatus->status == SD_HOST_DOWN || temp_hoststatus->status == SD_HOST_UNREACHABLE)) { services_critical_host_problem++; problem = FALSE; } @@ -576,8 +496,10 @@ void analyze_status_data(void) { services_critical_disabled++; problem = FALSE; } - if(problem == TRUE) - services_critical_unacknowledged++; + if(problem == TRUE) { + if (temp_servicestatus->state_type == HARD_STATE || tac_cgi_hard_only == FALSE) + services_critical_unacknowledged++; + } services_critical++; } @@ -600,7 +522,7 @@ void analyze_status_data(void) { /* calculate execution time and latency stats */ - if(temp_servicestatus->check_type == SERVICE_CHECK_ACTIVE) { + if(temp_servicestatus->check_type == CHECK_TYPE_ACTIVE) { total_active_service_checks++; @@ -655,7 +577,7 @@ void analyze_status_data(void) { active_checks_disabled_hosts++; /* passive check acceptance */ - if(temp_hoststatus->accept_passive_host_checks == FALSE) + if(temp_hoststatus->accept_passive_checks == FALSE) passive_checks_disabled_hosts++; @@ -663,7 +585,7 @@ void analyze_status_data(void) { problem = TRUE; - if(temp_hoststatus->status == HOST_UP) { + if(temp_hoststatus->status == SD_HOST_UP) { if(temp_hoststatus->checks_enabled == FALSE) hosts_up_disabled++; else @@ -671,7 +593,7 @@ void analyze_status_data(void) { hosts_up++; } - else if(temp_hoststatus->status == HOST_DOWN) { + else if(temp_hoststatus->status == SD_HOST_DOWN) { if(temp_hoststatus->scheduled_downtime_depth > 0) { hosts_down_scheduled++; problem = FALSE; @@ -684,12 +606,14 @@ void analyze_status_data(void) { hosts_down_disabled++; problem = FALSE; } - if(problem == TRUE) - hosts_down_unacknowledged++; + if(problem == TRUE) { + if (temp_hoststatus->state_type == HARD_STATE || tac_cgi_hard_only == FALSE) + hosts_down_unacknowledged++; + } hosts_down++; } - else if(temp_hoststatus->status == HOST_UNREACHABLE) { + else if(temp_hoststatus->status == SD_HOST_UNREACHABLE) { if(temp_hoststatus->scheduled_downtime_depth > 0) { hosts_unreachable_scheduled++; problem = FALSE; @@ -702,8 +626,10 @@ void analyze_status_data(void) { hosts_unreachable_disabled++; problem = FALSE; } - if(problem == TRUE) - hosts_unreachable_unacknowledged++; + if(problem == TRUE) { + if (temp_hoststatus->state_type == HARD_STATE || tac_cgi_hard_only == FALSE) + hosts_unreachable_unacknowledged++; + } hosts_unreachable++; } @@ -714,14 +640,14 @@ void analyze_status_data(void) { } /* get health stats */ - if(temp_hoststatus->status == HOST_UP) + if(temp_hoststatus->status == SD_HOST_UP) total_host_health++; if(temp_hoststatus->status != HOST_PENDING) potential_host_health++; /* check type stats */ - if(temp_hoststatus->check_type == HOST_CHECK_ACTIVE) { + if(temp_hoststatus->check_type == CHECK_TYPE_ACTIVE) { total_active_host_checks++; @@ -801,7 +727,7 @@ void find_hosts_causing_outages(void) { for(temp_hoststatus = hoststatus_list; temp_hoststatus != NULL; temp_hoststatus = temp_hoststatus->next) { /* check only hosts that are not up and not pending */ - if(temp_hoststatus->status != HOST_UP && temp_hoststatus->status != HOST_PENDING) { + if(temp_hoststatus->status != SD_HOST_UP && temp_hoststatus->status != HOST_PENDING) { /* find the host entry */ temp_host = find_host(temp_hoststatus->host_name); @@ -920,7 +846,7 @@ int is_route_to_host_blocked(host *hst) { continue; /* at least one parent it up (or pending), so this host is not blocked */ - if(temp_hoststatus->status == HOST_UP || temp_hoststatus->status == HOST_PENDING) + if(temp_hoststatus->status == SD_HOST_UP || temp_hoststatus->status == HOST_PENDING) return FALSE; } @@ -953,7 +879,7 @@ void display_tac_overview(void) { /* right column */ printf("
\n"); - printf("\n"); + printf("
\n"); printf("\n"); @@ -966,7 +892,7 @@ void display_tac_overview(void) { printf("/", " unlike( $output, "/Sorry, but no information is available for this command./", "$local_cgi with cmd_typ=$cmd_typ has a command description" ); -# Tests against command type '80' -$cmd_typ=80; -$output = `NAGIOS_CGI_CONFIG=etc/cgi.cfg $remote_user REQUEST_METHOD=GET QUERY_STRING='cmd_typ=$cmd_typ' $local_cgi`; -like( $output, "/You are requesting to enable failure prediction for hosts and service/", "$local_cgi with cmd_typ=$cmd_typ shows request to enable failure prediction for hosts and service" ); -unlike( $output, "/Sorry, but no information is available for this command./", "$local_cgi with cmd_typ=$cmd_typ has a command description" ); - - - -# Tests against command type '81' -$cmd_typ=81; -$output = `NAGIOS_CGI_CONFIG=etc/cgi.cfg $remote_user REQUEST_METHOD=GET QUERY_STRING='cmd_typ=$cmd_typ' $local_cgi`; -like( $output, "/You are requesting to disable failure prediction for hosts and service/", "$local_cgi with cmd_typ=$cmd_typ shows request to disable failure prediction for hosts and service" ); -unlike( $output, "/Sorry, but no information is available for this command./", "$local_cgi with cmd_typ=$cmd_typ has a command description" ); - - # Tests against command type '82' $cmd_typ=82; $output = `NAGIOS_CGI_CONFIG=etc/cgi.cfg $remote_user REQUEST_METHOD=GET QUERY_STRING='cmd_typ=$cmd_typ' $local_cgi`; diff --git a/t/705nagiostats.t b/t/705nagiostats.t index 4974294..f5c1ea0 100644 --- a/t/705nagiostats.t +++ b/t/705nagiostats.t @@ -12,17 +12,26 @@ chdir $Bin or die "Cannot chdir"; my $topdir = "$Bin/.."; my $nagiostats = "$topdir/base/nagiostats"; my $etc = "$Bin/etc"; +my $var = "$Bin/var"; -plan tests => 5; +plan tests => 10; -my $output = `$nagiostats -c "$etc/nagios-does-not-exit.cfg"`; +my $output = `$nagiostats -c "$etc/nagios-does-not-exist.cfg"`; isnt( $?, 0, "Bad return code with no config file" ); like( $output, "/Error processing config file/", "No config file" ); $output = `$nagiostats -c "$etc/nagios-no-status.cfg"`; isnt( $?, 0, "Bad return code with no status file" ); -like( $output, "/Error reading status file 'var/status.dat.no.such.file': No such file or directory/", "No config file" ); +like( $output, "/Error reading status file '.*var/status.dat.no.such.file': No such file or directory/", "No config file" ); -$output = `$nagiostats -c "$etc/nagios-no-status.cfg" -m NUMHSTUP`; +$output = `$nagiostats -c "$etc/nagios-no-status.cfg" -m -d NUMHSTUP`; isnt( $?, 0, "Bad return code with no status file in MRTG mode" ); +like( $output, "/^0\$/", "No UP host when no status file" ); +$output = `$nagiostats -c "$etc/nagios-with-generated-status.cfg" -m -d NUMHOSTS`; +is( $?, 0, "Bad return code with implied status file in MRTG mode" ); +unlike( $output, "/^0\$/", "Implied generated status file contains host(s)" ); + +$output = `$nagiostats -s "$var/status-generated.dat" -m -d NUMHOSTS`; +is( $?, 0, "Bad return code with explicit status file in MRTG mode" ); +unlike( $output, "/^0\$/", "Explicit generated status file contains host(s)" ); diff --git a/t/900-configparsing.t b/t/900-configparsing.t index 3548b3c..c4c1de3 100644 --- a/t/900-configparsing.t +++ b/t/900-configparsing.t @@ -31,7 +31,7 @@ my @output = `$diff`; if ($? == 0) { pass( "Nagios precached objects file matches expected" ); } else { - fail( "Nagios precached objects discrepency!!!\nTest with: $diff\nCopy with: cp $precache.generated $precache.expected" ); + fail( "Nagios precached objects discrepancy!!!\nTest with: $diff\nCopy with: cp $precache.generated $precache.expected" ); print "#$_" foreach @output; } diff --git a/t/920-nocontactgroup.t b/t/920-nocontactgroup.t index c7005a6..9cd7058 100644 --- a/t/920-nocontactgroup.t +++ b/t/920-nocontactgroup.t @@ -16,5 +16,5 @@ my $precache = "$Bin/var/objects.precache"; my $output = `$nagios -v "$etc/nagios-no-contactgroup.cfg"`; -like( $output, "/Error: Could not find any contactgroup matching 'nonexistantone'/", "Correct error for no contactgroup" ); +like( $output, "/Error: Could not find any contactgroup matching 'nonexistentone'/", "Correct error for no contactgroup" ); isnt($?, 0, "And get return code error" ); diff --git a/t/930-emptygroups.t b/t/930-emptygroups.t index 2df2074..fca320f 100644 --- a/t/930-emptygroups.t +++ b/t/930-emptygroups.t @@ -1,6 +1,6 @@ #!/usr/bin/perl # -# Check that empty host/service groups pass verfication. +# Check that empty host/service groups pass verification. # Likely error on non-patched version: # "Error: Host 'r' specified in host group 'generic-pc' is not defined anywhere!" diff --git a/t/etc/cgi-hosturgencies.cfg b/t/etc/cgi-hosturgencies.cfg index 3eeb96e..4358937 100644 --- a/t/etc/cgi-hosturgencies.cfg +++ b/t/etc/cgi-hosturgencies.cfg @@ -1,332 +1,23 @@ -################################################################# -# -# CGI.CFG - Sample CGI Configuration File for Nagios 3.1.0 -# -# Last Modified: 11-30-2008 -# -################################################################# - - -# MAIN CONFIGURATION FILE -# This tells the CGIs where to find your main configuration file. -# The CGIs will read the main and host config files for any other -# data they might need. - main_config_file=etc/nagios-hosturgencies.cfg - - - -# PHYSICAL HTML PATH -# This is the path where the HTML files for Nagios reside. This -# value is used to locate the logo images needed by the statusmap -# and statuswrl CGIs. - physical_html_path=/usr/local/nagios/share - - - -# URL HTML PATH -# This is the path portion of the URL that corresponds to the -# physical location of the Nagios HTML files (as defined above). -# This value is used by the CGIs to locate the online documentation -# and graphics. If you access the Nagios pages with an URL like -# http://www.myhost.com/nagios, this value should be '/nagios' -# (without the quotes). - url_html_path=/nagios - - - -# CONTEXT-SENSITIVE HELP -# This option determines whether or not a context-sensitive -# help icon will be displayed for most of the CGIs. -# Values: 0 = disables context-sensitive help -# 1 = enables context-sensitive help - show_context_help=0 - - - -# PENDING STATES OPTION -# This option determines what states should be displayed in the web -# interface for hosts/services that have not yet been checked. -# Values: 0 = leave hosts/services that have not been check yet in their original state -# 1 = mark hosts/services that have not been checked yet as PENDING - use_pending_states=1 - - - - -# AUTHENTICATION USAGE -# This option controls whether or not the CGIs will use any -# authentication when displaying host and service information, as -# well as committing commands to Nagios for processing. -# -# Read the HTML documentation to learn how the authorization works! -# -# NOTE: It is a really *bad* idea to disable authorization, unless -# you plan on removing the command CGI (cmd.cgi)! Failure to do -# so will leave you wide open to kiddies messing with Nagios and -# possibly hitting you with a denial of service attack by filling up -# your drive by continuously writing to your command file! -# -# Setting this value to 0 will cause the CGIs to *not* use -# authentication (bad idea), while any other value will make them -# use the authentication functions (the default). - use_authentication=1 - - - - -# x509 CERT AUTHENTICATION -# When enabled, this option allows you to use x509 cert (SSL) -# authentication in the CGIs. This is an advanced option and should -# not be enabled unless you know what you're doing. - use_ssl_authentication=0 - - - - -# DEFAULT USER -# Setting this variable will define a default user name that can -# access pages without authentication. This allows people within a -# secure domain (i.e., behind a firewall) to see the current status -# without authenticating. You may want to use this to avoid basic -# authentication if you are not using a secure server since basic -# authentication transmits passwords in the clear. -# -# Important: Do not define a default username unless you are -# running a secure web server and are sure that everyone who has -# access to the CGIs has been authenticated in some manner! If you -# define this variable, anyone who has not authenticated to the web -# server will inherit all rights you assign to this user! -#default_user_name=guest - - - -# SYSTEM/PROCESS INFORMATION ACCESS -# This option is a comma-delimited list of all usernames that -# have access to viewing the Nagios process information as -# provided by the Extended Information CGI (extinfo.cgi). By -# default, *no one* has access to this unless you choose to -# not use authorization. You may use an asterisk (*) to -# authorize any user who has authenticated to the web server. - authorized_for_system_information=nagiosadmin - - - -# CONFIGURATION INFORMATION ACCESS -# This option is a comma-delimited list of all usernames that -# can view ALL configuration information (hosts, commands, etc). -# By default, users can only view configuration information -# for the hosts and services they are contacts for. You may use -# an asterisk (*) to authorize any user who has authenticated -# to the web server. - authorized_for_configuration_information=nagiosadmin - - - -# SYSTEM/PROCESS COMMAND ACCESS -# This option is a comma-delimited list of all usernames that -# can issue shutdown and restart commands to Nagios via the -# command CGI (cmd.cgi). Users in this list can also change -# the program mode to active or standby. By default, *no one* -# has access to this unless you choose to not use authorization. -# You may use an asterisk (*) to authorize any user who has -# authenticated to the web server. - authorized_for_system_commands=nagiosadmin - - - -# GLOBAL HOST/SERVICE VIEW ACCESS -# These two options are comma-delimited lists of all usernames that -# can view information for all hosts and services that are being -# monitored. By default, users can only view information -# for hosts or services that they are contacts for (unless you -# you choose to not use authorization). You may use an asterisk (*) -# to authorize any user who has authenticated to the web server. - - authorized_for_all_services=nagiosadmin authorized_for_all_hosts=nagiosadmin - - - -# GLOBAL HOST/SERVICE COMMAND ACCESS -# These two options are comma-delimited lists of all usernames that -# can issue host or service related commands via the command -# CGI (cmd.cgi) for all hosts and services that are being monitored. -# By default, users can only issue commands for hosts or services -# that they are contacts for (unless you you choose to not use -# authorization). You may use an asterisk (*) to authorize any -# user who has authenticated to the web server. - authorized_for_all_service_commands=nagiosadmin authorized_for_all_host_commands=nagiosadmin - - - - -# STATUSMAP BACKGROUND IMAGE -# This option allows you to specify an image to be used as a -# background in the statusmap CGI. It is assumed that the image -# resides in the HTML images path (i.e. /usr/local/nagios/share/images). -# This path is automatically determined by appending "/images" -# to the path specified by the 'physical_html_path' directive. -# Note: The image file may be in GIF, PNG, JPEG, or GD2 format. -# However, I recommend that you convert your image to GD2 format -# (uncompressed), as this will cause less CPU load when the CGI -# generates the image. - -#statusmap_background_image=smbackground.gd2 - - - -# DEFAULT STATUSMAP LAYOUT METHOD -# This option allows you to specify the default layout method -# the statusmap CGI should use for drawing hosts. If you do -# not use this option, the default is to use user-defined -# coordinates. Valid options are as follows: -# 0 = User-defined coordinates -# 1 = Depth layers -# 2 = Collapsed tree -# 3 = Balanced tree -# 4 = Circular -# 5 = Circular (Marked Up) - default_statusmap_layout=5 - - - -# DEFAULT STATUSWRL LAYOUT METHOD -# This option allows you to specify the default layout method -# the statuswrl (VRML) CGI should use for drawing hosts. If you -# do not use this option, the default is to use user-defined -# coordinates. Valid options are as follows: -# 0 = User-defined coordinates -# 2 = Collapsed tree -# 3 = Balanced tree -# 4 = Circular - default_statuswrl_layout=4 - - - -# STATUSWRL INCLUDE -# This option allows you to include your own objects in the -# generated VRML world. It is assumed that the file -# resides in the HTML path (i.e. /usr/local/nagios/share). - -#statuswrl_include=myworld.wrl - - - -# PING SYNTAX -# This option determines what syntax should be used when -# attempting to ping a host from the WAP interface (using -# the statuswml CGI. You must include the full path to -# the ping binary, along with all required options. The -# $HOSTADDRESS$ macro is substituted with the address of -# the host before the command is executed. -# Please note that the syntax for the ping binary is -# notorious for being different on virtually ever *NIX -# OS and distribution, so you may have to tweak this to -# work on your system. - ping_syntax=echo -n -U -c 5 $HOSTADDRESS$ - - - -# REFRESH RATE -# This option allows you to specify the refresh rate in seconds -# of various CGIs (status, statusmap, extinfo, and outages). - refresh_rate=90 - - - -# ESCAPE HTML TAGS -# This option determines whether HTML tags in host and service -# status output is escaped in the web interface. If enabled, -# your plugin output will not be able to contain clickable links. - escape_html_tags=1 - - - - -# SOUND OPTIONS -# These options allow you to specify an optional audio file -# that should be played in your browser window when there are -# problems on the network. The audio files are used only in -# the status CGI. Only the sound for the most critical problem -# will be played. Order of importance (higher to lower) is as -# follows: unreachable hosts, down hosts, critical services, -# warning services, and unknown services. If there are no -# visible problems, the sound file optionally specified by -# 'normal_sound' variable will be played. -# -# -# = -# -# Note: All audio files must be placed in the /media subdirectory -# under the HTML path (i.e. /usr/local/nagios/share/media/). - -#host_unreachable_sound=hostdown.wav -#host_down_sound=hostdown.wav -#service_critical_sound=critical.wav -#service_warning_sound=warning.wav -#service_unknown_sound=warning.wav -#normal_sound=noproblem.wav - - - -# URL TARGET FRAMES -# These options determine the target frames in which notes and -# action URLs will open. - action_url_target=_blank notes_url_target=_blank - - - - -# LOCK AUTHOR NAMES OPTION -# This option determines whether users can change the author name -# when submitting comments, scheduling downtime. If disabled, the -# author names will be locked into their contact name, as defined in Nagios. -# Values: 0 = allow editing author names -# 1 = lock author names (disallow editing) - lock_author_names=1 - - - - -# SPLUNK INTEGRATION OPTIONS -# These options allow you to enable integration with Splunk -# in the web interface. If enabled, you'll be presented with -# "Splunk It" links in various places in the CGIs (log file, -# alert history, host/service detail, etc). Useful if you're -# trying to research why a particular problem occurred. -# For more information on Splunk, visit http://www.splunk.com/ - -# This option determines whether the Splunk integration is enabled -# Values: 0 = disable Splunk integration -# 1 = enable Splunk integration - -#enable_splunk_integration=1 - - -# This option should be the URL used to access your instance of Splunk - -#splunk_url=http://127.0.0.1:8000/ - - diff --git a/t/etc/cgi-with-generated-status.cfg b/t/etc/cgi-with-generated-status.cfg index 9da610c..e9b843b 100644 --- a/t/etc/cgi-with-generated-status.cfg +++ b/t/etc/cgi-with-generated-status.cfg @@ -1,332 +1,23 @@ -################################################################# -# -# CGI.CFG - Sample CGI Configuration File for Nagios 3.1.0 -# -# Last Modified: 11-30-2008 -# -################################################################# - - -# MAIN CONFIGURATION FILE -# This tells the CGIs where to find your main configuration file. -# The CGIs will read the main and host config files for any other -# data they might need. - main_config_file=etc/nagios-with-generated-status.cfg - - - -# PHYSICAL HTML PATH -# This is the path where the HTML files for Nagios reside. This -# value is used to locate the logo images needed by the statusmap -# and statuswrl CGIs. - physical_html_path=/usr/local/nagios/share - - - -# URL HTML PATH -# This is the path portion of the URL that corresponds to the -# physical location of the Nagios HTML files (as defined above). -# This value is used by the CGIs to locate the online documentation -# and graphics. If you access the Nagios pages with an URL like -# http://www.myhost.com/nagios, this value should be '/nagios' -# (without the quotes). - url_html_path=/nagios - - - -# CONTEXT-SENSITIVE HELP -# This option determines whether or not a context-sensitive -# help icon will be displayed for most of the CGIs. -# Values: 0 = disables context-sensitive help -# 1 = enables context-sensitive help - show_context_help=0 - - - -# PENDING STATES OPTION -# This option determines what states should be displayed in the web -# interface for hosts/services that have not yet been checked. -# Values: 0 = leave hosts/services that have not been check yet in their original state -# 1 = mark hosts/services that have not been checked yet as PENDING - use_pending_states=1 - - - - -# AUTHENTICATION USAGE -# This option controls whether or not the CGIs will use any -# authentication when displaying host and service information, as -# well as committing commands to Nagios for processing. -# -# Read the HTML documentation to learn how the authorization works! -# -# NOTE: It is a really *bad* idea to disable authorization, unless -# you plan on removing the command CGI (cmd.cgi)! Failure to do -# so will leave you wide open to kiddies messing with Nagios and -# possibly hitting you with a denial of service attack by filling up -# your drive by continuously writing to your command file! -# -# Setting this value to 0 will cause the CGIs to *not* use -# authentication (bad idea), while any other value will make them -# use the authentication functions (the default). - use_authentication=1 - - - - -# x509 CERT AUTHENTICATION -# When enabled, this option allows you to use x509 cert (SSL) -# authentication in the CGIs. This is an advanced option and should -# not be enabled unless you know what you're doing. - use_ssl_authentication=0 - - - - -# DEFAULT USER -# Setting this variable will define a default user name that can -# access pages without authentication. This allows people within a -# secure domain (i.e., behind a firewall) to see the current status -# without authenticating. You may want to use this to avoid basic -# authentication if you are not using a secure server since basic -# authentication transmits passwords in the clear. -# -# Important: Do not define a default username unless you are -# running a secure web server and are sure that everyone who has -# access to the CGIs has been authenticated in some manner! If you -# define this variable, anyone who has not authenticated to the web -# server will inherit all rights you assign to this user! -#default_user_name=guest - - - -# SYSTEM/PROCESS INFORMATION ACCESS -# This option is a comma-delimited list of all usernames that -# have access to viewing the Nagios process information as -# provided by the Extended Information CGI (extinfo.cgi). By -# default, *no one* has access to this unless you choose to -# not use authorization. You may use an asterisk (*) to -# authorize any user who has authenticated to the web server. - authorized_for_system_information=nagiosadmin - - - -# CONFIGURATION INFORMATION ACCESS -# This option is a comma-delimited list of all usernames that -# can view ALL configuration information (hosts, commands, etc). -# By default, users can only view configuration information -# for the hosts and services they are contacts for. You may use -# an asterisk (*) to authorize any user who has authenticated -# to the web server. - authorized_for_configuration_information=nagiosadmin - - - -# SYSTEM/PROCESS COMMAND ACCESS -# This option is a comma-delimited list of all usernames that -# can issue shutdown and restart commands to Nagios via the -# command CGI (cmd.cgi). Users in this list can also change -# the program mode to active or standby. By default, *no one* -# has access to this unless you choose to not use authorization. -# You may use an asterisk (*) to authorize any user who has -# authenticated to the web server. - authorized_for_system_commands=nagiosadmin - - - -# GLOBAL HOST/SERVICE VIEW ACCESS -# These two options are comma-delimited lists of all usernames that -# can view information for all hosts and services that are being -# monitored. By default, users can only view information -# for hosts or services that they are contacts for (unless you -# you choose to not use authorization). You may use an asterisk (*) -# to authorize any user who has authenticated to the web server. - - authorized_for_all_services=nagiosadmin authorized_for_all_hosts=nagiosadmin - - - -# GLOBAL HOST/SERVICE COMMAND ACCESS -# These two options are comma-delimited lists of all usernames that -# can issue host or service related commands via the command -# CGI (cmd.cgi) for all hosts and services that are being monitored. -# By default, users can only issue commands for hosts or services -# that they are contacts for (unless you you choose to not use -# authorization). You may use an asterisk (*) to authorize any -# user who has authenticated to the web server. - authorized_for_all_service_commands=nagiosadmin authorized_for_all_host_commands=nagiosadmin - - - - -# STATUSMAP BACKGROUND IMAGE -# This option allows you to specify an image to be used as a -# background in the statusmap CGI. It is assumed that the image -# resides in the HTML images path (i.e. /usr/local/nagios/share/images). -# This path is automatically determined by appending "/images" -# to the path specified by the 'physical_html_path' directive. -# Note: The image file may be in GIF, PNG, JPEG, or GD2 format. -# However, I recommend that you convert your image to GD2 format -# (uncompressed), as this will cause less CPU load when the CGI -# generates the image. - -#statusmap_background_image=smbackground.gd2 - - - -# DEFAULT STATUSMAP LAYOUT METHOD -# This option allows you to specify the default layout method -# the statusmap CGI should use for drawing hosts. If you do -# not use this option, the default is to use user-defined -# coordinates. Valid options are as follows: -# 0 = User-defined coordinates -# 1 = Depth layers -# 2 = Collapsed tree -# 3 = Balanced tree -# 4 = Circular -# 5 = Circular (Marked Up) - default_statusmap_layout=5 - - - -# DEFAULT STATUSWRL LAYOUT METHOD -# This option allows you to specify the default layout method -# the statuswrl (VRML) CGI should use for drawing hosts. If you -# do not use this option, the default is to use user-defined -# coordinates. Valid options are as follows: -# 0 = User-defined coordinates -# 2 = Collapsed tree -# 3 = Balanced tree -# 4 = Circular - default_statuswrl_layout=4 - - - -# STATUSWRL INCLUDE -# This option allows you to include your own objects in the -# generated VRML world. It is assumed that the file -# resides in the HTML path (i.e. /usr/local/nagios/share). - -#statuswrl_include=myworld.wrl - - - -# PING SYNTAX -# This option determines what syntax should be used when -# attempting to ping a host from the WAP interface (using -# the statuswml CGI. You must include the full path to -# the ping binary, along with all required options. The -# $HOSTADDRESS$ macro is substituted with the address of -# the host before the command is executed. -# Please note that the syntax for the ping binary is -# notorious for being different on virtually ever *NIX -# OS and distribution, so you may have to tweak this to -# work on your system. - ping_syntax=echo -n -U -c 5 $HOSTADDRESS$ - - - -# REFRESH RATE -# This option allows you to specify the refresh rate in seconds -# of various CGIs (status, statusmap, extinfo, and outages). - refresh_rate=90 - - - -# ESCAPE HTML TAGS -# This option determines whether HTML tags in host and service -# status output is escaped in the web interface. If enabled, -# your plugin output will not be able to contain clickable links. - escape_html_tags=1 - - - - -# SOUND OPTIONS -# These options allow you to specify an optional audio file -# that should be played in your browser window when there are -# problems on the network. The audio files are used only in -# the status CGI. Only the sound for the most critical problem -# will be played. Order of importance (higher to lower) is as -# follows: unreachable hosts, down hosts, critical services, -# warning services, and unknown services. If there are no -# visible problems, the sound file optionally specified by -# 'normal_sound' variable will be played. -# -# -# = -# -# Note: All audio files must be placed in the /media subdirectory -# under the HTML path (i.e. /usr/local/nagios/share/media/). - -#host_unreachable_sound=hostdown.wav -#host_down_sound=hostdown.wav -#service_critical_sound=critical.wav -#service_warning_sound=warning.wav -#service_unknown_sound=warning.wav -#normal_sound=noproblem.wav - - - -# URL TARGET FRAMES -# These options determine the target frames in which notes and -# action URLs will open. - action_url_target=_blank notes_url_target=_blank - - - - -# LOCK AUTHOR NAMES OPTION -# This option determines whether users can change the author name -# when submitting comments, scheduling downtime. If disabled, the -# author names will be locked into their contact name, as defined in Nagios. -# Values: 0 = allow editing author names -# 1 = lock author names (disallow editing) - lock_author_names=1 - - - - -# SPLUNK INTEGRATION OPTIONS -# These options allow you to enable integration with Splunk -# in the web interface. If enabled, you'll be presented with -# "Splunk It" links in various places in the CGIs (log file, -# alert history, host/service detail, etc). Useful if you're -# trying to research why a particular problem occurred. -# For more information on Splunk, visit http://www.splunk.com/ - -# This option determines whether the Splunk integration is enabled -# Values: 0 = disable Splunk integration -# 1 = enable Splunk integration - -#enable_splunk_integration=1 - - -# This option should be the URL used to access your instance of Splunk - -#splunk_url=http://127.0.0.1:8000/ - - diff --git a/t/etc/cgi.cfg b/t/etc/cgi.cfg index a15825b..df00c13 100644 --- a/t/etc/cgi.cfg +++ b/t/etc/cgi.cfg @@ -1,332 +1,23 @@ -################################################################# -# -# CGI.CFG - Sample CGI Configuration File for Nagios 3.1.0 -# -# Last Modified: 11-30-2008 -# -################################################################# - - -# MAIN CONFIGURATION FILE -# This tells the CGIs where to find your main configuration file. -# The CGIs will read the main and host config files for any other -# data they might need. - main_config_file=etc/nagios.cfg - - - -# PHYSICAL HTML PATH -# This is the path where the HTML files for Nagios reside. This -# value is used to locate the logo images needed by the statusmap -# and statuswrl CGIs. - physical_html_path=/usr/local/nagios/share - - - -# URL HTML PATH -# This is the path portion of the URL that corresponds to the -# physical location of the Nagios HTML files (as defined above). -# This value is used by the CGIs to locate the online documentation -# and graphics. If you access the Nagios pages with an URL like -# http://www.myhost.com/nagios, this value should be '/nagios' -# (without the quotes). - url_html_path=/nagios - - - -# CONTEXT-SENSITIVE HELP -# This option determines whether or not a context-sensitive -# help icon will be displayed for most of the CGIs. -# Values: 0 = disables context-sensitive help -# 1 = enables context-sensitive help - show_context_help=0 - - - -# PENDING STATES OPTION -# This option determines what states should be displayed in the web -# interface for hosts/services that have not yet been checked. -# Values: 0 = leave hosts/services that have not been check yet in their original state -# 1 = mark hosts/services that have not been checked yet as PENDING - use_pending_states=1 - - - - -# AUTHENTICATION USAGE -# This option controls whether or not the CGIs will use any -# authentication when displaying host and service information, as -# well as committing commands to Nagios for processing. -# -# Read the HTML documentation to learn how the authorization works! -# -# NOTE: It is a really *bad* idea to disable authorization, unless -# you plan on removing the command CGI (cmd.cgi)! Failure to do -# so will leave you wide open to kiddies messing with Nagios and -# possibly hitting you with a denial of service attack by filling up -# your drive by continuously writing to your command file! -# -# Setting this value to 0 will cause the CGIs to *not* use -# authentication (bad idea), while any other value will make them -# use the authentication functions (the default). - use_authentication=1 - - - - -# x509 CERT AUTHENTICATION -# When enabled, this option allows you to use x509 cert (SSL) -# authentication in the CGIs. This is an advanced option and should -# not be enabled unless you know what you're doing. - use_ssl_authentication=0 - - - - -# DEFAULT USER -# Setting this variable will define a default user name that can -# access pages without authentication. This allows people within a -# secure domain (i.e., behind a firewall) to see the current status -# without authenticating. You may want to use this to avoid basic -# authentication if you are not using a secure server since basic -# authentication transmits passwords in the clear. -# -# Important: Do not define a default username unless you are -# running a secure web server and are sure that everyone who has -# access to the CGIs has been authenticated in some manner! If you -# define this variable, anyone who has not authenticated to the web -# server will inherit all rights you assign to this user! -#default_user_name=guest - - - -# SYSTEM/PROCESS INFORMATION ACCESS -# This option is a comma-delimited list of all usernames that -# have access to viewing the Nagios process information as -# provided by the Extended Information CGI (extinfo.cgi). By -# default, *no one* has access to this unless you choose to -# not use authorization. You may use an asterisk (*) to -# authorize any user who has authenticated to the web server. - authorized_for_system_information=nagiosadmin - - - -# CONFIGURATION INFORMATION ACCESS -# This option is a comma-delimited list of all usernames that -# can view ALL configuration information (hosts, commands, etc). -# By default, users can only view configuration information -# for the hosts and services they are contacts for. You may use -# an asterisk (*) to authorize any user who has authenticated -# to the web server. - authorized_for_configuration_information=nagiosadmin - - - -# SYSTEM/PROCESS COMMAND ACCESS -# This option is a comma-delimited list of all usernames that -# can issue shutdown and restart commands to Nagios via the -# command CGI (cmd.cgi). Users in this list can also change -# the program mode to active or standby. By default, *no one* -# has access to this unless you choose to not use authorization. -# You may use an asterisk (*) to authorize any user who has -# authenticated to the web server. - authorized_for_system_commands=nagiosadmin - - - -# GLOBAL HOST/SERVICE VIEW ACCESS -# These two options are comma-delimited lists of all usernames that -# can view information for all hosts and services that are being -# monitored. By default, users can only view information -# for hosts or services that they are contacts for (unless you -# you choose to not use authorization). You may use an asterisk (*) -# to authorize any user who has authenticated to the web server. - - authorized_for_all_services=nagiosadmin authorized_for_all_hosts=nagiosadmin - - - -# GLOBAL HOST/SERVICE COMMAND ACCESS -# These two options are comma-delimited lists of all usernames that -# can issue host or service related commands via the command -# CGI (cmd.cgi) for all hosts and services that are being monitored. -# By default, users can only issue commands for hosts or services -# that they are contacts for (unless you you choose to not use -# authorization). You may use an asterisk (*) to authorize any -# user who has authenticated to the web server. - authorized_for_all_service_commands=nagiosadmin authorized_for_all_host_commands=nagiosadmin - - - - -# STATUSMAP BACKGROUND IMAGE -# This option allows you to specify an image to be used as a -# background in the statusmap CGI. It is assumed that the image -# resides in the HTML images path (i.e. /usr/local/nagios/share/images). -# This path is automatically determined by appending "/images" -# to the path specified by the 'physical_html_path' directive. -# Note: The image file may be in GIF, PNG, JPEG, or GD2 format. -# However, I recommend that you convert your image to GD2 format -# (uncompressed), as this will cause less CPU load when the CGI -# generates the image. - -#statusmap_background_image=smbackground.gd2 - - - -# DEFAULT STATUSMAP LAYOUT METHOD -# This option allows you to specify the default layout method -# the statusmap CGI should use for drawing hosts. If you do -# not use this option, the default is to use user-defined -# coordinates. Valid options are as follows: -# 0 = User-defined coordinates -# 1 = Depth layers -# 2 = Collapsed tree -# 3 = Balanced tree -# 4 = Circular -# 5 = Circular (Marked Up) - default_statusmap_layout=5 - - - -# DEFAULT STATUSWRL LAYOUT METHOD -# This option allows you to specify the default layout method -# the statuswrl (VRML) CGI should use for drawing hosts. If you -# do not use this option, the default is to use user-defined -# coordinates. Valid options are as follows: -# 0 = User-defined coordinates -# 2 = Collapsed tree -# 3 = Balanced tree -# 4 = Circular - default_statuswrl_layout=4 - - - -# STATUSWRL INCLUDE -# This option allows you to include your own objects in the -# generated VRML world. It is assumed that the file -# resides in the HTML path (i.e. /usr/local/nagios/share). - -#statuswrl_include=myworld.wrl - - - -# PING SYNTAX -# This option determines what syntax should be used when -# attempting to ping a host from the WAP interface (using -# the statuswml CGI. You must include the full path to -# the ping binary, along with all required options. The -# $HOSTADDRESS$ macro is substituted with the address of -# the host before the command is executed. -# Please note that the syntax for the ping binary is -# notorious for being different on virtually ever *NIX -# OS and distribution, so you may have to tweak this to -# work on your system. - ping_syntax=echo -n -U -c 5 $HOSTADDRESS$ - - - -# REFRESH RATE -# This option allows you to specify the refresh rate in seconds -# of various CGIs (status, statusmap, extinfo, and outages). - refresh_rate=90 - - - -# ESCAPE HTML TAGS -# This option determines whether HTML tags in host and service -# status output is escaped in the web interface. If enabled, -# your plugin output will not be able to contain clickable links. - escape_html_tags=1 - - - - -# SOUND OPTIONS -# These options allow you to specify an optional audio file -# that should be played in your browser window when there are -# problems on the network. The audio files are used only in -# the status CGI. Only the sound for the most critical problem -# will be played. Order of importance (higher to lower) is as -# follows: unreachable hosts, down hosts, critical services, -# warning services, and unknown services. If there are no -# visible problems, the sound file optionally specified by -# 'normal_sound' variable will be played. -# -# -# = -# -# Note: All audio files must be placed in the /media subdirectory -# under the HTML path (i.e. /usr/local/nagios/share/media/). - -#host_unreachable_sound=hostdown.wav -#host_down_sound=hostdown.wav -#service_critical_sound=critical.wav -#service_warning_sound=warning.wav -#service_unknown_sound=warning.wav -#normal_sound=noproblem.wav - - - -# URL TARGET FRAMES -# These options determine the target frames in which notes and -# action URLs will open. - action_url_target=_blank notes_url_target=_blank - - - - -# LOCK AUTHOR NAMES OPTION -# This option determines whether users can change the author name -# when submitting comments, scheduling downtime. If disabled, the -# author names will be locked into their contact name, as defined in Nagios. -# Values: 0 = allow editing author names -# 1 = lock author names (disallow editing) - lock_author_names=1 - - - - -# SPLUNK INTEGRATION OPTIONS -# These options allow you to enable integration with Splunk -# in the web interface. If enabled, you'll be presented with -# "Splunk It" links in various places in the CGIs (log file, -# alert history, host/service detail, etc). Useful if you're -# trying to research why a particular problem occurred. -# For more information on Splunk, visit http://www.splunk.com/ - -# This option determines whether the Splunk integration is enabled -# Values: 0 = disable Splunk integration -# 1 = enable Splunk integration - -#enable_splunk_integration=1 - - -# This option should be the URL used to access your instance of Splunk - -#splunk_url=http://127.0.0.1:8000/ - - diff --git a/t/etc/empty-groups-error.cfg b/t/etc/empty-groups-error.cfg index 4220276..bedba4a 100644 --- a/t/etc/empty-groups-error.cfg +++ b/t/etc/empty-groups-error.cfg @@ -2,12 +2,10 @@ define command{ command_name dummy command_line /bin/true } - define timeperiod{ timeperiod_name never alias Never } - define contact{ contact_name dude host_notification_period never @@ -15,7 +13,6 @@ define contact{ service_notification_period never service_notification_commands dummy } - define host{ host_name fake alias Fake @@ -25,7 +22,6 @@ define host{ max_check_attempts 5 contacts dude } - define service{ name dummy-service service_description Dummy Service @@ -36,12 +32,10 @@ define service{ contacts dude host_name fake } - define hostgroup{ hostgroup_name generic-pc alias Generic PCs } - define host{ name generic-host hostgroups generic-pc diff --git a/t/etc/hosturgencies.cfg b/t/etc/hosturgencies.cfg index 53d9133..7f1efe1 100644 --- a/t/etc/hosturgencies.cfg +++ b/t/etc/hosturgencies.cfg @@ -8,7 +8,6 @@ define host { notification_interval 60 notification_period none } - define host { host_name host2 alias host2 test @@ -19,7 +18,6 @@ define host { notification_interval 60 notification_period none } - define host { host_name host3 alias host3 test @@ -30,7 +28,6 @@ define host { notification_interval 60 notification_period none } - define host { host_name host4 alias host4 test @@ -41,7 +38,6 @@ define host { notification_interval 60 notification_period none } - define service { host_name host1,host2,host3,host4 service_description Dummy service diff --git a/t/etc/minimal.cfg b/t/etc/minimal.cfg index abdb600..106d993 100644 --- a/t/etc/minimal.cfg +++ b/t/etc/minimal.cfg @@ -8,7 +8,6 @@ define host { notification_interval 60 notification_period none } - define host { host_name host2 alias host2 test @@ -19,7 +18,6 @@ define host { notification_interval 60 notification_period none } - define host { host_name host3 alias host3 test @@ -31,12 +29,10 @@ define host { notification_period none hostgroups +hosts-with-master-service } - define hostgroup { hostgroup_name hosts-with-master-service alias Hosts running a master service } - define service { host_name host1 service_description Dummy service @@ -49,7 +45,6 @@ define service { notification_period none contacts nagiosadmin } - define service { host_name host1,host2 service_description Uses important check command @@ -63,13 +58,11 @@ define service { contacts nagiosadmin use service-distributed } - define service { name service-distributed check_command !set_to_stale register 0 } - define service { hostgroup_name hosts-with-master-service service_description master-service @@ -82,7 +75,6 @@ define service { notification_period none contacts nagiosadmin } - define service { host_name host3 service_description dependent-service @@ -96,40 +88,33 @@ define service { contacts nagiosadmin servicegroups +services-depending-on-master-service } - define servicegroup { servicegroup_name services-depending-on-master-service alias Servicegroup for services depending on a "master" service on the same host } - define command { command_name set_to_stale command_line /usr/local/nagios/libexec/set_to_stale } - define command { command_name check_me command_line /usr/local/nagios/libexec/check_me } - define command { command_name with_continuation_lines command_line $USER1$/check_foo one\ two } - define command { command_name multiple_continuation_lines_with_spaces_intermingled command_line \ check_nrpe_arg!30!\ check_fs_ping!/mnt/account-p,/mnt/prepro-p,/mnt/webapp-ssl,/mnt/rollout-p } - define timeperiod { timeperiod_name none alias Nothing } - define contact { contact_name nagiosadmin host_notifications_enabled 0 @@ -141,12 +126,10 @@ define contact { host_notification_commands notify-none service_notification_commands notify-none } - define command { command_name notify-none command_line /usr/local/nagios/notifications/notify-none } - define contact { contact_name second host_notifications_enabled 0 @@ -164,17 +147,14 @@ define contactgroup { alias This causes a test failure by having a comma separated list before the empty contactgroup members nagiosadmin,second } - define contactgroup { contactgroup_name empty alias No members defined - this should pass validation } - define serviceescalation { host_name * service_description *,!Dummy service } - define servicedependency { service_description master-service dependent_servicegroup_name services-depending-on-master-service diff --git a/t/etc/nagios-empty-groups.cfg b/t/etc/nagios-empty-groups.cfg index e6eafe8..d477a50 100644 --- a/t/etc/nagios-empty-groups.cfg +++ b/t/etc/nagios-empty-groups.cfg @@ -1,1305 +1,101 @@ -############################################################################## -# -# NAGIOS.CFG - Sample Main Config File for Nagios 3.1.0 -# -# Read the documentation for more information on this configuration -# file. I've provided some comments here, but things may not be so -# clear without further explanation. -# -# Last Modified: 12-14-2008 -# -############################################################################## - - -# LOG FILE -# This is the main log file where service and host events are logged -# for historical purposes. This should be the first option specified -# in the config file!!! - -log_file=var/nagios.log - - - -# OBJECT CONFIGURATION FILE(S) -# These are the object configuration files in which you define hosts, -# host groups, contacts, contact groups, services, etc. -# You can split your object definitions across several config files -# if you wish (as shown below), or keep them all in a single config file. - -# Note: A relative path here is relative to the location of the overall nagios.cfg file, -# not relative to the current directory +log_file=../var/nagios.log cfg_file=empty-groups-error.cfg - -# You can also tell Nagios to process all config files (with a .cfg -# extension) in a particular directory by using the cfg_dir -# directive as shown below: - -#cfg_dir=/usr/local/nagios/etc/servers -#cfg_dir=/usr/local/nagios/etc/printers -#cfg_dir=/usr/local/nagios/etc/switches -#cfg_dir=/usr/local/nagios/etc/routers - - - - -# OBJECT CACHE FILE -# This option determines where object definitions are cached when -# Nagios starts/restarts. The CGIs read object definitions from -# this cache file (rather than looking at the object config files -# directly) in order to prevent inconsistencies that can occur -# when the config files are modified after Nagios starts. - -object_cache_file=var/objects.cache - - - -# PRE-CACHED OBJECT FILE -# This options determines the location of the precached object file. -# If you run Nagios with the -p command line option, it will preprocess -# your object configuration file(s) and write the cached config to this -# file. You can then start Nagios with the -u option to have it read -# object definitions from this precached file, rather than the standard -# object configuration files (see the cfg_file and cfg_dir options above). -# Using a precached object file can speed up the time needed to (re)start -# the Nagios process if you've got a large and/or complex configuration. -# Read the documentation section on optimizing Nagios to find our more -# about how this feature works. - -precached_object_file=var/objects.precache - - - -# RESOURCE FILE -# This is an optional resource file that contains $USERx$ macro -# definitions. Multiple resource files can be specified by using -# multiple resource_file definitions. The CGIs will not attempt to -# read the contents of resource files, so information that is -# considered to be sensitive (usernames, passwords, etc) can be -# defined as macros in this file and restrictive permissions (600) -# can be placed on this file. - -resource_file=etc/resource.cfg - - - -# STATUS FILE -# This is where the current status of all monitored services and -# hosts is stored. Its contents are read and processed by the CGIs. -# The contents of the status file are deleted every time Nagios -# restarts. - -status_file=var/status.dat - - - -# STATUS FILE UPDATE INTERVAL -# This option determines the frequency (in seconds) that -# Nagios will periodically dump program, host, and -# service status data. - +object_cache_file=../var/objects.cache +precached_object_file=../var/objects.precache +resource_file=resource.cfg +status_file=../var/status.dat status_update_interval=10 - - - -# NAGIOS USER -# This determines the effective user that Nagios should run as. -# You can either supply a username or a UID. - nagios_user=nagios - - - -# NAGIOS GROUP -# This determines the effective group that Nagios should run as. -# You can either supply a group name or a GID. - nagios_group=nagios - - - -# EXTERNAL COMMAND OPTION -# This option allows you to specify whether or not Nagios should check -# for external commands (in the command file defined below). By default -# Nagios will *not* check for external commands, just to be on the -# cautious side. If you want to be able to use the CGI command interface -# you will have to enable this. -# Values: 0 = disable commands, 1 = enable commands - check_external_commands=1 - - - -# EXTERNAL COMMAND CHECK INTERVAL -# This is the interval at which Nagios should check for external commands. -# This value works of the interval_length you specify later. If you leave -# that at its default value of 60 (seconds), a value of 1 here will cause -# Nagios to check for external commands every minute. If you specify a -# number followed by an "s" (i.e. 15s), this will be interpreted to mean -# actual seconds rather than a multiple of the interval_length variable. -# Note: In addition to reading the external command file at regularly -# scheduled intervals, Nagios will also check for external commands after -# event handlers are executed. -# NOTE: Setting this value to -1 causes Nagios to check the external -# command file as often as possible. - -#command_check_interval=15s -command_check_interval=-1 - - - -# EXTERNAL COMMAND FILE -# This is the file that Nagios checks for external command requests. -# It is also where the command CGI will write commands that are submitted -# by users, so it must be writeable by the user that the web server -# is running as (usually 'nobody'). Permissions should be set at the -# directory level instead of on the file, as the file is deleted every -# time its contents are processed. - -command_file=var/rw/nagios.cmd - - - -# EXTERNAL COMMAND BUFFER SLOTS -# This settings is used to tweak the number of items or "slots" that -# the Nagios daemon should allocate to the buffer that holds incoming -# external commands before they are processed. As external commands -# are processed by the daemon, they are removed from the buffer. - -external_command_buffer_slots=4096 - - - -# LOCK FILE -# This is the lockfile that Nagios will use to store its PID number -# in when it is running in daemon mode. - -lock_file=var/nagios.lock - - - -# TEMP FILE -# This is a temporary file that is used as scratch space when Nagios -# updates the status log, cleans the comment file, etc. This file -# is created, used, and deleted throughout the time that Nagios is -# running. - -temp_file=var/nagios.tmp - - - -# TEMP PATH -# This is path where Nagios can create temp files for service and -# host check results, etc. - +command_file=../var/rw/nagios.cmd +lock_file=../var/nagios.lock +temp_file=../var/nagios.tmp temp_path=/tmp - - - -# EVENT BROKER OPTIONS -# Controls what (if any) data gets sent to the event broker. -# Values: 0 = Broker nothing -# -1 = Broker everything -# = See documentation - event_broker_options=-1 - - - -# EVENT BROKER MODULE(S) -# This directive is used to specify an event broker module that should -# by loaded by Nagios at startup. Use multiple directives if you want -# to load more than one module. Arguments that should be passed to -# the module at startup are seperated from the module path by a space. -# -#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -# WARNING !!! WARNING !!! WARNING !!! WARNING !!! WARNING !!! WARNING -#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -# -# Do NOT overwrite modules while they are being used by Nagios or Nagios -# will crash in a fiery display of SEGFAULT glory. This is a bug/limitation -# either in dlopen(), the kernel, and/or the filesystem. And maybe Nagios... -# -# The correct/safe way of updating a module is by using one of these methods: -# 1. Shutdown Nagios, replace the module file, restart Nagios -# 2. Delete the original module file, move the new module file into place, restart Nagios -# -# Example: -# -# broker_module= [moduleargs] - -#broker_module=/somewhere/module1.o -#broker_module=/somewhere/module2.o arg1 arg2=3 debug=0 - - - -# LOG ROTATION METHOD -# This is the log rotation method that Nagios should use to rotate -# the main log file. Values are as follows.. -# n = None - don't rotate the log -# h = Hourly rotation (top of the hour) -# d = Daily rotation (midnight every day) -# w = Weekly rotation (midnight on Saturday evening) -# m = Monthly rotation (midnight last day of month) - log_rotation_method=d - - - -# LOG ARCHIVE PATH -# This is the directory where archived (rotated) log files should be -# placed (assuming you've chosen to do log rotation). - log_archive_path=var/archives - - - -# LOGGING OPTIONS -# If you want messages logged to the syslog facility, as well as the -# Nagios log file set this option to 1. If not, set it to 0. - use_syslog=1 - - - -# NOTIFICATION LOGGING OPTION -# If you don't want notifications to be logged, set this value to 0. -# If notifications should be logged, set the value to 1. - log_notifications=1 - - - -# SERVICE RETRY LOGGING OPTION -# If you don't want service check retries to be logged, set this value -# to 0. If retries should be logged, set the value to 1. - log_service_retries=1 - - - -# HOST RETRY LOGGING OPTION -# If you don't want host check retries to be logged, set this value to -# 0. If retries should be logged, set the value to 1. - log_host_retries=1 - - - -# EVENT HANDLER LOGGING OPTION -# If you don't want host and service event handlers to be logged, set -# this value to 0. If event handlers should be logged, set the value -# to 1. - log_event_handlers=1 - - - -# INITIAL STATES LOGGING OPTION -# If you want Nagios to log all initial host and service states to -# the main log file (the first time the service or host is checked) -# you can enable this option by setting this value to 1. If you -# are not using an external application that does long term state -# statistics reporting, you do not need to enable this option. In -# this case, set the value to 0. - log_initial_states=0 - - - -# EXTERNAL COMMANDS LOGGING OPTION -# If you don't want Nagios to log external commands, set this value -# to 0. If external commands should be logged, set this value to 1. -# Note: This option does not include logging of passive service -# checks - see the option below for controlling whether or not -# passive checks are logged. - log_external_commands=1 - - - -# PASSIVE CHECKS LOGGING OPTION -# If you don't want Nagios to log passive host and service checks, set -# this value to 0. If passive checks should be logged, set -# this value to 1. - log_passive_checks=1 - - - -# GLOBAL HOST AND SERVICE EVENT HANDLERS -# These options allow you to specify a host and service event handler -# command that is to be run for every host or service state change. -# The global event handler is executed immediately prior to the event -# handler that you have optionally specified in each host or -# service definition. The command argument is the short name of a -# command definition that you define in your host configuration file. -# Read the HTML docs for more information. - -#global_host_event_handler=somecommand -#global_service_event_handler=somecommand - - - -# SERVICE INTER-CHECK DELAY METHOD -# This is the method that Nagios should use when initially -# "spreading out" service checks when it starts monitoring. The -# default is to use smart delay calculation, which will try to -# space all service checks out evenly to minimize CPU load. -# Using the dumb setting will cause all checks to be scheduled -# at the same time (with no delay between them)! This is not a -# good thing for production, but is useful when testing the -# parallelization functionality. -# n = None - don't use any delay between checks -# d = Use a "dumb" delay of 1 second between checks -# s = Use "smart" inter-check delay calculation -# x.xx = Use an inter-check delay of x.xx seconds - service_inter_check_delay_method=s - - - -# MAXIMUM SERVICE CHECK SPREAD -# This variable determines the timeframe (in minutes) from the -# program start time that an initial check of all services should -# be completed. Default is 30 minutes. - max_service_check_spread=30 - - - -# SERVICE CHECK INTERLEAVE FACTOR -# This variable determines how service checks are interleaved. -# Interleaving the service checks allows for a more even -# distribution of service checks and reduced load on remote -# hosts. Setting this value to 1 is equivalent to how versions -# of Nagios previous to 0.0.5 did service checks. Set this -# value to s (smart) for automatic calculation of the interleave -# factor unless you have a specific reason to change it. -# s = Use "smart" interleave factor calculation -# x = Use an interleave factor of x, where x is a -# number greater than or equal to 1. - service_interleave_factor=s - - - -# HOST INTER-CHECK DELAY METHOD -# This is the method that Nagios should use when initially -# "spreading out" host checks when it starts monitoring. The -# default is to use smart delay calculation, which will try to -# space all host checks out evenly to minimize CPU load. -# Using the dumb setting will cause all checks to be scheduled -# at the same time (with no delay between them)! -# n = None - don't use any delay between checks -# d = Use a "dumb" delay of 1 second between checks -# s = Use "smart" inter-check delay calculation -# x.xx = Use an inter-check delay of x.xx seconds - host_inter_check_delay_method=s - - - -# MAXIMUM HOST CHECK SPREAD -# This variable determines the timeframe (in minutes) from the -# program start time that an initial check of all hosts should -# be completed. Default is 30 minutes. - max_host_check_spread=30 - - - -# MAXIMUM CONCURRENT SERVICE CHECKS -# This option allows you to specify the maximum number of -# service checks that can be run in parallel at any given time. -# Specifying a value of 1 for this variable essentially prevents -# any service checks from being parallelized. A value of 0 -# will not restrict the number of concurrent checks that are -# being executed. - max_concurrent_checks=0 - - - -# HOST AND SERVICE CHECK REAPER FREQUENCY -# This is the frequency (in seconds!) that Nagios will process -# the results of host and service checks. - check_result_reaper_frequency=10 - - - - -# MAX CHECK RESULT REAPER TIME -# This is the max amount of time (in seconds) that a single -# check result reaper event will be allowed to run before -# returning control back to Nagios so it can perform other -# duties. - max_check_result_reaper_time=30 - - - - -# CHECK RESULT PATH -# This is directory where Nagios stores the results of host and -# service checks that have not yet been processed. -# -# Note: Make sure that only one instance of Nagios has access -# to this directory! - -check_result_path=var/spool/checkresults - - - - -# MAX CHECK RESULT FILE AGE -# This option determines the maximum age (in seconds) which check -# result files are considered to be valid. Files older than this -# threshold will be mercilessly deleted without further processing. - +check_result_path=/tmp max_check_result_file_age=3600 - - - - -# CACHED HOST CHECK HORIZON -# This option determines the maximum amount of time (in seconds) -# that the state of a previous host check is considered current. -# Cached host states (from host checks that were performed more -# recently that the timeframe specified by this value) can immensely -# improve performance in regards to the host check logic. -# Too high of a value for this option may result in inaccurate host -# states being used by Nagios, while a lower value may result in a -# performance hit for host checks. Use a value of 0 to disable host -# check caching. - cached_host_check_horizon=15 - - - -# CACHED SERVICE CHECK HORIZON -# This option determines the maximum amount of time (in seconds) -# that the state of a previous service check is considered current. -# Cached service states (from service checks that were performed more -# recently that the timeframe specified by this value) can immensely -# improve performance in regards to predictive dependency checks. -# Use a value of 0 to disable service check caching. - cached_service_check_horizon=15 - - - -# ENABLE PREDICTIVE HOST DEPENDENCY CHECKS -# This option determines whether or not Nagios will attempt to execute -# checks of hosts when it predicts that future dependency logic test -# may be needed. These predictive checks can help ensure that your -# host dependency logic works well. -# Values: -# 0 = Disable predictive checks -# 1 = Enable predictive checks (default) - enable_predictive_host_dependency_checks=1 - - - -# ENABLE PREDICTIVE SERVICE DEPENDENCY CHECKS -# This option determines whether or not Nagios will attempt to execute -# checks of service when it predicts that future dependency logic test -# may be needed. These predictive checks can help ensure that your -# service dependency logic works well. -# Values: -# 0 = Disable predictive checks -# 1 = Enable predictive checks (default) - enable_predictive_service_dependency_checks=1 - - - -# SOFT STATE DEPENDENCIES -# This option determines whether or not Nagios will use soft state -# information when checking host and service dependencies. Normally -# Nagios will only use the latest hard host or service state when -# checking dependencies. If you want it to use the latest state (regardless -# of whether its a soft or hard state type), enable this option. -# Values: -# 0 = Don't use soft state dependencies (default) -# 1 = Use soft state dependencies - soft_state_dependencies=0 - - - -# TIME CHANGE ADJUSTMENT THRESHOLDS -# These options determine when Nagios will react to detected changes -# in system time (either forward or backwards). - -#time_change_threshold=900 - - - -# AUTO-RESCHEDULING OPTION -# This option determines whether or not Nagios will attempt to -# automatically reschedule active host and service checks to -# "smooth" them out over time. This can help balance the load on -# the monitoring server. -# WARNING: THIS IS AN EXPERIMENTAL FEATURE - IT CAN DEGRADE -# PERFORMANCE, RATHER THAN INCREASE IT, IF USED IMPROPERLY - auto_reschedule_checks=0 - - - -# AUTO-RESCHEDULING INTERVAL -# This option determines how often (in seconds) Nagios will -# attempt to automatically reschedule checks. This option only -# has an effect if the auto_reschedule_checks option is enabled. -# Default is 30 seconds. -# WARNING: THIS IS AN EXPERIMENTAL FEATURE - IT CAN DEGRADE -# PERFORMANCE, RATHER THAN INCREASE IT, IF USED IMPROPERLY - auto_rescheduling_interval=30 - - - -# AUTO-RESCHEDULING WINDOW -# This option determines the "window" of time (in seconds) that -# Nagios will look at when automatically rescheduling checks. -# Only host and service checks that occur in the next X seconds -# (determined by this variable) will be rescheduled. This option -# only has an effect if the auto_reschedule_checks option is -# enabled. Default is 180 seconds (3 minutes). -# WARNING: THIS IS AN EXPERIMENTAL FEATURE - IT CAN DEGRADE -# PERFORMANCE, RATHER THAN INCREASE IT, IF USED IMPROPERLY - auto_rescheduling_window=180 - - - -# SLEEP TIME -# This is the number of seconds to sleep between checking for system -# events and service checks that need to be run. - -sleep_time=0.25 - - - -# TIMEOUT VALUES -# These options control how much time Nagios will allow various -# types of commands to execute before killing them off. Options -# are available for controlling maximum time allotted for -# service checks, host checks, event handlers, notifications, the -# ocsp command, and performance data commands. All values are in -# seconds. - service_check_timeout=60 host_check_timeout=30 event_handler_timeout=30 notification_timeout=30 ocsp_timeout=5 perfdata_timeout=5 - - - -# RETAIN STATE INFORMATION -# This setting determines whether or not Nagios will save state -# information for services and hosts before it shuts down. Upon -# startup Nagios will reload all saved service and host state -# information before starting to monitor. This is useful for -# maintaining long-term data on state statistics, etc, but will -# slow Nagios down a bit when it (re)starts. Since its only -# a one-time penalty, I think its well worth the additional -# startup delay. - retain_state_information=1 - - - -# STATE RETENTION FILE -# This is the file that Nagios should use to store host and -# service state information before it shuts down. The state -# information in this file is also read immediately prior to -# starting to monitor the network when Nagios is restarted. -# This file is used only if the preserve_state_information -# variable is set to 1. - state_retention_file=var/retention.dat - - - -# RETENTION DATA UPDATE INTERVAL -# This setting determines how often (in minutes) that Nagios -# will automatically save retention data during normal operation. -# If you set this value to 0, Nagios will not save retention -# data at regular interval, but it will still save retention -# data before shutting down or restarting. If you have disabled -# state retention, this option has no effect. - retention_update_interval=60 - - - -# USE RETAINED PROGRAM STATE -# This setting determines whether or not Nagios will set -# program status variables based on the values saved in the -# retention file. If you want to use retained program status -# information, set this value to 1. If not, set this value -# to 0. - use_retained_program_state=1 - - - -# USE RETAINED SCHEDULING INFO -# This setting determines whether or not Nagios will retain -# the scheduling info (next check time) for hosts and services -# based on the values saved in the retention file. If you -# If you want to use retained scheduling info, set this -# value to 1. If not, set this value to 0. - use_retained_scheduling_info=1 - - - -# RETAINED ATTRIBUTE MASKS (ADVANCED FEATURE) -# The following variables are used to specify specific host and -# service attributes that should *not* be retained by Nagios during -# program restarts. -# -# The values of the masks are bitwise ANDs of values specified -# by the "MODATTR_" definitions found in include/common.h. -# For example, if you do not want the current enabled/disabled state -# of flap detection and event handlers for hosts to be retained, you -# would use a value of 24 for the host attribute mask... -# MODATTR_EVENT_HANDLER_ENABLED (8) + MODATTR_FLAP_DETECTION_ENABLED (16) = 24 - -# This mask determines what host attributes are not retained retained_host_attribute_mask=0 - -# This mask determines what service attributes are not retained retained_service_attribute_mask=0 - -# These two masks determine what process attributes are not retained. -# There are two masks, because some process attributes have host and service -# options. For example, you can disable active host checks, but leave active -# service checks enabled. retained_process_host_attribute_mask=0 retained_process_service_attribute_mask=0 - -# These two masks determine what contact attributes are not retained. -# There are two masks, because some contact attributes have host and -# service options. For example, you can disable host notifications for -# a contact, but leave service notifications enabled for them. retained_contact_host_attribute_mask=0 retained_contact_service_attribute_mask=0 - - - -# INTERVAL LENGTH -# This is the seconds per unit interval as used in the -# host/contact/service configuration files. Setting this to 60 means -# that each interval is one minute long (60 seconds). Other settings -# have not been tested much, so your mileage is likely to vary... - interval_length=60 - - - -# CHECK FOR UPDATES -# This option determines whether Nagios will automatically check to -# see if new updates (releases) are available. It is recommend that you -# enable this option to ensure that you stay on top of the latest critical -# patches to Nagios. Nagios is critical to you - make sure you keep it in -# good shape. Nagios will check once a day for new updates. Data collected -# by Nagios Enterprises from the update check is processed in accordance -# with our privacy policy - see http://api.nagios.org for details. - check_for_updates=1 - - - -# BARE UPDATE CHECK -# This option deterines what data Nagios will send to api.nagios.org when -# it checks for updates. By default, Nagios will send information on the -# current version of Nagios you have installed, as well as an indicator as -# to whether this was a new installation or not. Nagios Enterprises uses -# this data to determine the number of users running specific version of -# Nagios. Enable this option if you do not want this information to be sent. - bare_update_check=0 - - - -# AGGRESSIVE HOST CHECKING OPTION -# If you don't want to turn on aggressive host checking features, set -# this value to 0 (the default). Otherwise set this value to 1 to -# enable the aggressive check option. Read the docs for more info -# on what aggressive host check is or check out the source code in -# base/checks.c - use_aggressive_host_checking=0 - - - -# SERVICE CHECK EXECUTION OPTION -# This determines whether or not Nagios will actively execute -# service checks when it initially starts. If this option is -# disabled, checks are not actively made, but Nagios can still -# receive and process passive check results that come in. Unless -# you're implementing redundant hosts or have a special need for -# disabling the execution of service checks, leave this enabled! -# Values: 1 = enable checks, 0 = disable checks - execute_service_checks=1 - - - -# PASSIVE SERVICE CHECK ACCEPTANCE OPTION -# This determines whether or not Nagios will accept passive -# service checks results when it initially (re)starts. -# Values: 1 = accept passive checks, 0 = reject passive checks - accept_passive_service_checks=1 - - - -# HOST CHECK EXECUTION OPTION -# This determines whether or not Nagios will actively execute -# host checks when it initially starts. If this option is -# disabled, checks are not actively made, but Nagios can still -# receive and process passive check results that come in. Unless -# you're implementing redundant hosts or have a special need for -# disabling the execution of host checks, leave this enabled! -# Values: 1 = enable checks, 0 = disable checks - execute_host_checks=1 - - - -# PASSIVE HOST CHECK ACCEPTANCE OPTION -# This determines whether or not Nagios will accept passive -# host checks results when it initially (re)starts. -# Values: 1 = accept passive checks, 0 = reject passive checks - accept_passive_host_checks=1 - - - -# NOTIFICATIONS OPTION -# This determines whether or not Nagios will sent out any host or -# service notifications when it is initially (re)started. -# Values: 1 = enable notifications, 0 = disable notifications - enable_notifications=1 - - - -# EVENT HANDLER USE OPTION -# This determines whether or not Nagios will run any host or -# service event handlers when it is initially (re)started. Unless -# you're implementing redundant hosts, leave this option enabled. -# Values: 1 = enable event handlers, 0 = disable event handlers - enable_event_handlers=1 - - - -# PROCESS PERFORMANCE DATA OPTION -# This determines whether or not Nagios will process performance -# data returned from service and host checks. If this option is -# enabled, host performance data will be processed using the -# host_perfdata_command (defined below) and service performance -# data will be processed using the service_perfdata_command (also -# defined below). Read the HTML docs for more information on -# performance data. -# Values: 1 = process performance data, 0 = do not process performance data - process_performance_data=0 - - - -# HOST AND SERVICE PERFORMANCE DATA PROCESSING COMMANDS -# These commands are run after every host and service check is -# performed. These commands are executed only if the -# enable_performance_data option (above) is set to 1. The command -# argument is the short name of a command definition that you -# define in your host configuration file. Read the HTML docs for -# more information on performance data. - -#host_perfdata_command=process-host-perfdata -#service_perfdata_command=process-service-perfdata - - - -# HOST AND SERVICE PERFORMANCE DATA FILES -# These files are used to store host and service performance data. -# Performance data is only written to these files if the -# enable_performance_data option (above) is set to 1. - -#host_perfdata_file=/tmp/host-perfdata -#service_perfdata_file=/tmp/service-perfdata - - - -# HOST AND SERVICE PERFORMANCE DATA FILE TEMPLATES -# These options determine what data is written (and how) to the -# performance data files. The templates may contain macros, special -# characters (\t for tab, \r for carriage return, \n for newline) -# and plain text. A newline is automatically added after each write -# to the performance data file. Some examples of what you can do are -# shown below. - -#host_perfdata_file_template=[HOSTPERFDATA]\t$TIMET$\t$HOSTNAME$\t$HOSTEXECUTIONTIME$\t$HOSTOUTPUT$\t$HOSTPERFDATA$ -#service_perfdata_file_template=[SERVICEPERFDATA]\t$TIMET$\t$HOSTNAME$\t$SERVICEDESC$\t$SERVICEEXECUTIONTIME$\t$SERVICELATENCY$\t$SERVICEOUTPUT$\t$SERVICEPERFDATA$ - - - -# HOST AND SERVICE PERFORMANCE DATA FILE MODES -# This option determines whether or not the host and service -# performance data files are opened in write ("w") or append ("a") -# mode. If you want to use named pipes, you should use the special -# pipe ("p") mode which avoid blocking at startup, otherwise you will -# likely want the defult append ("a") mode. - -#host_perfdata_file_mode=a -#service_perfdata_file_mode=a - - - -# HOST AND SERVICE PERFORMANCE DATA FILE PROCESSING INTERVAL -# These options determine how often (in seconds) the host and service -# performance data files are processed using the commands defined -# below. A value of 0 indicates the files should not be periodically -# processed. - -#host_perfdata_file_processing_interval=0 -#service_perfdata_file_processing_interval=0 - - - -# HOST AND SERVICE PERFORMANCE DATA FILE PROCESSING COMMANDS -# These commands are used to periodically process the host and -# service performance data files. The interval at which the -# processing occurs is determined by the options above. - -#host_perfdata_file_processing_command=process-host-perfdata-file -#service_perfdata_file_processing_command=process-service-perfdata-file - - - -# OBSESS OVER SERVICE CHECKS OPTION -# This determines whether or not Nagios will obsess over service -# checks and run the ocsp_command defined below. Unless you're -# planning on implementing distributed monitoring, do not enable -# this option. Read the HTML docs for more information on -# implementing distributed monitoring. -# Values: 1 = obsess over services, 0 = do not obsess (default) - obsess_over_services=0 - - - -# OBSESSIVE COMPULSIVE SERVICE PROCESSOR COMMAND -# This is the command that is run for every service check that is -# processed by Nagios. This command is executed only if the -# obsess_over_services option (above) is set to 1. The command -# argument is the short name of a command definition that you -# define in your host configuration file. Read the HTML docs for -# more information on implementing distributed monitoring. - -#ocsp_command=somecommand - - - -# OBSESS OVER HOST CHECKS OPTION -# This determines whether or not Nagios will obsess over host -# checks and run the ochp_command defined below. Unless you're -# planning on implementing distributed monitoring, do not enable -# this option. Read the HTML docs for more information on -# implementing distributed monitoring. -# Values: 1 = obsess over hosts, 0 = do not obsess (default) - obsess_over_hosts=0 - - - -# OBSESSIVE COMPULSIVE HOST PROCESSOR COMMAND -# This is the command that is run for every host check that is -# processed by Nagios. This command is executed only if the -# obsess_over_hosts option (above) is set to 1. The command -# argument is the short name of a command definition that you -# define in your host configuration file. Read the HTML docs for -# more information on implementing distributed monitoring. - -#ochp_command=somecommand - - - -# TRANSLATE PASSIVE HOST CHECKS OPTION -# This determines whether or not Nagios will translate -# DOWN/UNREACHABLE passive host check results into their proper -# state for this instance of Nagios. This option is useful -# if you have distributed or failover monitoring setup. In -# these cases your other Nagios servers probably have a different -# "view" of the network, with regards to the parent/child relationship -# of hosts. If a distributed monitoring server thinks a host -# is DOWN, it may actually be UNREACHABLE from the point of -# this Nagios instance. Enabling this option will tell Nagios -# to translate any DOWN or UNREACHABLE host states it receives -# passively into the correct state from the view of this server. -# Values: 1 = perform translation, 0 = do not translate (default) - translate_passive_host_checks=0 - - - -# PASSIVE HOST CHECKS ARE SOFT OPTION -# This determines whether or not Nagios will treat passive host -# checks as being HARD or SOFT. By default, a passive host check -# result will put a host into a HARD state type. This can be changed -# by enabling this option. -# Values: 0 = passive checks are HARD, 1 = passive checks are SOFT - passive_host_checks_are_soft=0 - - - -# ORPHANED HOST/SERVICE CHECK OPTIONS -# These options determine whether or not Nagios will periodically -# check for orphaned host service checks. Since service checks are -# not rescheduled until the results of their previous execution -# instance are processed, there exists a possibility that some -# checks may never get rescheduled. A similar situation exists for -# host checks, although the exact scheduling details differ a bit -# from service checks. Orphaned checks seem to be a rare -# problem and should not happen under normal circumstances. -# If you have problems with service checks never getting -# rescheduled, make sure you have orphaned service checks enabled. -# Values: 1 = enable checks, 0 = disable checks - check_for_orphaned_services=1 check_for_orphaned_hosts=1 - - - -# SERVICE FRESHNESS CHECK OPTION -# This option determines whether or not Nagios will periodically -# check the "freshness" of service results. Enabling this option -# is useful for ensuring passive checks are received in a timely -# manner. -# Values: 1 = enabled freshness checking, 0 = disable freshness checking - check_service_freshness=1 - - - -# SERVICE FRESHNESS CHECK INTERVAL -# This setting determines how often (in seconds) Nagios will -# check the "freshness" of service check results. If you have -# disabled service freshness checking, this option has no effect. - service_freshness_check_interval=60 - - - -# HOST FRESHNESS CHECK OPTION -# This option determines whether or not Nagios will periodically -# check the "freshness" of host results. Enabling this option -# is useful for ensuring passive checks are received in a timely -# manner. -# Values: 1 = enabled freshness checking, 0 = disable freshness checking - check_host_freshness=0 - - - -# HOST FRESHNESS CHECK INTERVAL -# This setting determines how often (in seconds) Nagios will -# check the "freshness" of host check results. If you have -# disabled host freshness checking, this option has no effect. - host_freshness_check_interval=60 - - - - -# ADDITIONAL FRESHNESS THRESHOLD LATENCY -# This setting determines the number of seconds that Nagios -# will add to any host and service freshness thresholds that -# it calculates (those not explicitly specified by the user). - additional_freshness_latency=15 - - - - -# FLAP DETECTION OPTION -# This option determines whether or not Nagios will try -# and detect hosts and services that are "flapping". -# Flapping occurs when a host or service changes between -# states too frequently. When Nagios detects that a -# host or service is flapping, it will temporarily suppress -# notifications for that host/service until it stops -# flapping. Flap detection is very experimental, so read -# the HTML documentation before enabling this feature! -# Values: 1 = enable flap detection -# 0 = disable flap detection (default) - enable_flap_detection=1 - - - -# FLAP DETECTION THRESHOLDS FOR HOSTS AND SERVICES -# Read the HTML documentation on flap detection for -# an explanation of what this option does. This option -# has no effect if flap detection is disabled. - low_service_flap_threshold=5.0 high_service_flap_threshold=20.0 low_host_flap_threshold=5.0 high_host_flap_threshold=20.0 - - - -# DATE FORMAT OPTION -# This option determines how short dates are displayed. Valid options -# include: -# us (MM-DD-YYYY HH:MM:SS) -# euro (DD-MM-YYYY HH:MM:SS) -# iso8601 (YYYY-MM-DD HH:MM:SS) -# strict-iso8601 (YYYY-MM-DDTHH:MM:SS) -# - date_format=us - - - - -# TIMEZONE OFFSET -# This option is used to override the default timezone that this -# instance of Nagios runs in. If not specified, Nagios will use -# the system configured timezone. -# -# NOTE: In order to display the correct timezone in the CGIs, you -# will also need to alter the Apache directives for the CGI path -# to include your timezone. Example: -# -# -# SetEnv TZ "Australia/Brisbane" -# ... -# - -#use_timezone=US/Mountain -#use_timezone=Australia/Brisbane - - - - -# P1.PL FILE LOCATION -# This value determines where the p1.pl perl script (used by the -# embedded Perl interpreter) is located. If you didn't compile -# Nagios with embedded Perl support, this option has no effect. - -p1_file=/usr/local/nagios/bin/p1.pl - - - -# EMBEDDED PERL INTERPRETER OPTION -# This option determines whether or not the embedded Perl interpreter -# will be enabled during runtime. This option has no effect if Nagios -# has not been compiled with support for embedded Perl. -# Values: 0 = disable interpreter, 1 = enable interpreter - -enable_embedded_perl=1 - - - -# EMBEDDED PERL USAGE OPTION -# This option determines whether or not Nagios will process Perl plugins -# and scripts with the embedded Perl interpreter if the plugins/scripts -# do not explicitly indicate whether or not it is okay to do so. Read -# the HTML documentation on the embedded Perl interpreter for more -# information on how this option works. - -use_embedded_perl_implicitly=1 - - - -# ILLEGAL OBJECT NAME CHARACTERS -# This option allows you to specify illegal characters that cannot -# be used in host names, service descriptions, or names of other -# object types. - illegal_object_name_chars=`~!$%^&*|'"<>?,()= - - - -# ILLEGAL MACRO OUTPUT CHARACTERS -# This option allows you to specify illegal characters that are -# stripped from macros before being used in notifications, event -# handlers, etc. This DOES NOT affect macros used in service or -# host check commands. -# The following macros are stripped of the characters you specify: -# $HOSTOUTPUT$ -# $HOSTPERFDATA$ -# $HOSTACKAUTHOR$ -# $HOSTACKCOMMENT$ -# $SERVICEOUTPUT$ -# $SERVICEPERFDATA$ -# $SERVICEACKAUTHOR$ -# $SERVICEACKCOMMENT$ - illegal_macro_output_chars=`~$&|'"<> - - - -# REGULAR EXPRESSION MATCHING -# This option controls whether or not regular expression matching -# takes place in the object config files. Regular expression -# matching is used to match host, hostgroup, service, and service -# group names/descriptions in some fields of various object types. -# Values: 1 = enable regexp matching, 0 = disable regexp matching - use_regexp_matching=0 - - - -# "TRUE" REGULAR EXPRESSION MATCHING -# This option controls whether or not "true" regular expression -# matching takes place in the object config files. This option -# only has an effect if regular expression matching is enabled -# (see above). If this option is DISABLED, regular expression -# matching only occurs if a string contains wildcard characters -# (* and ?). If the option is ENABLED, regexp matching occurs -# all the time (which can be annoying). -# Values: 1 = enable true matching, 0 = disable true matching - use_true_regexp_matching=0 - - - -# ADMINISTRATOR EMAIL/PAGER ADDRESSES -# The email and pager address of a global administrator (likely you). -# Nagios never uses these values itself, but you can access them by -# using the $ADMINEMAIL$ and $ADMINPAGER$ macros in your notification -# commands. - admin_email=nagios@localhost admin_pager=pagenagios@localhost - - - -# DAEMON CORE DUMP OPTION -# This option determines whether or not Nagios is allowed to create -# a core dump when it runs as a daemon. Note that it is generally -# considered bad form to allow this, but it may be useful for -# debugging purposes. Enabling this option doesn't guarantee that -# a core file will be produced, but that's just life... -# Values: 1 - Allow core dumps -# 0 - Do not allow core dumps (default) - daemon_dumps_core=0 - - - -# LARGE INSTALLATION TWEAKS OPTION -# This option determines whether or not Nagios will take some shortcuts -# which can save on memory and CPU usage in large Nagios installations. -# Read the documentation for more information on the benefits/tradeoffs -# of enabling this option. -# Values: 1 - Enabled tweaks -# 0 - Disable tweaks (default) - use_large_installation_tweaks=0 - - - -# ENABLE ENVIRONMENT MACROS -# This option determines whether or not Nagios will make all standard -# macros available as environment variables when host/service checks -# and system commands (event handlers, notifications, etc.) are -# executed. Enabling this option can cause performance issues in -# large installations, as it will consume a bit more memory and (more -# importantly) consume more CPU. -# Values: 1 - Enable environment variable macros (default) -# 0 - Disable environment variable macros - enable_environment_macros=1 - - - -# CHILD PROCESS MEMORY OPTION -# This option determines whether or not Nagios will free memory in -# child processes (processed used to execute system commands and host/ -# service checks). If you specify a value here, it will override -# program defaults. -# Value: 1 - Free memory in child processes -# 0 - Do not free memory in child processes - -#free_child_process_memory=1 - - - -# CHILD PROCESS FORKING BEHAVIOR -# This option determines how Nagios will fork child processes -# (used to execute system commands and host/service checks). Normally -# child processes are fork()ed twice, which provides a very high level -# of isolation from problems. Fork()ing once is probably enough and will -# save a great deal on CPU usage (in large installs), so you might -# want to consider using this. If you specify a value here, it will -# program defaults. -# Value: 1 - Child processes fork() twice -# 0 - Child processes fork() just once - -#child_processes_fork_twice=1 - - - -# DEBUG LEVEL -# This option determines how much (if any) debugging information will -# be written to the debug file. OR values together to log multiple -# types of information. -# Values: -# -1 = Everything -# 0 = Nothing -# 1 = Functions -# 2 = Configuration -# 4 = Process information -# 8 = Scheduled events -# 16 = Host/service checks -# 32 = Notifications -# 64 = Event broker -# 128 = External commands -# 256 = Commands -# 512 = Scheduled downtime -# 1024 = Comments -# 2048 = Macros - debug_level=0 - - - -# DEBUG VERBOSITY -# This option determines how verbose the debug log out will be. -# Values: 0 = Brief output -# 1 = More detailed -# 2 = Very detailed - debug_verbosity=1 - - - -# DEBUG FILE -# This option determines where Nagios should write debugging information. - debug_file=var/nagios.debug - - - -# MAX DEBUG FILE SIZE -# This option determines the maximum size (in bytes) of the debug file. If -# the file grows larger than this size, it will be renamed with a .old -# extension. If a file already exists with a .old extension it will -# automatically be deleted. This helps ensure your disk space usage doesn't -# get out of control when debugging Nagios. - max_debug_file_size=1000000 diff --git a/t/etc/nagios-hosturgencies.cfg b/t/etc/nagios-hosturgencies.cfg index ffc13ba..3708b15 100644 --- a/t/etc/nagios-hosturgencies.cfg +++ b/t/etc/nagios-hosturgencies.cfg @@ -1,1307 +1,101 @@ -############################################################################## -# -# NAGIOS.CFG - Sample Main Config File for Nagios 3.1.0 -# -# Read the documentation for more information on this configuration -# file. I've provided some comments here, but things may not be so -# clear without further explanation. -# -# Last Modified: 12-14-2008 -# -############################################################################## - - -# LOG FILE -# This is the main log file where service and host events are logged -# for historical purposes. This should be the first option specified -# in the config file!!! - -log_file=var/nagios.log - - - -# OBJECT CONFIGURATION FILE(S) -# These are the object configuration files in which you define hosts, -# host groups, contacts, contact groups, services, etc. -# You can split your object definitions across several config files -# if you wish (as shown below), or keep them all in a single config file. - -# Note: A relative path here is relative to the location of the overall nagios.cfg file, -# not relative to the current directory +log_file=../var/nagios.log cfg_file=hosturgencies.cfg - -# You can also tell Nagios to process all config files (with a .cfg -# extension) in a particular directory by using the cfg_dir -# directive as shown below: - -#cfg_dir=/usr/local/nagios/etc/servers -#cfg_dir=/usr/local/nagios/etc/printers -#cfg_dir=/usr/local/nagios/etc/switches -#cfg_dir=/usr/local/nagios/etc/routers - - - - -# OBJECT CACHE FILE -# This option determines where object definitions are cached when -# Nagios starts/restarts. The CGIs read object definitions from -# this cache file (rather than looking at the object config files -# directly) in order to prevent inconsistencies that can occur -# when the config files are modified after Nagios starts. - -object_cache_file=var/objects.cache.hosturgencies - - - -# PRE-CACHED OBJECT FILE -# This options determines the location of the precached object file. -# If you run Nagios with the -p command line option, it will preprocess -# your object configuration file(s) and write the cached config to this -# file. You can then start Nagios with the -u option to have it read -# object definitions from this precached file, rather than the standard -# object configuration files (see the cfg_file and cfg_dir options above). -# Using a precached object file can speed up the time needed to (re)start -# the Nagios process if you've got a large and/or complex configuration. -# Read the documentation section on optimizing Nagios to find our more -# about how this feature works. - -precached_object_file=var/objects.precache.hosturgencies - - - -# RESOURCE FILE -# This is an optional resource file that contains $USERx$ macro -# definitions. Multiple resource files can be specified by using -# multiple resource_file definitions. The CGIs will not attempt to -# read the contents of resource files, so information that is -# considered to be sensitive (usernames, passwords, etc) can be -# defined as macros in this file and restrictive permissions (600) -# can be placed on this file. - -resource_file=etc/resource.cfg - - - -# STATUS FILE -# This is where the current status of all monitored services and -# hosts is stored. Its contents are read and processed by the CGIs. -# The contents of the status file are deleted every time Nagios -# restarts. - -status_file=var/status-hosturgencies.dat - - - -# STATUS FILE UPDATE INTERVAL -# This option determines the frequency (in seconds) that -# Nagios will periodically dump program, host, and -# service status data. - +object_cache_file=../var/objects.cache.hosturgencies +precached_object_file=../var/objects.precache.hosturgencies +resource_file=resource.cfg +status_file=../var/status-hosturgencies.dat status_update_interval=10 - - - -# NAGIOS USER -# This determines the effective user that Nagios should run as. -# You can either supply a username or a UID. - nagios_user=nagios - - - -# NAGIOS GROUP -# This determines the effective group that Nagios should run as. -# You can either supply a group name or a GID. - nagios_group=nagios - - - -# EXTERNAL COMMAND OPTION -# This option allows you to specify whether or not Nagios should check -# for external commands (in the command file defined below). By default -# Nagios will *not* check for external commands, just to be on the -# cautious side. If you want to be able to use the CGI command interface -# you will have to enable this. -# Values: 0 = disable commands, 1 = enable commands - check_external_commands=1 - - - -# EXTERNAL COMMAND CHECK INTERVAL -# This is the interval at which Nagios should check for external commands. -# This value works of the interval_length you specify later. If you leave -# that at its default value of 60 (seconds), a value of 1 here will cause -# Nagios to check for external commands every minute. If you specify a -# number followed by an "s" (i.e. 15s), this will be interpreted to mean -# actual seconds rather than a multiple of the interval_length variable. -# Note: In addition to reading the external command file at regularly -# scheduled intervals, Nagios will also check for external commands after -# event handlers are executed. -# NOTE: Setting this value to -1 causes Nagios to check the external -# command file as often as possible. - -#command_check_interval=15s -command_check_interval=-1 - - - -# EXTERNAL COMMAND FILE -# This is the file that Nagios checks for external command requests. -# It is also where the command CGI will write commands that are submitted -# by users, so it must be writeable by the user that the web server -# is running as (usually 'nobody'). Permissions should be set at the -# directory level instead of on the file, as the file is deleted every -# time its contents are processed. - -command_file=var/rw/nagios.cmd - - - -# EXTERNAL COMMAND BUFFER SLOTS -# This settings is used to tweak the number of items or "slots" that -# the Nagios daemon should allocate to the buffer that holds incoming -# external commands before they are processed. As external commands -# are processed by the daemon, they are removed from the buffer. - -external_command_buffer_slots=4096 - - - -# LOCK FILE -# This is the lockfile that Nagios will use to store its PID number -# in when it is running in daemon mode. - -lock_file=var/nagios.lock - - - -# TEMP FILE -# This is a temporary file that is used as scratch space when Nagios -# updates the status log, cleans the comment file, etc. This file -# is created, used, and deleted throughout the time that Nagios is -# running. - -temp_file=var/nagios.tmp - - - -# TEMP PATH -# This is path where Nagios can create temp files for service and -# host check results, etc. - +command_file=../var/rw/nagios.cmd +lock_file=../var/nagios.lock +temp_file=../var/nagios.tmp temp_path=/tmp - - - -# EVENT BROKER OPTIONS -# Controls what (if any) data gets sent to the event broker. -# Values: 0 = Broker nothing -# -1 = Broker everything -# = See documentation - event_broker_options=-1 - - - -# EVENT BROKER MODULE(S) -# This directive is used to specify an event broker module that should -# by loaded by Nagios at startup. Use multiple directives if you want -# to load more than one module. Arguments that should be passed to -# the module at startup are seperated from the module path by a space. -# -#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -# WARNING !!! WARNING !!! WARNING !!! WARNING !!! WARNING !!! WARNING -#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -# -# Do NOT overwrite modules while they are being used by Nagios or Nagios -# will crash in a fiery display of SEGFAULT glory. This is a bug/limitation -# either in dlopen(), the kernel, and/or the filesystem. And maybe Nagios... -# -# The correct/safe way of updating a module is by using one of these methods: -# 1. Shutdown Nagios, replace the module file, restart Nagios -# 2. Delete the original module file, move the new module file into place, restart Nagios -# -# Example: -# -# broker_module= [moduleargs] - -#broker_module=/somewhere/module1.o -#broker_module=/somewhere/module2.o arg1 arg2=3 debug=0 - - - -# LOG ROTATION METHOD -# This is the log rotation method that Nagios should use to rotate -# the main log file. Values are as follows.. -# n = None - don't rotate the log -# h = Hourly rotation (top of the hour) -# d = Daily rotation (midnight every day) -# w = Weekly rotation (midnight on Saturday evening) -# m = Monthly rotation (midnight last day of month) - log_rotation_method=d - - - -# LOG ARCHIVE PATH -# This is the directory where archived (rotated) log files should be -# placed (assuming you've chosen to do log rotation). - log_archive_path=var/archives - - - -# LOGGING OPTIONS -# If you want messages logged to the syslog facility, as well as the -# Nagios log file set this option to 1. If not, set it to 0. - use_syslog=1 - - - -# NOTIFICATION LOGGING OPTION -# If you don't want notifications to be logged, set this value to 0. -# If notifications should be logged, set the value to 1. - log_notifications=1 - - - -# SERVICE RETRY LOGGING OPTION -# If you don't want service check retries to be logged, set this value -# to 0. If retries should be logged, set the value to 1. - log_service_retries=1 - - - -# HOST RETRY LOGGING OPTION -# If you don't want host check retries to be logged, set this value to -# 0. If retries should be logged, set the value to 1. - log_host_retries=1 - - - -# EVENT HANDLER LOGGING OPTION -# If you don't want host and service event handlers to be logged, set -# this value to 0. If event handlers should be logged, set the value -# to 1. - log_event_handlers=1 - - - -# INITIAL STATES LOGGING OPTION -# If you want Nagios to log all initial host and service states to -# the main log file (the first time the service or host is checked) -# you can enable this option by setting this value to 1. If you -# are not using an external application that does long term state -# statistics reporting, you do not need to enable this option. In -# this case, set the value to 0. - log_initial_states=0 - - - -# EXTERNAL COMMANDS LOGGING OPTION -# If you don't want Nagios to log external commands, set this value -# to 0. If external commands should be logged, set this value to 1. -# Note: This option does not include logging of passive service -# checks - see the option below for controlling whether or not -# passive checks are logged. - log_external_commands=1 - - - -# PASSIVE CHECKS LOGGING OPTION -# If you don't want Nagios to log passive host and service checks, set -# this value to 0. If passive checks should be logged, set -# this value to 1. - log_passive_checks=1 - - - -# GLOBAL HOST AND SERVICE EVENT HANDLERS -# These options allow you to specify a host and service event handler -# command that is to be run for every host or service state change. -# The global event handler is executed immediately prior to the event -# handler that you have optionally specified in each host or -# service definition. The command argument is the short name of a -# command definition that you define in your host configuration file. -# Read the HTML docs for more information. - -#global_host_event_handler=somecommand -#global_service_event_handler=somecommand - - - -# SERVICE INTER-CHECK DELAY METHOD -# This is the method that Nagios should use when initially -# "spreading out" service checks when it starts monitoring. The -# default is to use smart delay calculation, which will try to -# space all service checks out evenly to minimize CPU load. -# Using the dumb setting will cause all checks to be scheduled -# at the same time (with no delay between them)! This is not a -# good thing for production, but is useful when testing the -# parallelization functionality. -# n = None - don't use any delay between checks -# d = Use a "dumb" delay of 1 second between checks -# s = Use "smart" inter-check delay calculation -# x.xx = Use an inter-check delay of x.xx seconds - service_inter_check_delay_method=s - - - -# MAXIMUM SERVICE CHECK SPREAD -# This variable determines the timeframe (in minutes) from the -# program start time that an initial check of all services should -# be completed. Default is 30 minutes. - max_service_check_spread=30 - - - -# SERVICE CHECK INTERLEAVE FACTOR -# This variable determines how service checks are interleaved. -# Interleaving the service checks allows for a more even -# distribution of service checks and reduced load on remote -# hosts. Setting this value to 1 is equivalent to how versions -# of Nagios previous to 0.0.5 did service checks. Set this -# value to s (smart) for automatic calculation of the interleave -# factor unless you have a specific reason to change it. -# s = Use "smart" interleave factor calculation -# x = Use an interleave factor of x, where x is a -# number greater than or equal to 1. - service_interleave_factor=s - - - -# HOST INTER-CHECK DELAY METHOD -# This is the method that Nagios should use when initially -# "spreading out" host checks when it starts monitoring. The -# default is to use smart delay calculation, which will try to -# space all host checks out evenly to minimize CPU load. -# Using the dumb setting will cause all checks to be scheduled -# at the same time (with no delay between them)! -# n = None - don't use any delay between checks -# d = Use a "dumb" delay of 1 second between checks -# s = Use "smart" inter-check delay calculation -# x.xx = Use an inter-check delay of x.xx seconds - host_inter_check_delay_method=s - - - -# MAXIMUM HOST CHECK SPREAD -# This variable determines the timeframe (in minutes) from the -# program start time that an initial check of all hosts should -# be completed. Default is 30 minutes. - max_host_check_spread=30 - - - -# MAXIMUM CONCURRENT SERVICE CHECKS -# This option allows you to specify the maximum number of -# service checks that can be run in parallel at any given time. -# Specifying a value of 1 for this variable essentially prevents -# any service checks from being parallelized. A value of 0 -# will not restrict the number of concurrent checks that are -# being executed. - max_concurrent_checks=0 - - - -# HOST AND SERVICE CHECK REAPER FREQUENCY -# This is the frequency (in seconds!) that Nagios will process -# the results of host and service checks. - check_result_reaper_frequency=10 - - - - -# MAX CHECK RESULT REAPER TIME -# This is the max amount of time (in seconds) that a single -# check result reaper event will be allowed to run before -# returning control back to Nagios so it can perform other -# duties. - max_check_result_reaper_time=30 - - - - -# CHECK RESULT PATH -# This is directory where Nagios stores the results of host and -# service checks that have not yet been processed. -# -# Note: Make sure that only one instance of Nagios has access -# to this directory! - -check_result_path=var/spool/checkresults - - - - -# MAX CHECK RESULT FILE AGE -# This option determines the maximum age (in seconds) which check -# result files are considered to be valid. Files older than this -# threshold will be mercilessly deleted without further processing. - +check_result_path=/tmp max_check_result_file_age=3600 - - - - -# CACHED HOST CHECK HORIZON -# This option determines the maximum amount of time (in seconds) -# that the state of a previous host check is considered current. -# Cached host states (from host checks that were performed more -# recently that the timeframe specified by this value) can immensely -# improve performance in regards to the host check logic. -# Too high of a value for this option may result in inaccurate host -# states being used by Nagios, while a lower value may result in a -# performance hit for host checks. Use a value of 0 to disable host -# check caching. - cached_host_check_horizon=15 - - - -# CACHED SERVICE CHECK HORIZON -# This option determines the maximum amount of time (in seconds) -# that the state of a previous service check is considered current. -# Cached service states (from service checks that were performed more -# recently that the timeframe specified by this value) can immensely -# improve performance in regards to predictive dependency checks. -# Use a value of 0 to disable service check caching. - cached_service_check_horizon=15 - - - -# ENABLE PREDICTIVE HOST DEPENDENCY CHECKS -# This option determines whether or not Nagios will attempt to execute -# checks of hosts when it predicts that future dependency logic test -# may be needed. These predictive checks can help ensure that your -# host dependency logic works well. -# Values: -# 0 = Disable predictive checks -# 1 = Enable predictive checks (default) - enable_predictive_host_dependency_checks=1 - - - -# ENABLE PREDICTIVE SERVICE DEPENDENCY CHECKS -# This option determines whether or not Nagios will attempt to execute -# checks of service when it predicts that future dependency logic test -# may be needed. These predictive checks can help ensure that your -# service dependency logic works well. -# Values: -# 0 = Disable predictive checks -# 1 = Enable predictive checks (default) - enable_predictive_service_dependency_checks=1 - - - -# SOFT STATE DEPENDENCIES -# This option determines whether or not Nagios will use soft state -# information when checking host and service dependencies. Normally -# Nagios will only use the latest hard host or service state when -# checking dependencies. If you want it to use the latest state (regardless -# of whether its a soft or hard state type), enable this option. -# Values: -# 0 = Don't use soft state dependencies (default) -# 1 = Use soft state dependencies - soft_state_dependencies=0 - - - -# TIME CHANGE ADJUSTMENT THRESHOLDS -# These options determine when Nagios will react to detected changes -# in system time (either forward or backwards). - -#time_change_threshold=900 - - - -# AUTO-RESCHEDULING OPTION -# This option determines whether or not Nagios will attempt to -# automatically reschedule active host and service checks to -# "smooth" them out over time. This can help balance the load on -# the monitoring server. -# WARNING: THIS IS AN EXPERIMENTAL FEATURE - IT CAN DEGRADE -# PERFORMANCE, RATHER THAN INCREASE IT, IF USED IMPROPERLY - auto_reschedule_checks=0 - - - -# AUTO-RESCHEDULING INTERVAL -# This option determines how often (in seconds) Nagios will -# attempt to automatically reschedule checks. This option only -# has an effect if the auto_reschedule_checks option is enabled. -# Default is 30 seconds. -# WARNING: THIS IS AN EXPERIMENTAL FEATURE - IT CAN DEGRADE -# PERFORMANCE, RATHER THAN INCREASE IT, IF USED IMPROPERLY - auto_rescheduling_interval=30 - - - -# AUTO-RESCHEDULING WINDOW -# This option determines the "window" of time (in seconds) that -# Nagios will look at when automatically rescheduling checks. -# Only host and service checks that occur in the next X seconds -# (determined by this variable) will be rescheduled. This option -# only has an effect if the auto_reschedule_checks option is -# enabled. Default is 180 seconds (3 minutes). -# WARNING: THIS IS AN EXPERIMENTAL FEATURE - IT CAN DEGRADE -# PERFORMANCE, RATHER THAN INCREASE IT, IF USED IMPROPERLY - auto_rescheduling_window=180 - - - -# SLEEP TIME -# This is the number of seconds to sleep between checking for system -# events and service checks that need to be run. - -sleep_time=0.25 - - - -# TIMEOUT VALUES -# These options control how much time Nagios will allow various -# types of commands to execute before killing them off. Options -# are available for controlling maximum time allotted for -# service checks, host checks, event handlers, notifications, the -# ocsp command, and performance data commands. All values are in -# seconds. - service_check_timeout=60 host_check_timeout=30 event_handler_timeout=30 notification_timeout=30 ocsp_timeout=5 perfdata_timeout=5 - - - -# RETAIN STATE INFORMATION -# This setting determines whether or not Nagios will save state -# information for services and hosts before it shuts down. Upon -# startup Nagios will reload all saved service and host state -# information before starting to monitor. This is useful for -# maintaining long-term data on state statistics, etc, but will -# slow Nagios down a bit when it (re)starts. Since its only -# a one-time penalty, I think its well worth the additional -# startup delay. - retain_state_information=1 - - - -# STATE RETENTION FILE -# This is the file that Nagios should use to store host and -# service state information before it shuts down. The state -# information in this file is also read immediately prior to -# starting to monitor the network when Nagios is restarted. -# This file is used only if the preserve_state_information -# variable is set to 1. - -state_retention_file=var/retention.dat - - - -# RETENTION DATA UPDATE INTERVAL -# This setting determines how often (in minutes) that Nagios -# will automatically save retention data during normal operation. -# If you set this value to 0, Nagios will not save retention -# data at regular interval, but it will still save retention -# data before shutting down or restarting. If you have disabled -# state retention, this option has no effect. - +state_retention_file=../var/retention.dat retention_update_interval=60 - - - -# USE RETAINED PROGRAM STATE -# This setting determines whether or not Nagios will set -# program status variables based on the values saved in the -# retention file. If you want to use retained program status -# information, set this value to 1. If not, set this value -# to 0. - use_retained_program_state=1 - - - -# USE RETAINED SCHEDULING INFO -# This setting determines whether or not Nagios will retain -# the scheduling info (next check time) for hosts and services -# based on the values saved in the retention file. If you -# If you want to use retained scheduling info, set this -# value to 1. If not, set this value to 0. - use_retained_scheduling_info=1 - - - -# RETAINED ATTRIBUTE MASKS (ADVANCED FEATURE) -# The following variables are used to specify specific host and -# service attributes that should *not* be retained by Nagios during -# program restarts. -# -# The values of the masks are bitwise ANDs of values specified -# by the "MODATTR_" definitions found in include/common.h. -# For example, if you do not want the current enabled/disabled state -# of flap detection and event handlers for hosts to be retained, you -# would use a value of 24 for the host attribute mask... -# MODATTR_EVENT_HANDLER_ENABLED (8) + MODATTR_FLAP_DETECTION_ENABLED (16) = 24 - -# This mask determines what host attributes are not retained retained_host_attribute_mask=0 - -# This mask determines what service attributes are not retained retained_service_attribute_mask=0 - -# These two masks determine what process attributes are not retained. -# There are two masks, because some process attributes have host and service -# options. For example, you can disable active host checks, but leave active -# service checks enabled. retained_process_host_attribute_mask=0 retained_process_service_attribute_mask=0 - -# These two masks determine what contact attributes are not retained. -# There are two masks, because some contact attributes have host and -# service options. For example, you can disable host notifications for -# a contact, but leave service notifications enabled for them. retained_contact_host_attribute_mask=0 retained_contact_service_attribute_mask=0 - - - -# INTERVAL LENGTH -# This is the seconds per unit interval as used in the -# host/contact/service configuration files. Setting this to 60 means -# that each interval is one minute long (60 seconds). Other settings -# have not been tested much, so your mileage is likely to vary... - interval_length=60 - - - -# CHECK FOR UPDATES -# This option determines whether Nagios will automatically check to -# see if new updates (releases) are available. It is recommend that you -# enable this option to ensure that you stay on top of the latest critical -# patches to Nagios. Nagios is critical to you - make sure you keep it in -# good shape. Nagios will check once a day for new updates. Data collected -# by Nagios Enterprises from the update check is processed in accordance -# with our privacy policy - see http://api.nagios.org for details. - check_for_updates=1 - - - -# BARE UPDATE CHECK -# This option deterines what data Nagios will send to api.nagios.org when -# it checks for updates. By default, Nagios will send information on the -# current version of Nagios you have installed, as well as an indicator as -# to whether this was a new installation or not. Nagios Enterprises uses -# this data to determine the number of users running specific version of -# Nagios. Enable this option if you do not want this information to be sent. - bare_update_check=0 - - - -# AGGRESSIVE HOST CHECKING OPTION -# If you don't want to turn on aggressive host checking features, set -# this value to 0 (the default). Otherwise set this value to 1 to -# enable the aggressive check option. Read the docs for more info -# on what aggressive host check is or check out the source code in -# base/checks.c - use_aggressive_host_checking=0 - - - -# SERVICE CHECK EXECUTION OPTION -# This determines whether or not Nagios will actively execute -# service checks when it initially starts. If this option is -# disabled, checks are not actively made, but Nagios can still -# receive and process passive check results that come in. Unless -# you're implementing redundant hosts or have a special need for -# disabling the execution of service checks, leave this enabled! -# Values: 1 = enable checks, 0 = disable checks - execute_service_checks=1 - - - -# PASSIVE SERVICE CHECK ACCEPTANCE OPTION -# This determines whether or not Nagios will accept passive -# service checks results when it initially (re)starts. -# Values: 1 = accept passive checks, 0 = reject passive checks - accept_passive_service_checks=1 - - - -# HOST CHECK EXECUTION OPTION -# This determines whether or not Nagios will actively execute -# host checks when it initially starts. If this option is -# disabled, checks are not actively made, but Nagios can still -# receive and process passive check results that come in. Unless -# you're implementing redundant hosts or have a special need for -# disabling the execution of host checks, leave this enabled! -# Values: 1 = enable checks, 0 = disable checks - execute_host_checks=1 - - - -# PASSIVE HOST CHECK ACCEPTANCE OPTION -# This determines whether or not Nagios will accept passive -# host checks results when it initially (re)starts. -# Values: 1 = accept passive checks, 0 = reject passive checks - accept_passive_host_checks=1 - - - -# NOTIFICATIONS OPTION -# This determines whether or not Nagios will sent out any host or -# service notifications when it is initially (re)started. -# Values: 1 = enable notifications, 0 = disable notifications - enable_notifications=1 - - - -# EVENT HANDLER USE OPTION -# This determines whether or not Nagios will run any host or -# service event handlers when it is initially (re)started. Unless -# you're implementing redundant hosts, leave this option enabled. -# Values: 1 = enable event handlers, 0 = disable event handlers - enable_event_handlers=1 - - - -# PROCESS PERFORMANCE DATA OPTION -# This determines whether or not Nagios will process performance -# data returned from service and host checks. If this option is -# enabled, host performance data will be processed using the -# host_perfdata_command (defined below) and service performance -# data will be processed using the service_perfdata_command (also -# defined below). Read the HTML docs for more information on -# performance data. -# Values: 1 = process performance data, 0 = do not process performance data - process_performance_data=0 - - - -# HOST AND SERVICE PERFORMANCE DATA PROCESSING COMMANDS -# These commands are run after every host and service check is -# performed. These commands are executed only if the -# enable_performance_data option (above) is set to 1. The command -# argument is the short name of a command definition that you -# define in your host configuration file. Read the HTML docs for -# more information on performance data. - -#host_perfdata_command=process-host-perfdata -#service_perfdata_command=process-service-perfdata - - - -# HOST AND SERVICE PERFORMANCE DATA FILES -# These files are used to store host and service performance data. -# Performance data is only written to these files if the -# enable_performance_data option (above) is set to 1. - -#host_perfdata_file=/tmp/host-perfdata -#service_perfdata_file=/tmp/service-perfdata - - - -# HOST AND SERVICE PERFORMANCE DATA FILE TEMPLATES -# These options determine what data is written (and how) to the -# performance data files. The templates may contain macros, special -# characters (\t for tab, \r for carriage return, \n for newline) -# and plain text. A newline is automatically added after each write -# to the performance data file. Some examples of what you can do are -# shown below. - -#host_perfdata_file_template=[HOSTPERFDATA]\t$TIMET$\t$HOSTNAME$\t$HOSTEXECUTIONTIME$\t$HOSTOUTPUT$\t$HOSTPERFDATA$ -#service_perfdata_file_template=[SERVICEPERFDATA]\t$TIMET$\t$HOSTNAME$\t$SERVICEDESC$\t$SERVICEEXECUTIONTIME$\t$SERVICELATENCY$\t$SERVICEOUTPUT$\t$SERVICEPERFDATA$ - - - -# HOST AND SERVICE PERFORMANCE DATA FILE MODES -# This option determines whether or not the host and service -# performance data files are opened in write ("w") or append ("a") -# mode. If you want to use named pipes, you should use the special -# pipe ("p") mode which avoid blocking at startup, otherwise you will -# likely want the defult append ("a") mode. - -#host_perfdata_file_mode=a -#service_perfdata_file_mode=a - - - -# HOST AND SERVICE PERFORMANCE DATA FILE PROCESSING INTERVAL -# These options determine how often (in seconds) the host and service -# performance data files are processed using the commands defined -# below. A value of 0 indicates the files should not be periodically -# processed. - -#host_perfdata_file_processing_interval=0 -#service_perfdata_file_processing_interval=0 - - - -# HOST AND SERVICE PERFORMANCE DATA FILE PROCESSING COMMANDS -# These commands are used to periodically process the host and -# service performance data files. The interval at which the -# processing occurs is determined by the options above. - -#host_perfdata_file_processing_command=process-host-perfdata-file -#service_perfdata_file_processing_command=process-service-perfdata-file - - - -# OBSESS OVER SERVICE CHECKS OPTION -# This determines whether or not Nagios will obsess over service -# checks and run the ocsp_command defined below. Unless you're -# planning on implementing distributed monitoring, do not enable -# this option. Read the HTML docs for more information on -# implementing distributed monitoring. -# Values: 1 = obsess over services, 0 = do not obsess (default) - obsess_over_services=0 - - - -# OBSESSIVE COMPULSIVE SERVICE PROCESSOR COMMAND -# This is the command that is run for every service check that is -# processed by Nagios. This command is executed only if the -# obsess_over_services option (above) is set to 1. The command -# argument is the short name of a command definition that you -# define in your host configuration file. Read the HTML docs for -# more information on implementing distributed monitoring. - -#ocsp_command=somecommand - - - -# OBSESS OVER HOST CHECKS OPTION -# This determines whether or not Nagios will obsess over host -# checks and run the ochp_command defined below. Unless you're -# planning on implementing distributed monitoring, do not enable -# this option. Read the HTML docs for more information on -# implementing distributed monitoring. -# Values: 1 = obsess over hosts, 0 = do not obsess (default) - obsess_over_hosts=0 - - - -# OBSESSIVE COMPULSIVE HOST PROCESSOR COMMAND -# This is the command that is run for every host check that is -# processed by Nagios. This command is executed only if the -# obsess_over_hosts option (above) is set to 1. The command -# argument is the short name of a command definition that you -# define in your host configuration file. Read the HTML docs for -# more information on implementing distributed monitoring. - -#ochp_command=somecommand - - - -# TRANSLATE PASSIVE HOST CHECKS OPTION -# This determines whether or not Nagios will translate -# DOWN/UNREACHABLE passive host check results into their proper -# state for this instance of Nagios. This option is useful -# if you have distributed or failover monitoring setup. In -# these cases your other Nagios servers probably have a different -# "view" of the network, with regards to the parent/child relationship -# of hosts. If a distributed monitoring server thinks a host -# is DOWN, it may actually be UNREACHABLE from the point of -# this Nagios instance. Enabling this option will tell Nagios -# to translate any DOWN or UNREACHABLE host states it receives -# passively into the correct state from the view of this server. -# Values: 1 = perform translation, 0 = do not translate (default) - translate_passive_host_checks=0 - - - -# PASSIVE HOST CHECKS ARE SOFT OPTION -# This determines whether or not Nagios will treat passive host -# checks as being HARD or SOFT. By default, a passive host check -# result will put a host into a HARD state type. This can be changed -# by enabling this option. -# Values: 0 = passive checks are HARD, 1 = passive checks are SOFT - passive_host_checks_are_soft=0 - - - -# ORPHANED HOST/SERVICE CHECK OPTIONS -# These options determine whether or not Nagios will periodically -# check for orphaned host service checks. Since service checks are -# not rescheduled until the results of their previous execution -# instance are processed, there exists a possibility that some -# checks may never get rescheduled. A similar situation exists for -# host checks, although the exact scheduling details differ a bit -# from service checks. Orphaned checks seem to be a rare -# problem and should not happen under normal circumstances. -# If you have problems with service checks never getting -# rescheduled, make sure you have orphaned service checks enabled. -# Values: 1 = enable checks, 0 = disable checks - check_for_orphaned_services=1 check_for_orphaned_hosts=1 - - - -# SERVICE FRESHNESS CHECK OPTION -# This option determines whether or not Nagios will periodically -# check the "freshness" of service results. Enabling this option -# is useful for ensuring passive checks are received in a timely -# manner. -# Values: 1 = enabled freshness checking, 0 = disable freshness checking - check_service_freshness=1 - - - -# SERVICE FRESHNESS CHECK INTERVAL -# This setting determines how often (in seconds) Nagios will -# check the "freshness" of service check results. If you have -# disabled service freshness checking, this option has no effect. - service_freshness_check_interval=60 - - - -# HOST FRESHNESS CHECK OPTION -# This option determines whether or not Nagios will periodically -# check the "freshness" of host results. Enabling this option -# is useful for ensuring passive checks are received in a timely -# manner. -# Values: 1 = enabled freshness checking, 0 = disable freshness checking - check_host_freshness=0 - - - -# HOST FRESHNESS CHECK INTERVAL -# This setting determines how often (in seconds) Nagios will -# check the "freshness" of host check results. If you have -# disabled host freshness checking, this option has no effect. - host_freshness_check_interval=60 - - - - -# ADDITIONAL FRESHNESS THRESHOLD LATENCY -# This setting determines the number of seconds that Nagios -# will add to any host and service freshness thresholds that -# it calculates (those not explicitly specified by the user). - additional_freshness_latency=15 - - - - -# FLAP DETECTION OPTION -# This option determines whether or not Nagios will try -# and detect hosts and services that are "flapping". -# Flapping occurs when a host or service changes between -# states too frequently. When Nagios detects that a -# host or service is flapping, it will temporarily suppress -# notifications for that host/service until it stops -# flapping. Flap detection is very experimental, so read -# the HTML documentation before enabling this feature! -# Values: 1 = enable flap detection -# 0 = disable flap detection (default) - enable_flap_detection=1 - - - -# FLAP DETECTION THRESHOLDS FOR HOSTS AND SERVICES -# Read the HTML documentation on flap detection for -# an explanation of what this option does. This option -# has no effect if flap detection is disabled. - low_service_flap_threshold=5.0 high_service_flap_threshold=20.0 low_host_flap_threshold=5.0 high_host_flap_threshold=20.0 - - - -# DATE FORMAT OPTION -# This option determines how short dates are displayed. Valid options -# include: -# us (MM-DD-YYYY HH:MM:SS) -# euro (DD-MM-YYYY HH:MM:SS) -# iso8601 (YYYY-MM-DD HH:MM:SS) -# strict-iso8601 (YYYY-MM-DDTHH:MM:SS) -# - date_format=us - - - - -# TIMEZONE OFFSET -# This option is used to override the default timezone that this -# instance of Nagios runs in. If not specified, Nagios will use -# the system configured timezone. -# -# NOTE: In order to display the correct timezone in the CGIs, you -# will also need to alter the Apache directives for the CGI path -# to include your timezone. Example: -# -# -# SetEnv TZ "Australia/Brisbane" -# ... -# - -#use_timezone=US/Mountain -#use_timezone=Australia/Brisbane - - - - -# P1.PL FILE LOCATION -# This value determines where the p1.pl perl script (used by the -# embedded Perl interpreter) is located. If you didn't compile -# Nagios with embedded Perl support, this option has no effect. - -p1_file=/usr/local/nagios/bin/p1.pl - - - -# EMBEDDED PERL INTERPRETER OPTION -# This option determines whether or not the embedded Perl interpreter -# will be enabled during runtime. This option has no effect if Nagios -# has not been compiled with support for embedded Perl. -# Values: 0 = disable interpreter, 1 = enable interpreter - -enable_embedded_perl=1 - - - -# EMBEDDED PERL USAGE OPTION -# This option determines whether or not Nagios will process Perl plugins -# and scripts with the embedded Perl interpreter if the plugins/scripts -# do not explicitly indicate whether or not it is okay to do so. Read -# the HTML documentation on the embedded Perl interpreter for more -# information on how this option works. - -use_embedded_perl_implicitly=1 - - - -# ILLEGAL OBJECT NAME CHARACTERS -# This option allows you to specify illegal characters that cannot -# be used in host names, service descriptions, or names of other -# object types. - illegal_object_name_chars=`~!$%^&*|'"<>?,()= - - - -# ILLEGAL MACRO OUTPUT CHARACTERS -# This option allows you to specify illegal characters that are -# stripped from macros before being used in notifications, event -# handlers, etc. This DOES NOT affect macros used in service or -# host check commands. -# The following macros are stripped of the characters you specify: -# $HOSTOUTPUT$ -# $HOSTPERFDATA$ -# $HOSTACKAUTHOR$ -# $HOSTACKCOMMENT$ -# $SERVICEOUTPUT$ -# $SERVICEPERFDATA$ -# $SERVICEACKAUTHOR$ -# $SERVICEACKCOMMENT$ - illegal_macro_output_chars=`~$&|'"<> - - - -# REGULAR EXPRESSION MATCHING -# This option controls whether or not regular expression matching -# takes place in the object config files. Regular expression -# matching is used to match host, hostgroup, service, and service -# group names/descriptions in some fields of various object types. -# Values: 1 = enable regexp matching, 0 = disable regexp matching - use_regexp_matching=0 - - - -# "TRUE" REGULAR EXPRESSION MATCHING -# This option controls whether or not "true" regular expression -# matching takes place in the object config files. This option -# only has an effect if regular expression matching is enabled -# (see above). If this option is DISABLED, regular expression -# matching only occurs if a string contains wildcard characters -# (* and ?). If the option is ENABLED, regexp matching occurs -# all the time (which can be annoying). -# Values: 1 = enable true matching, 0 = disable true matching - use_true_regexp_matching=0 - - - -# ADMINISTRATOR EMAIL/PAGER ADDRESSES -# The email and pager address of a global administrator (likely you). -# Nagios never uses these values itself, but you can access them by -# using the $ADMINEMAIL$ and $ADMINPAGER$ macros in your notification -# commands. - admin_email=nagios@localhost admin_pager=pagenagios@localhost - - - -# DAEMON CORE DUMP OPTION -# This option determines whether or not Nagios is allowed to create -# a core dump when it runs as a daemon. Note that it is generally -# considered bad form to allow this, but it may be useful for -# debugging purposes. Enabling this option doesn't guarantee that -# a core file will be produced, but that's just life... -# Values: 1 - Allow core dumps -# 0 - Do not allow core dumps (default) - daemon_dumps_core=0 - - - -# LARGE INSTALLATION TWEAKS OPTION -# This option determines whether or not Nagios will take some shortcuts -# which can save on memory and CPU usage in large Nagios installations. -# Read the documentation for more information on the benefits/tradeoffs -# of enabling this option. -# Values: 1 - Enabled tweaks -# 0 - Disable tweaks (default) - use_large_installation_tweaks=0 - - - -# ENABLE ENVIRONMENT MACROS -# This option determines whether or not Nagios will make all standard -# macros available as environment variables when host/service checks -# and system commands (event handlers, notifications, etc.) are -# executed. Enabling this option can cause performance issues in -# large installations, as it will consume a bit more memory and (more -# importantly) consume more CPU. -# Values: 1 - Enable environment variable macros (default) -# 0 - Disable environment variable macros - enable_environment_macros=1 - - - -# CHILD PROCESS MEMORY OPTION -# This option determines whether or not Nagios will free memory in -# child processes (processed used to execute system commands and host/ -# service checks). If you specify a value here, it will override -# program defaults. -# Value: 1 - Free memory in child processes -# 0 - Do not free memory in child processes - -#free_child_process_memory=1 - - - -# CHILD PROCESS FORKING BEHAVIOR -# This option determines how Nagios will fork child processes -# (used to execute system commands and host/service checks). Normally -# child processes are fork()ed twice, which provides a very high level -# of isolation from problems. Fork()ing once is probably enough and will -# save a great deal on CPU usage (in large installs), so you might -# want to consider using this. If you specify a value here, it will -# program defaults. -# Value: 1 - Child processes fork() twice -# 0 - Child processes fork() just once - -#child_processes_fork_twice=1 - - - -# DEBUG LEVEL -# This option determines how much (if any) debugging information will -# be written to the debug file. OR values together to log multiple -# types of information. -# Values: -# -1 = Everything -# 0 = Nothing -# 1 = Functions -# 2 = Configuration -# 4 = Process information -# 8 = Scheduled events -# 16 = Host/service checks -# 32 = Notifications -# 64 = Event broker -# 128 = External commands -# 256 = Commands -# 512 = Scheduled downtime -# 1024 = Comments -# 2048 = Macros - debug_level=0 - - - -# DEBUG VERBOSITY -# This option determines how verbose the debug log out will be. -# Values: 0 = Brief output -# 1 = More detailed -# 2 = Very detailed - debug_verbosity=1 - - - -# DEBUG FILE -# This option determines where Nagios should write debugging information. - debug_file=var/nagios.debug - - - -# MAX DEBUG FILE SIZE -# This option determines the maximum size (in bytes) of the debug file. If -# the file grows larger than this size, it will be renamed with a .old -# extension. If a file already exists with a .old extension it will -# automatically be deleted. This helps ensure your disk space usage doesn't -# get out of control when debugging Nagios. - max_debug_file_size=1000000 - - diff --git a/t/etc/nagios-no-contactgroup.cfg b/t/etc/nagios-no-contactgroup.cfg index 519d8f8..3683aae 100644 --- a/t/etc/nagios-no-contactgroup.cfg +++ b/t/etc/nagios-no-contactgroup.cfg @@ -1,1307 +1,101 @@ -############################################################################## -# -# NAGIOS.CFG - Sample Main Config File for Nagios 3.1.0 -# -# Read the documentation for more information on this configuration -# file. I've provided some comments here, but things may not be so -# clear without further explanation. -# -# Last Modified: 12-14-2008 -# -############################################################################## - - -# LOG FILE -# This is the main log file where service and host events are logged -# for historical purposes. This should be the first option specified -# in the config file!!! - -log_file=/usr/local/nagios/var/nagios.log - - - -# OBJECT CONFIGURATION FILE(S) -# These are the object configuration files in which you define hosts, -# host groups, contacts, contact groups, services, etc. -# You can split your object definitions across several config files -# if you wish (as shown below), or keep them all in a single config file. - -# Note: A relative path here is relative to the location of the overall nagios.cfg file, -# not relative to the current directory +log_file=/tmp/nagios.log cfg_file=no-contactgroup-error.cfg - -# You can also tell Nagios to process all config files (with a .cfg -# extension) in a particular directory by using the cfg_dir -# directive as shown below: - -#cfg_dir=/usr/local/nagios/etc/servers -#cfg_dir=/usr/local/nagios/etc/printers -#cfg_dir=/usr/local/nagios/etc/switches -#cfg_dir=/usr/local/nagios/etc/routers - - - - -# OBJECT CACHE FILE -# This option determines where object definitions are cached when -# Nagios starts/restarts. The CGIs read object definitions from -# this cache file (rather than looking at the object config files -# directly) in order to prevent inconsistencies that can occur -# when the config files are modified after Nagios starts. - -object_cache_file=var/objects.cache - - - -# PRE-CACHED OBJECT FILE -# This options determines the location of the precached object file. -# If you run Nagios with the -p command line option, it will preprocess -# your object configuration file(s) and write the cached config to this -# file. You can then start Nagios with the -u option to have it read -# object definitions from this precached file, rather than the standard -# object configuration files (see the cfg_file and cfg_dir options above). -# Using a precached object file can speed up the time needed to (re)start -# the Nagios process if you've got a large and/or complex configuration. -# Read the documentation section on optimizing Nagios to find our more -# about how this feature works. - -precached_object_file=var/objects.precache - - - -# RESOURCE FILE -# This is an optional resource file that contains $USERx$ macro -# definitions. Multiple resource files can be specified by using -# multiple resource_file definitions. The CGIs will not attempt to -# read the contents of resource files, so information that is -# considered to be sensitive (usernames, passwords, etc) can be -# defined as macros in this file and restrictive permissions (600) -# can be placed on this file. - -resource_file=etc/resource.cfg - - - -# STATUS FILE -# This is where the current status of all monitored services and -# hosts is stored. Its contents are read and processed by the CGIs. -# The contents of the status file are deleted every time Nagios -# restarts. - -status_file=/usr/local/nagios/var/status.dat - - - -# STATUS FILE UPDATE INTERVAL -# This option determines the frequency (in seconds) that -# Nagios will periodically dump program, host, and -# service status data. - +object_cache_file=../var/objects.cache +precached_object_file=../var/objects.precache +resource_file=resource.cfg +status_file=../var/status.dat status_update_interval=10 - - - -# NAGIOS USER -# This determines the effective user that Nagios should run as. -# You can either supply a username or a UID. - nagios_user=nagios - - - -# NAGIOS GROUP -# This determines the effective group that Nagios should run as. -# You can either supply a group name or a GID. - nagios_group=nagios - - - -# EXTERNAL COMMAND OPTION -# This option allows you to specify whether or not Nagios should check -# for external commands (in the command file defined below). By default -# Nagios will *not* check for external commands, just to be on the -# cautious side. If you want to be able to use the CGI command interface -# you will have to enable this. -# Values: 0 = disable commands, 1 = enable commands - check_external_commands=1 - - - -# EXTERNAL COMMAND CHECK INTERVAL -# This is the interval at which Nagios should check for external commands. -# This value works of the interval_length you specify later. If you leave -# that at its default value of 60 (seconds), a value of 1 here will cause -# Nagios to check for external commands every minute. If you specify a -# number followed by an "s" (i.e. 15s), this will be interpreted to mean -# actual seconds rather than a multiple of the interval_length variable. -# Note: In addition to reading the external command file at regularly -# scheduled intervals, Nagios will also check for external commands after -# event handlers are executed. -# NOTE: Setting this value to -1 causes Nagios to check the external -# command file as often as possible. - -#command_check_interval=15s -command_check_interval=-1 - - - -# EXTERNAL COMMAND FILE -# This is the file that Nagios checks for external command requests. -# It is also where the command CGI will write commands that are submitted -# by users, so it must be writeable by the user that the web server -# is running as (usually 'nobody'). Permissions should be set at the -# directory level instead of on the file, as the file is deleted every -# time its contents are processed. - command_file=/usr/local/nagios/var/rw/nagios.cmd - - - -# EXTERNAL COMMAND BUFFER SLOTS -# This settings is used to tweak the number of items or "slots" that -# the Nagios daemon should allocate to the buffer that holds incoming -# external commands before they are processed. As external commands -# are processed by the daemon, they are removed from the buffer. - -external_command_buffer_slots=4096 - - - -# LOCK FILE -# This is the lockfile that Nagios will use to store its PID number -# in when it is running in daemon mode. - lock_file=/usr/local/nagios/var/nagios.lock - - - -# TEMP FILE -# This is a temporary file that is used as scratch space when Nagios -# updates the status log, cleans the comment file, etc. This file -# is created, used, and deleted throughout the time that Nagios is -# running. - temp_file=/usr/local/nagios/var/nagios.tmp - - - -# TEMP PATH -# This is path where Nagios can create temp files for service and -# host check results, etc. - temp_path=/tmp - - - -# EVENT BROKER OPTIONS -# Controls what (if any) data gets sent to the event broker. -# Values: 0 = Broker nothing -# -1 = Broker everything -# = See documentation - event_broker_options=-1 - - - -# EVENT BROKER MODULE(S) -# This directive is used to specify an event broker module that should -# by loaded by Nagios at startup. Use multiple directives if you want -# to load more than one module. Arguments that should be passed to -# the module at startup are seperated from the module path by a space. -# -#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -# WARNING !!! WARNING !!! WARNING !!! WARNING !!! WARNING !!! WARNING -#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -# -# Do NOT overwrite modules while they are being used by Nagios or Nagios -# will crash in a fiery display of SEGFAULT glory. This is a bug/limitation -# either in dlopen(), the kernel, and/or the filesystem. And maybe Nagios... -# -# The correct/safe way of updating a module is by using one of these methods: -# 1. Shutdown Nagios, replace the module file, restart Nagios -# 2. Delete the original module file, move the new module file into place, restart Nagios -# -# Example: -# -# broker_module= [moduleargs] - -#broker_module=/somewhere/module1.o -#broker_module=/somewhere/module2.o arg1 arg2=3 debug=0 - - - -# LOG ROTATION METHOD -# This is the log rotation method that Nagios should use to rotate -# the main log file. Values are as follows.. -# n = None - don't rotate the log -# h = Hourly rotation (top of the hour) -# d = Daily rotation (midnight every day) -# w = Weekly rotation (midnight on Saturday evening) -# m = Monthly rotation (midnight last day of month) - log_rotation_method=d - - - -# LOG ARCHIVE PATH -# This is the directory where archived (rotated) log files should be -# placed (assuming you've chosen to do log rotation). - log_archive_path=/usr/local/nagios/var/archives - - - -# LOGGING OPTIONS -# If you want messages logged to the syslog facility, as well as the -# Nagios log file set this option to 1. If not, set it to 0. - use_syslog=1 - - - -# NOTIFICATION LOGGING OPTION -# If you don't want notifications to be logged, set this value to 0. -# If notifications should be logged, set the value to 1. - log_notifications=1 - - - -# SERVICE RETRY LOGGING OPTION -# If you don't want service check retries to be logged, set this value -# to 0. If retries should be logged, set the value to 1. - log_service_retries=1 - - - -# HOST RETRY LOGGING OPTION -# If you don't want host check retries to be logged, set this value to -# 0. If retries should be logged, set the value to 1. - log_host_retries=1 - - - -# EVENT HANDLER LOGGING OPTION -# If you don't want host and service event handlers to be logged, set -# this value to 0. If event handlers should be logged, set the value -# to 1. - log_event_handlers=1 - - - -# INITIAL STATES LOGGING OPTION -# If you want Nagios to log all initial host and service states to -# the main log file (the first time the service or host is checked) -# you can enable this option by setting this value to 1. If you -# are not using an external application that does long term state -# statistics reporting, you do not need to enable this option. In -# this case, set the value to 0. - log_initial_states=0 - - - -# EXTERNAL COMMANDS LOGGING OPTION -# If you don't want Nagios to log external commands, set this value -# to 0. If external commands should be logged, set this value to 1. -# Note: This option does not include logging of passive service -# checks - see the option below for controlling whether or not -# passive checks are logged. - log_external_commands=1 - - - -# PASSIVE CHECKS LOGGING OPTION -# If you don't want Nagios to log passive host and service checks, set -# this value to 0. If passive checks should be logged, set -# this value to 1. - log_passive_checks=1 - - - -# GLOBAL HOST AND SERVICE EVENT HANDLERS -# These options allow you to specify a host and service event handler -# command that is to be run for every host or service state change. -# The global event handler is executed immediately prior to the event -# handler that you have optionally specified in each host or -# service definition. The command argument is the short name of a -# command definition that you define in your host configuration file. -# Read the HTML docs for more information. - -#global_host_event_handler=somecommand -#global_service_event_handler=somecommand - - - -# SERVICE INTER-CHECK DELAY METHOD -# This is the method that Nagios should use when initially -# "spreading out" service checks when it starts monitoring. The -# default is to use smart delay calculation, which will try to -# space all service checks out evenly to minimize CPU load. -# Using the dumb setting will cause all checks to be scheduled -# at the same time (with no delay between them)! This is not a -# good thing for production, but is useful when testing the -# parallelization functionality. -# n = None - don't use any delay between checks -# d = Use a "dumb" delay of 1 second between checks -# s = Use "smart" inter-check delay calculation -# x.xx = Use an inter-check delay of x.xx seconds - service_inter_check_delay_method=s - - - -# MAXIMUM SERVICE CHECK SPREAD -# This variable determines the timeframe (in minutes) from the -# program start time that an initial check of all services should -# be completed. Default is 30 minutes. - max_service_check_spread=30 - - - -# SERVICE CHECK INTERLEAVE FACTOR -# This variable determines how service checks are interleaved. -# Interleaving the service checks allows for a more even -# distribution of service checks and reduced load on remote -# hosts. Setting this value to 1 is equivalent to how versions -# of Nagios previous to 0.0.5 did service checks. Set this -# value to s (smart) for automatic calculation of the interleave -# factor unless you have a specific reason to change it. -# s = Use "smart" interleave factor calculation -# x = Use an interleave factor of x, where x is a -# number greater than or equal to 1. - service_interleave_factor=s - - - -# HOST INTER-CHECK DELAY METHOD -# This is the method that Nagios should use when initially -# "spreading out" host checks when it starts monitoring. The -# default is to use smart delay calculation, which will try to -# space all host checks out evenly to minimize CPU load. -# Using the dumb setting will cause all checks to be scheduled -# at the same time (with no delay between them)! -# n = None - don't use any delay between checks -# d = Use a "dumb" delay of 1 second between checks -# s = Use "smart" inter-check delay calculation -# x.xx = Use an inter-check delay of x.xx seconds - host_inter_check_delay_method=s - - - -# MAXIMUM HOST CHECK SPREAD -# This variable determines the timeframe (in minutes) from the -# program start time that an initial check of all hosts should -# be completed. Default is 30 minutes. - max_host_check_spread=30 - - - -# MAXIMUM CONCURRENT SERVICE CHECKS -# This option allows you to specify the maximum number of -# service checks that can be run in parallel at any given time. -# Specifying a value of 1 for this variable essentially prevents -# any service checks from being parallelized. A value of 0 -# will not restrict the number of concurrent checks that are -# being executed. - max_concurrent_checks=0 - - - -# HOST AND SERVICE CHECK REAPER FREQUENCY -# This is the frequency (in seconds!) that Nagios will process -# the results of host and service checks. - check_result_reaper_frequency=10 - - - - -# MAX CHECK RESULT REAPER TIME -# This is the max amount of time (in seconds) that a single -# check result reaper event will be allowed to run before -# returning control back to Nagios so it can perform other -# duties. - max_check_result_reaper_time=30 - - - - -# CHECK RESULT PATH -# This is directory where Nagios stores the results of host and -# service checks that have not yet been processed. -# -# Note: Make sure that only one instance of Nagios has access -# to this directory! - -check_result_path=var/spool/checkresults - - - - -# MAX CHECK RESULT FILE AGE -# This option determines the maximum age (in seconds) which check -# result files are considered to be valid. Files older than this -# threshold will be mercilessly deleted without further processing. - +check_result_path=/tmp max_check_result_file_age=3600 - - - - -# CACHED HOST CHECK HORIZON -# This option determines the maximum amount of time (in seconds) -# that the state of a previous host check is considered current. -# Cached host states (from host checks that were performed more -# recently that the timeframe specified by this value) can immensely -# improve performance in regards to the host check logic. -# Too high of a value for this option may result in inaccurate host -# states being used by Nagios, while a lower value may result in a -# performance hit for host checks. Use a value of 0 to disable host -# check caching. - cached_host_check_horizon=15 - - - -# CACHED SERVICE CHECK HORIZON -# This option determines the maximum amount of time (in seconds) -# that the state of a previous service check is considered current. -# Cached service states (from service checks that were performed more -# recently that the timeframe specified by this value) can immensely -# improve performance in regards to predictive dependency checks. -# Use a value of 0 to disable service check caching. - cached_service_check_horizon=15 - - - -# ENABLE PREDICTIVE HOST DEPENDENCY CHECKS -# This option determines whether or not Nagios will attempt to execute -# checks of hosts when it predicts that future dependency logic test -# may be needed. These predictive checks can help ensure that your -# host dependency logic works well. -# Values: -# 0 = Disable predictive checks -# 1 = Enable predictive checks (default) - enable_predictive_host_dependency_checks=1 - - - -# ENABLE PREDICTIVE SERVICE DEPENDENCY CHECKS -# This option determines whether or not Nagios will attempt to execute -# checks of service when it predicts that future dependency logic test -# may be needed. These predictive checks can help ensure that your -# service dependency logic works well. -# Values: -# 0 = Disable predictive checks -# 1 = Enable predictive checks (default) - enable_predictive_service_dependency_checks=1 - - - -# SOFT STATE DEPENDENCIES -# This option determines whether or not Nagios will use soft state -# information when checking host and service dependencies. Normally -# Nagios will only use the latest hard host or service state when -# checking dependencies. If you want it to use the latest state (regardless -# of whether its a soft or hard state type), enable this option. -# Values: -# 0 = Don't use soft state dependencies (default) -# 1 = Use soft state dependencies - soft_state_dependencies=0 - - - -# TIME CHANGE ADJUSTMENT THRESHOLDS -# These options determine when Nagios will react to detected changes -# in system time (either forward or backwards). - -#time_change_threshold=900 - - - -# AUTO-RESCHEDULING OPTION -# This option determines whether or not Nagios will attempt to -# automatically reschedule active host and service checks to -# "smooth" them out over time. This can help balance the load on -# the monitoring server. -# WARNING: THIS IS AN EXPERIMENTAL FEATURE - IT CAN DEGRADE -# PERFORMANCE, RATHER THAN INCREASE IT, IF USED IMPROPERLY - auto_reschedule_checks=0 - - - -# AUTO-RESCHEDULING INTERVAL -# This option determines how often (in seconds) Nagios will -# attempt to automatically reschedule checks. This option only -# has an effect if the auto_reschedule_checks option is enabled. -# Default is 30 seconds. -# WARNING: THIS IS AN EXPERIMENTAL FEATURE - IT CAN DEGRADE -# PERFORMANCE, RATHER THAN INCREASE IT, IF USED IMPROPERLY - auto_rescheduling_interval=30 - - - -# AUTO-RESCHEDULING WINDOW -# This option determines the "window" of time (in seconds) that -# Nagios will look at when automatically rescheduling checks. -# Only host and service checks that occur in the next X seconds -# (determined by this variable) will be rescheduled. This option -# only has an effect if the auto_reschedule_checks option is -# enabled. Default is 180 seconds (3 minutes). -# WARNING: THIS IS AN EXPERIMENTAL FEATURE - IT CAN DEGRADE -# PERFORMANCE, RATHER THAN INCREASE IT, IF USED IMPROPERLY - auto_rescheduling_window=180 - - - -# SLEEP TIME -# This is the number of seconds to sleep between checking for system -# events and service checks that need to be run. - -sleep_time=0.25 - - - -# TIMEOUT VALUES -# These options control how much time Nagios will allow various -# types of commands to execute before killing them off. Options -# are available for controlling maximum time allotted for -# service checks, host checks, event handlers, notifications, the -# ocsp command, and performance data commands. All values are in -# seconds. - service_check_timeout=60 host_check_timeout=30 event_handler_timeout=30 notification_timeout=30 ocsp_timeout=5 perfdata_timeout=5 - - - -# RETAIN STATE INFORMATION -# This setting determines whether or not Nagios will save state -# information for services and hosts before it shuts down. Upon -# startup Nagios will reload all saved service and host state -# information before starting to monitor. This is useful for -# maintaining long-term data on state statistics, etc, but will -# slow Nagios down a bit when it (re)starts. Since its only -# a one-time penalty, I think its well worth the additional -# startup delay. - retain_state_information=1 - - - -# STATE RETENTION FILE -# This is the file that Nagios should use to store host and -# service state information before it shuts down. The state -# information in this file is also read immediately prior to -# starting to monitor the network when Nagios is restarted. -# This file is used only if the preserve_state_information -# variable is set to 1. - state_retention_file=/usr/local/nagios/var/retention.dat - - - -# RETENTION DATA UPDATE INTERVAL -# This setting determines how often (in minutes) that Nagios -# will automatically save retention data during normal operation. -# If you set this value to 0, Nagios will not save retention -# data at regular interval, but it will still save retention -# data before shutting down or restarting. If you have disabled -# state retention, this option has no effect. - retention_update_interval=60 - - - -# USE RETAINED PROGRAM STATE -# This setting determines whether or not Nagios will set -# program status variables based on the values saved in the -# retention file. If you want to use retained program status -# information, set this value to 1. If not, set this value -# to 0. - use_retained_program_state=1 - - - -# USE RETAINED SCHEDULING INFO -# This setting determines whether or not Nagios will retain -# the scheduling info (next check time) for hosts and services -# based on the values saved in the retention file. If you -# If you want to use retained scheduling info, set this -# value to 1. If not, set this value to 0. - use_retained_scheduling_info=1 - - - -# RETAINED ATTRIBUTE MASKS (ADVANCED FEATURE) -# The following variables are used to specify specific host and -# service attributes that should *not* be retained by Nagios during -# program restarts. -# -# The values of the masks are bitwise ANDs of values specified -# by the "MODATTR_" definitions found in include/common.h. -# For example, if you do not want the current enabled/disabled state -# of flap detection and event handlers for hosts to be retained, you -# would use a value of 24 for the host attribute mask... -# MODATTR_EVENT_HANDLER_ENABLED (8) + MODATTR_FLAP_DETECTION_ENABLED (16) = 24 - -# This mask determines what host attributes are not retained retained_host_attribute_mask=0 - -# This mask determines what service attributes are not retained retained_service_attribute_mask=0 - -# These two masks determine what process attributes are not retained. -# There are two masks, because some process attributes have host and service -# options. For example, you can disable active host checks, but leave active -# service checks enabled. retained_process_host_attribute_mask=0 retained_process_service_attribute_mask=0 - -# These two masks determine what contact attributes are not retained. -# There are two masks, because some contact attributes have host and -# service options. For example, you can disable host notifications for -# a contact, but leave service notifications enabled for them. retained_contact_host_attribute_mask=0 retained_contact_service_attribute_mask=0 - - - -# INTERVAL LENGTH -# This is the seconds per unit interval as used in the -# host/contact/service configuration files. Setting this to 60 means -# that each interval is one minute long (60 seconds). Other settings -# have not been tested much, so your mileage is likely to vary... - interval_length=60 - - - -# CHECK FOR UPDATES -# This option determines whether Nagios will automatically check to -# see if new updates (releases) are available. It is recommend that you -# enable this option to ensure that you stay on top of the latest critical -# patches to Nagios. Nagios is critical to you - make sure you keep it in -# good shape. Nagios will check once a day for new updates. Data collected -# by Nagios Enterprises from the update check is processed in accordance -# with our privacy policy - see http://api.nagios.org for details. - check_for_updates=1 - - - -# BARE UPDATE CHECK -# This option deterines what data Nagios will send to api.nagios.org when -# it checks for updates. By default, Nagios will send information on the -# current version of Nagios you have installed, as well as an indicator as -# to whether this was a new installation or not. Nagios Enterprises uses -# this data to determine the number of users running specific version of -# Nagios. Enable this option if you do not want this information to be sent. - bare_update_check=0 - - - -# AGGRESSIVE HOST CHECKING OPTION -# If you don't want to turn on aggressive host checking features, set -# this value to 0 (the default). Otherwise set this value to 1 to -# enable the aggressive check option. Read the docs for more info -# on what aggressive host check is or check out the source code in -# base/checks.c - use_aggressive_host_checking=0 - - - -# SERVICE CHECK EXECUTION OPTION -# This determines whether or not Nagios will actively execute -# service checks when it initially starts. If this option is -# disabled, checks are not actively made, but Nagios can still -# receive and process passive check results that come in. Unless -# you're implementing redundant hosts or have a special need for -# disabling the execution of service checks, leave this enabled! -# Values: 1 = enable checks, 0 = disable checks - execute_service_checks=1 - - - -# PASSIVE SERVICE CHECK ACCEPTANCE OPTION -# This determines whether or not Nagios will accept passive -# service checks results when it initially (re)starts. -# Values: 1 = accept passive checks, 0 = reject passive checks - accept_passive_service_checks=1 - - - -# HOST CHECK EXECUTION OPTION -# This determines whether or not Nagios will actively execute -# host checks when it initially starts. If this option is -# disabled, checks are not actively made, but Nagios can still -# receive and process passive check results that come in. Unless -# you're implementing redundant hosts or have a special need for -# disabling the execution of host checks, leave this enabled! -# Values: 1 = enable checks, 0 = disable checks - execute_host_checks=1 - - - -# PASSIVE HOST CHECK ACCEPTANCE OPTION -# This determines whether or not Nagios will accept passive -# host checks results when it initially (re)starts. -# Values: 1 = accept passive checks, 0 = reject passive checks - accept_passive_host_checks=1 - - - -# NOTIFICATIONS OPTION -# This determines whether or not Nagios will sent out any host or -# service notifications when it is initially (re)started. -# Values: 1 = enable notifications, 0 = disable notifications - enable_notifications=1 - - - -# EVENT HANDLER USE OPTION -# This determines whether or not Nagios will run any host or -# service event handlers when it is initially (re)started. Unless -# you're implementing redundant hosts, leave this option enabled. -# Values: 1 = enable event handlers, 0 = disable event handlers - enable_event_handlers=1 - - - -# PROCESS PERFORMANCE DATA OPTION -# This determines whether or not Nagios will process performance -# data returned from service and host checks. If this option is -# enabled, host performance data will be processed using the -# host_perfdata_command (defined below) and service performance -# data will be processed using the service_perfdata_command (also -# defined below). Read the HTML docs for more information on -# performance data. -# Values: 1 = process performance data, 0 = do not process performance data - process_performance_data=0 - - - -# HOST AND SERVICE PERFORMANCE DATA PROCESSING COMMANDS -# These commands are run after every host and service check is -# performed. These commands are executed only if the -# enable_performance_data option (above) is set to 1. The command -# argument is the short name of a command definition that you -# define in your host configuration file. Read the HTML docs for -# more information on performance data. - -#host_perfdata_command=process-host-perfdata -#service_perfdata_command=process-service-perfdata - - - -# HOST AND SERVICE PERFORMANCE DATA FILES -# These files are used to store host and service performance data. -# Performance data is only written to these files if the -# enable_performance_data option (above) is set to 1. - -#host_perfdata_file=/tmp/host-perfdata -#service_perfdata_file=/tmp/service-perfdata - - - -# HOST AND SERVICE PERFORMANCE DATA FILE TEMPLATES -# These options determine what data is written (and how) to the -# performance data files. The templates may contain macros, special -# characters (\t for tab, \r for carriage return, \n for newline) -# and plain text. A newline is automatically added after each write -# to the performance data file. Some examples of what you can do are -# shown below. - -#host_perfdata_file_template=[HOSTPERFDATA]\t$TIMET$\t$HOSTNAME$\t$HOSTEXECUTIONTIME$\t$HOSTOUTPUT$\t$HOSTPERFDATA$ -#service_perfdata_file_template=[SERVICEPERFDATA]\t$TIMET$\t$HOSTNAME$\t$SERVICEDESC$\t$SERVICEEXECUTIONTIME$\t$SERVICELATENCY$\t$SERVICEOUTPUT$\t$SERVICEPERFDATA$ - - - -# HOST AND SERVICE PERFORMANCE DATA FILE MODES -# This option determines whether or not the host and service -# performance data files are opened in write ("w") or append ("a") -# mode. If you want to use named pipes, you should use the special -# pipe ("p") mode which avoid blocking at startup, otherwise you will -# likely want the defult append ("a") mode. - -#host_perfdata_file_mode=a -#service_perfdata_file_mode=a - - - -# HOST AND SERVICE PERFORMANCE DATA FILE PROCESSING INTERVAL -# These options determine how often (in seconds) the host and service -# performance data files are processed using the commands defined -# below. A value of 0 indicates the files should not be periodically -# processed. - -#host_perfdata_file_processing_interval=0 -#service_perfdata_file_processing_interval=0 - - - -# HOST AND SERVICE PERFORMANCE DATA FILE PROCESSING COMMANDS -# These commands are used to periodically process the host and -# service performance data files. The interval at which the -# processing occurs is determined by the options above. - -#host_perfdata_file_processing_command=process-host-perfdata-file -#service_perfdata_file_processing_command=process-service-perfdata-file - - - -# OBSESS OVER SERVICE CHECKS OPTION -# This determines whether or not Nagios will obsess over service -# checks and run the ocsp_command defined below. Unless you're -# planning on implementing distributed monitoring, do not enable -# this option. Read the HTML docs for more information on -# implementing distributed monitoring. -# Values: 1 = obsess over services, 0 = do not obsess (default) - obsess_over_services=0 - - - -# OBSESSIVE COMPULSIVE SERVICE PROCESSOR COMMAND -# This is the command that is run for every service check that is -# processed by Nagios. This command is executed only if the -# obsess_over_services option (above) is set to 1. The command -# argument is the short name of a command definition that you -# define in your host configuration file. Read the HTML docs for -# more information on implementing distributed monitoring. - -#ocsp_command=somecommand - - - -# OBSESS OVER HOST CHECKS OPTION -# This determines whether or not Nagios will obsess over host -# checks and run the ochp_command defined below. Unless you're -# planning on implementing distributed monitoring, do not enable -# this option. Read the HTML docs for more information on -# implementing distributed monitoring. -# Values: 1 = obsess over hosts, 0 = do not obsess (default) - obsess_over_hosts=0 - - - -# OBSESSIVE COMPULSIVE HOST PROCESSOR COMMAND -# This is the command that is run for every host check that is -# processed by Nagios. This command is executed only if the -# obsess_over_hosts option (above) is set to 1. The command -# argument is the short name of a command definition that you -# define in your host configuration file. Read the HTML docs for -# more information on implementing distributed monitoring. - -#ochp_command=somecommand - - - -# TRANSLATE PASSIVE HOST CHECKS OPTION -# This determines whether or not Nagios will translate -# DOWN/UNREACHABLE passive host check results into their proper -# state for this instance of Nagios. This option is useful -# if you have distributed or failover monitoring setup. In -# these cases your other Nagios servers probably have a different -# "view" of the network, with regards to the parent/child relationship -# of hosts. If a distributed monitoring server thinks a host -# is DOWN, it may actually be UNREACHABLE from the point of -# this Nagios instance. Enabling this option will tell Nagios -# to translate any DOWN or UNREACHABLE host states it receives -# passively into the correct state from the view of this server. -# Values: 1 = perform translation, 0 = do not translate (default) - translate_passive_host_checks=0 - - - -# PASSIVE HOST CHECKS ARE SOFT OPTION -# This determines whether or not Nagios will treat passive host -# checks as being HARD or SOFT. By default, a passive host check -# result will put a host into a HARD state type. This can be changed -# by enabling this option. -# Values: 0 = passive checks are HARD, 1 = passive checks are SOFT - passive_host_checks_are_soft=0 - - - -# ORPHANED HOST/SERVICE CHECK OPTIONS -# These options determine whether or not Nagios will periodically -# check for orphaned host service checks. Since service checks are -# not rescheduled until the results of their previous execution -# instance are processed, there exists a possibility that some -# checks may never get rescheduled. A similar situation exists for -# host checks, although the exact scheduling details differ a bit -# from service checks. Orphaned checks seem to be a rare -# problem and should not happen under normal circumstances. -# If you have problems with service checks never getting -# rescheduled, make sure you have orphaned service checks enabled. -# Values: 1 = enable checks, 0 = disable checks - check_for_orphaned_services=1 check_for_orphaned_hosts=1 - - - -# SERVICE FRESHNESS CHECK OPTION -# This option determines whether or not Nagios will periodically -# check the "freshness" of service results. Enabling this option -# is useful for ensuring passive checks are received in a timely -# manner. -# Values: 1 = enabled freshness checking, 0 = disable freshness checking - check_service_freshness=1 - - - -# SERVICE FRESHNESS CHECK INTERVAL -# This setting determines how often (in seconds) Nagios will -# check the "freshness" of service check results. If you have -# disabled service freshness checking, this option has no effect. - service_freshness_check_interval=60 - - - -# HOST FRESHNESS CHECK OPTION -# This option determines whether or not Nagios will periodically -# check the "freshness" of host results. Enabling this option -# is useful for ensuring passive checks are received in a timely -# manner. -# Values: 1 = enabled freshness checking, 0 = disable freshness checking - check_host_freshness=0 - - - -# HOST FRESHNESS CHECK INTERVAL -# This setting determines how often (in seconds) Nagios will -# check the "freshness" of host check results. If you have -# disabled host freshness checking, this option has no effect. - host_freshness_check_interval=60 - - - - -# ADDITIONAL FRESHNESS THRESHOLD LATENCY -# This setting determines the number of seconds that Nagios -# will add to any host and service freshness thresholds that -# it calculates (those not explicitly specified by the user). - additional_freshness_latency=15 - - - - -# FLAP DETECTION OPTION -# This option determines whether or not Nagios will try -# and detect hosts and services that are "flapping". -# Flapping occurs when a host or service changes between -# states too frequently. When Nagios detects that a -# host or service is flapping, it will temporarily suppress -# notifications for that host/service until it stops -# flapping. Flap detection is very experimental, so read -# the HTML documentation before enabling this feature! -# Values: 1 = enable flap detection -# 0 = disable flap detection (default) - enable_flap_detection=1 - - - -# FLAP DETECTION THRESHOLDS FOR HOSTS AND SERVICES -# Read the HTML documentation on flap detection for -# an explanation of what this option does. This option -# has no effect if flap detection is disabled. - low_service_flap_threshold=5.0 high_service_flap_threshold=20.0 low_host_flap_threshold=5.0 high_host_flap_threshold=20.0 - - - -# DATE FORMAT OPTION -# This option determines how short dates are displayed. Valid options -# include: -# us (MM-DD-YYYY HH:MM:SS) -# euro (DD-MM-YYYY HH:MM:SS) -# iso8601 (YYYY-MM-DD HH:MM:SS) -# strict-iso8601 (YYYY-MM-DDTHH:MM:SS) -# - date_format=us - - - - -# TIMEZONE OFFSET -# This option is used to override the default timezone that this -# instance of Nagios runs in. If not specified, Nagios will use -# the system configured timezone. -# -# NOTE: In order to display the correct timezone in the CGIs, you -# will also need to alter the Apache directives for the CGI path -# to include your timezone. Example: -# -# -# SetEnv TZ "Australia/Brisbane" -# ... -# - -#use_timezone=US/Mountain -#use_timezone=Australia/Brisbane - - - - -# P1.PL FILE LOCATION -# This value determines where the p1.pl perl script (used by the -# embedded Perl interpreter) is located. If you didn't compile -# Nagios with embedded Perl support, this option has no effect. - -p1_file=/usr/local/nagios/bin/p1.pl - - - -# EMBEDDED PERL INTERPRETER OPTION -# This option determines whether or not the embedded Perl interpreter -# will be enabled during runtime. This option has no effect if Nagios -# has not been compiled with support for embedded Perl. -# Values: 0 = disable interpreter, 1 = enable interpreter - -enable_embedded_perl=1 - - - -# EMBEDDED PERL USAGE OPTION -# This option determines whether or not Nagios will process Perl plugins -# and scripts with the embedded Perl interpreter if the plugins/scripts -# do not explicitly indicate whether or not it is okay to do so. Read -# the HTML documentation on the embedded Perl interpreter for more -# information on how this option works. - -use_embedded_perl_implicitly=1 - - - -# ILLEGAL OBJECT NAME CHARACTERS -# This option allows you to specify illegal characters that cannot -# be used in host names, service descriptions, or names of other -# object types. - illegal_object_name_chars=`~!$%^&*|'"<>?,()= - - - -# ILLEGAL MACRO OUTPUT CHARACTERS -# This option allows you to specify illegal characters that are -# stripped from macros before being used in notifications, event -# handlers, etc. This DOES NOT affect macros used in service or -# host check commands. -# The following macros are stripped of the characters you specify: -# $HOSTOUTPUT$ -# $HOSTPERFDATA$ -# $HOSTACKAUTHOR$ -# $HOSTACKCOMMENT$ -# $SERVICEOUTPUT$ -# $SERVICEPERFDATA$ -# $SERVICEACKAUTHOR$ -# $SERVICEACKCOMMENT$ - illegal_macro_output_chars=`~$&|'"<> - - - -# REGULAR EXPRESSION MATCHING -# This option controls whether or not regular expression matching -# takes place in the object config files. Regular expression -# matching is used to match host, hostgroup, service, and service -# group names/descriptions in some fields of various object types. -# Values: 1 = enable regexp matching, 0 = disable regexp matching - use_regexp_matching=0 - - - -# "TRUE" REGULAR EXPRESSION MATCHING -# This option controls whether or not "true" regular expression -# matching takes place in the object config files. This option -# only has an effect if regular expression matching is enabled -# (see above). If this option is DISABLED, regular expression -# matching only occurs if a string contains wildcard characters -# (* and ?). If the option is ENABLED, regexp matching occurs -# all the time (which can be annoying). -# Values: 1 = enable true matching, 0 = disable true matching - use_true_regexp_matching=0 - - - -# ADMINISTRATOR EMAIL/PAGER ADDRESSES -# The email and pager address of a global administrator (likely you). -# Nagios never uses these values itself, but you can access them by -# using the $ADMINEMAIL$ and $ADMINPAGER$ macros in your notification -# commands. - admin_email=nagios@localhost admin_pager=pagenagios@localhost - - - -# DAEMON CORE DUMP OPTION -# This option determines whether or not Nagios is allowed to create -# a core dump when it runs as a daemon. Note that it is generally -# considered bad form to allow this, but it may be useful for -# debugging purposes. Enabling this option doesn't guarantee that -# a core file will be produced, but that's just life... -# Values: 1 - Allow core dumps -# 0 - Do not allow core dumps (default) - daemon_dumps_core=0 - - - -# LARGE INSTALLATION TWEAKS OPTION -# This option determines whether or not Nagios will take some shortcuts -# which can save on memory and CPU usage in large Nagios installations. -# Read the documentation for more information on the benefits/tradeoffs -# of enabling this option. -# Values: 1 - Enabled tweaks -# 0 - Disable tweaks (default) - use_large_installation_tweaks=0 - - - -# ENABLE ENVIRONMENT MACROS -# This option determines whether or not Nagios will make all standard -# macros available as environment variables when host/service checks -# and system commands (event handlers, notifications, etc.) are -# executed. Enabling this option can cause performance issues in -# large installations, as it will consume a bit more memory and (more -# importantly) consume more CPU. -# Values: 1 - Enable environment variable macros (default) -# 0 - Disable environment variable macros - enable_environment_macros=1 - - - -# CHILD PROCESS MEMORY OPTION -# This option determines whether or not Nagios will free memory in -# child processes (processed used to execute system commands and host/ -# service checks). If you specify a value here, it will override -# program defaults. -# Value: 1 - Free memory in child processes -# 0 - Do not free memory in child processes - -#free_child_process_memory=1 - - - -# CHILD PROCESS FORKING BEHAVIOR -# This option determines how Nagios will fork child processes -# (used to execute system commands and host/service checks). Normally -# child processes are fork()ed twice, which provides a very high level -# of isolation from problems. Fork()ing once is probably enough and will -# save a great deal on CPU usage (in large installs), so you might -# want to consider using this. If you specify a value here, it will -# program defaults. -# Value: 1 - Child processes fork() twice -# 0 - Child processes fork() just once - -#child_processes_fork_twice=1 - - - -# DEBUG LEVEL -# This option determines how much (if any) debugging information will -# be written to the debug file. OR values together to log multiple -# types of information. -# Values: -# -1 = Everything -# 0 = Nothing -# 1 = Functions -# 2 = Configuration -# 4 = Process information -# 8 = Scheduled events -# 16 = Host/service checks -# 32 = Notifications -# 64 = Event broker -# 128 = External commands -# 256 = Commands -# 512 = Scheduled downtime -# 1024 = Comments -# 2048 = Macros - debug_level=0 - - - -# DEBUG VERBOSITY -# This option determines how verbose the debug log out will be. -# Values: 0 = Brief output -# 1 = More detailed -# 2 = Very detailed - debug_verbosity=1 - - - -# DEBUG FILE -# This option determines where Nagios should write debugging information. - debug_file=/usr/local/nagios/var/nagios.debug - - - -# MAX DEBUG FILE SIZE -# This option determines the maximum size (in bytes) of the debug file. If -# the file grows larger than this size, it will be renamed with a .old -# extension. If a file already exists with a .old extension it will -# automatically be deleted. This helps ensure your disk space usage doesn't -# get out of control when debugging Nagios. - max_debug_file_size=1000000 - - diff --git a/t/etc/nagios-no-service.cfg b/t/etc/nagios-no-service.cfg index a6fd60c..47ba29e 100644 --- a/t/etc/nagios-no-service.cfg +++ b/t/etc/nagios-no-service.cfg @@ -1,1307 +1,101 @@ -############################################################################## -# -# NAGIOS.CFG - Sample Main Config File for Nagios 3.1.0 -# -# Read the documentation for more information on this configuration -# file. I've provided some comments here, but things may not be so -# clear without further explanation. -# -# Last Modified: 12-14-2008 -# -############################################################################## - - -# LOG FILE -# This is the main log file where service and host events are logged -# for historical purposes. This should be the first option specified -# in the config file!!! - -log_file=/usr/local/nagios/var/nagios.log - - - -# OBJECT CONFIGURATION FILE(S) -# These are the object configuration files in which you define hosts, -# host groups, contacts, contact groups, services, etc. -# You can split your object definitions across several config files -# if you wish (as shown below), or keep them all in a single config file. - -# Note: A relative path here is relative to the location of the overall nagios.cfg file, -# not relative to the current directory +log_file=../var/nagios.log cfg_file=no-service-error.cfg - -# You can also tell Nagios to process all config files (with a .cfg -# extension) in a particular directory by using the cfg_dir -# directive as shown below: - -#cfg_dir=/usr/local/nagios/etc/servers -#cfg_dir=/usr/local/nagios/etc/printers -#cfg_dir=/usr/local/nagios/etc/switches -#cfg_dir=/usr/local/nagios/etc/routers - - - - -# OBJECT CACHE FILE -# This option determines where object definitions are cached when -# Nagios starts/restarts. The CGIs read object definitions from -# this cache file (rather than looking at the object config files -# directly) in order to prevent inconsistencies that can occur -# when the config files are modified after Nagios starts. - -object_cache_file=var/objects.cache - - - -# PRE-CACHED OBJECT FILE -# This options determines the location of the precached object file. -# If you run Nagios with the -p command line option, it will preprocess -# your object configuration file(s) and write the cached config to this -# file. You can then start Nagios with the -u option to have it read -# object definitions from this precached file, rather than the standard -# object configuration files (see the cfg_file and cfg_dir options above). -# Using a precached object file can speed up the time needed to (re)start -# the Nagios process if you've got a large and/or complex configuration. -# Read the documentation section on optimizing Nagios to find our more -# about how this feature works. - -precached_object_file=var/objects.precache - - - -# RESOURCE FILE -# This is an optional resource file that contains $USERx$ macro -# definitions. Multiple resource files can be specified by using -# multiple resource_file definitions. The CGIs will not attempt to -# read the contents of resource files, so information that is -# considered to be sensitive (usernames, passwords, etc) can be -# defined as macros in this file and restrictive permissions (600) -# can be placed on this file. - -resource_file=etc/resource.cfg - - - -# STATUS FILE -# This is where the current status of all monitored services and -# hosts is stored. Its contents are read and processed by the CGIs. -# The contents of the status file are deleted every time Nagios -# restarts. - -status_file=/usr/local/nagios/var/status.dat - - - -# STATUS FILE UPDATE INTERVAL -# This option determines the frequency (in seconds) that -# Nagios will periodically dump program, host, and -# service status data. - +object_cache_file=../var/objects.cache +precached_object_file=../var/objects.precache +resource_file=resource.cfg +status_file=../var/status.dat status_update_interval=10 - - - -# NAGIOS USER -# This determines the effective user that Nagios should run as. -# You can either supply a username or a UID. - nagios_user=nagios - - - -# NAGIOS GROUP -# This determines the effective group that Nagios should run as. -# You can either supply a group name or a GID. - nagios_group=nagios - - - -# EXTERNAL COMMAND OPTION -# This option allows you to specify whether or not Nagios should check -# for external commands (in the command file defined below). By default -# Nagios will *not* check for external commands, just to be on the -# cautious side. If you want to be able to use the CGI command interface -# you will have to enable this. -# Values: 0 = disable commands, 1 = enable commands - check_external_commands=1 - - - -# EXTERNAL COMMAND CHECK INTERVAL -# This is the interval at which Nagios should check for external commands. -# This value works of the interval_length you specify later. If you leave -# that at its default value of 60 (seconds), a value of 1 here will cause -# Nagios to check for external commands every minute. If you specify a -# number followed by an "s" (i.e. 15s), this will be interpreted to mean -# actual seconds rather than a multiple of the interval_length variable. -# Note: In addition to reading the external command file at regularly -# scheduled intervals, Nagios will also check for external commands after -# event handlers are executed. -# NOTE: Setting this value to -1 causes Nagios to check the external -# command file as often as possible. - -#command_check_interval=15s -command_check_interval=-1 - - - -# EXTERNAL COMMAND FILE -# This is the file that Nagios checks for external command requests. -# It is also where the command CGI will write commands that are submitted -# by users, so it must be writeable by the user that the web server -# is running as (usually 'nobody'). Permissions should be set at the -# directory level instead of on the file, as the file is deleted every -# time its contents are processed. - -command_file=/usr/local/nagios/var/rw/nagios.cmd - - - -# EXTERNAL COMMAND BUFFER SLOTS -# This settings is used to tweak the number of items or "slots" that -# the Nagios daemon should allocate to the buffer that holds incoming -# external commands before they are processed. As external commands -# are processed by the daemon, they are removed from the buffer. - -external_command_buffer_slots=4096 - - - -# LOCK FILE -# This is the lockfile that Nagios will use to store its PID number -# in when it is running in daemon mode. - -lock_file=/usr/local/nagios/var/nagios.lock - - - -# TEMP FILE -# This is a temporary file that is used as scratch space when Nagios -# updates the status log, cleans the comment file, etc. This file -# is created, used, and deleted throughout the time that Nagios is -# running. - -temp_file=/usr/local/nagios/var/nagios.tmp - - - -# TEMP PATH -# This is path where Nagios can create temp files for service and -# host check results, etc. - +command_file=../var/rw/nagios.cmd +lock_file=../var/nagios.lock +temp_file=../var/nagios.tmp temp_path=/tmp - - - -# EVENT BROKER OPTIONS -# Controls what (if any) data gets sent to the event broker. -# Values: 0 = Broker nothing -# -1 = Broker everything -# = See documentation - event_broker_options=-1 - - - -# EVENT BROKER MODULE(S) -# This directive is used to specify an event broker module that should -# by loaded by Nagios at startup. Use multiple directives if you want -# to load more than one module. Arguments that should be passed to -# the module at startup are seperated from the module path by a space. -# -#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -# WARNING !!! WARNING !!! WARNING !!! WARNING !!! WARNING !!! WARNING -#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -# -# Do NOT overwrite modules while they are being used by Nagios or Nagios -# will crash in a fiery display of SEGFAULT glory. This is a bug/limitation -# either in dlopen(), the kernel, and/or the filesystem. And maybe Nagios... -# -# The correct/safe way of updating a module is by using one of these methods: -# 1. Shutdown Nagios, replace the module file, restart Nagios -# 2. Delete the original module file, move the new module file into place, restart Nagios -# -# Example: -# -# broker_module= [moduleargs] - -#broker_module=/somewhere/module1.o -#broker_module=/somewhere/module2.o arg1 arg2=3 debug=0 - - - -# LOG ROTATION METHOD -# This is the log rotation method that Nagios should use to rotate -# the main log file. Values are as follows.. -# n = None - don't rotate the log -# h = Hourly rotation (top of the hour) -# d = Daily rotation (midnight every day) -# w = Weekly rotation (midnight on Saturday evening) -# m = Monthly rotation (midnight last day of month) - log_rotation_method=d - - - -# LOG ARCHIVE PATH -# This is the directory where archived (rotated) log files should be -# placed (assuming you've chosen to do log rotation). - -log_archive_path=/usr/local/nagios/var/archives - - - -# LOGGING OPTIONS -# If you want messages logged to the syslog facility, as well as the -# Nagios log file set this option to 1. If not, set it to 0. - +log_archive_path=../var/archives use_syslog=1 - - - -# NOTIFICATION LOGGING OPTION -# If you don't want notifications to be logged, set this value to 0. -# If notifications should be logged, set the value to 1. - log_notifications=1 - - - -# SERVICE RETRY LOGGING OPTION -# If you don't want service check retries to be logged, set this value -# to 0. If retries should be logged, set the value to 1. - log_service_retries=1 - - - -# HOST RETRY LOGGING OPTION -# If you don't want host check retries to be logged, set this value to -# 0. If retries should be logged, set the value to 1. - log_host_retries=1 - - - -# EVENT HANDLER LOGGING OPTION -# If you don't want host and service event handlers to be logged, set -# this value to 0. If event handlers should be logged, set the value -# to 1. - log_event_handlers=1 - - - -# INITIAL STATES LOGGING OPTION -# If you want Nagios to log all initial host and service states to -# the main log file (the first time the service or host is checked) -# you can enable this option by setting this value to 1. If you -# are not using an external application that does long term state -# statistics reporting, you do not need to enable this option. In -# this case, set the value to 0. - log_initial_states=0 - - - -# EXTERNAL COMMANDS LOGGING OPTION -# If you don't want Nagios to log external commands, set this value -# to 0. If external commands should be logged, set this value to 1. -# Note: This option does not include logging of passive service -# checks - see the option below for controlling whether or not -# passive checks are logged. - log_external_commands=1 - - - -# PASSIVE CHECKS LOGGING OPTION -# If you don't want Nagios to log passive host and service checks, set -# this value to 0. If passive checks should be logged, set -# this value to 1. - log_passive_checks=1 - - - -# GLOBAL HOST AND SERVICE EVENT HANDLERS -# These options allow you to specify a host and service event handler -# command that is to be run for every host or service state change. -# The global event handler is executed immediately prior to the event -# handler that you have optionally specified in each host or -# service definition. The command argument is the short name of a -# command definition that you define in your host configuration file. -# Read the HTML docs for more information. - -#global_host_event_handler=somecommand -#global_service_event_handler=somecommand - - - -# SERVICE INTER-CHECK DELAY METHOD -# This is the method that Nagios should use when initially -# "spreading out" service checks when it starts monitoring. The -# default is to use smart delay calculation, which will try to -# space all service checks out evenly to minimize CPU load. -# Using the dumb setting will cause all checks to be scheduled -# at the same time (with no delay between them)! This is not a -# good thing for production, but is useful when testing the -# parallelization functionality. -# n = None - don't use any delay between checks -# d = Use a "dumb" delay of 1 second between checks -# s = Use "smart" inter-check delay calculation -# x.xx = Use an inter-check delay of x.xx seconds - service_inter_check_delay_method=s - - - -# MAXIMUM SERVICE CHECK SPREAD -# This variable determines the timeframe (in minutes) from the -# program start time that an initial check of all services should -# be completed. Default is 30 minutes. - max_service_check_spread=30 - - - -# SERVICE CHECK INTERLEAVE FACTOR -# This variable determines how service checks are interleaved. -# Interleaving the service checks allows for a more even -# distribution of service checks and reduced load on remote -# hosts. Setting this value to 1 is equivalent to how versions -# of Nagios previous to 0.0.5 did service checks. Set this -# value to s (smart) for automatic calculation of the interleave -# factor unless you have a specific reason to change it. -# s = Use "smart" interleave factor calculation -# x = Use an interleave factor of x, where x is a -# number greater than or equal to 1. - service_interleave_factor=s - - - -# HOST INTER-CHECK DELAY METHOD -# This is the method that Nagios should use when initially -# "spreading out" host checks when it starts monitoring. The -# default is to use smart delay calculation, which will try to -# space all host checks out evenly to minimize CPU load. -# Using the dumb setting will cause all checks to be scheduled -# at the same time (with no delay between them)! -# n = None - don't use any delay between checks -# d = Use a "dumb" delay of 1 second between checks -# s = Use "smart" inter-check delay calculation -# x.xx = Use an inter-check delay of x.xx seconds - host_inter_check_delay_method=s - - - -# MAXIMUM HOST CHECK SPREAD -# This variable determines the timeframe (in minutes) from the -# program start time that an initial check of all hosts should -# be completed. Default is 30 minutes. - max_host_check_spread=30 - - - -# MAXIMUM CONCURRENT SERVICE CHECKS -# This option allows you to specify the maximum number of -# service checks that can be run in parallel at any given time. -# Specifying a value of 1 for this variable essentially prevents -# any service checks from being parallelized. A value of 0 -# will not restrict the number of concurrent checks that are -# being executed. - max_concurrent_checks=0 - - - -# HOST AND SERVICE CHECK REAPER FREQUENCY -# This is the frequency (in seconds!) that Nagios will process -# the results of host and service checks. - check_result_reaper_frequency=10 - - - - -# MAX CHECK RESULT REAPER TIME -# This is the max amount of time (in seconds) that a single -# check result reaper event will be allowed to run before -# returning control back to Nagios so it can perform other -# duties. - max_check_result_reaper_time=30 - - - - -# CHECK RESULT PATH -# This is directory where Nagios stores the results of host and -# service checks that have not yet been processed. -# -# Note: Make sure that only one instance of Nagios has access -# to this directory! - -check_result_path=var/spool/checkresults - - - - -# MAX CHECK RESULT FILE AGE -# This option determines the maximum age (in seconds) which check -# result files are considered to be valid. Files older than this -# threshold will be mercilessly deleted without further processing. - +check_result_path=/tmp max_check_result_file_age=3600 - - - - -# CACHED HOST CHECK HORIZON -# This option determines the maximum amount of time (in seconds) -# that the state of a previous host check is considered current. -# Cached host states (from host checks that were performed more -# recently that the timeframe specified by this value) can immensely -# improve performance in regards to the host check logic. -# Too high of a value for this option may result in inaccurate host -# states being used by Nagios, while a lower value may result in a -# performance hit for host checks. Use a value of 0 to disable host -# check caching. - cached_host_check_horizon=15 - - - -# CACHED SERVICE CHECK HORIZON -# This option determines the maximum amount of time (in seconds) -# that the state of a previous service check is considered current. -# Cached service states (from service checks that were performed more -# recently that the timeframe specified by this value) can immensely -# improve performance in regards to predictive dependency checks. -# Use a value of 0 to disable service check caching. - cached_service_check_horizon=15 - - - -# ENABLE PREDICTIVE HOST DEPENDENCY CHECKS -# This option determines whether or not Nagios will attempt to execute -# checks of hosts when it predicts that future dependency logic test -# may be needed. These predictive checks can help ensure that your -# host dependency logic works well. -# Values: -# 0 = Disable predictive checks -# 1 = Enable predictive checks (default) - enable_predictive_host_dependency_checks=1 - - - -# ENABLE PREDICTIVE SERVICE DEPENDENCY CHECKS -# This option determines whether or not Nagios will attempt to execute -# checks of service when it predicts that future dependency logic test -# may be needed. These predictive checks can help ensure that your -# service dependency logic works well. -# Values: -# 0 = Disable predictive checks -# 1 = Enable predictive checks (default) - enable_predictive_service_dependency_checks=1 - - - -# SOFT STATE DEPENDENCIES -# This option determines whether or not Nagios will use soft state -# information when checking host and service dependencies. Normally -# Nagios will only use the latest hard host or service state when -# checking dependencies. If you want it to use the latest state (regardless -# of whether its a soft or hard state type), enable this option. -# Values: -# 0 = Don't use soft state dependencies (default) -# 1 = Use soft state dependencies - soft_state_dependencies=0 - - - -# TIME CHANGE ADJUSTMENT THRESHOLDS -# These options determine when Nagios will react to detected changes -# in system time (either forward or backwards). - -#time_change_threshold=900 - - - -# AUTO-RESCHEDULING OPTION -# This option determines whether or not Nagios will attempt to -# automatically reschedule active host and service checks to -# "smooth" them out over time. This can help balance the load on -# the monitoring server. -# WARNING: THIS IS AN EXPERIMENTAL FEATURE - IT CAN DEGRADE -# PERFORMANCE, RATHER THAN INCREASE IT, IF USED IMPROPERLY - auto_reschedule_checks=0 - - - -# AUTO-RESCHEDULING INTERVAL -# This option determines how often (in seconds) Nagios will -# attempt to automatically reschedule checks. This option only -# has an effect if the auto_reschedule_checks option is enabled. -# Default is 30 seconds. -# WARNING: THIS IS AN EXPERIMENTAL FEATURE - IT CAN DEGRADE -# PERFORMANCE, RATHER THAN INCREASE IT, IF USED IMPROPERLY - auto_rescheduling_interval=30 - - - -# AUTO-RESCHEDULING WINDOW -# This option determines the "window" of time (in seconds) that -# Nagios will look at when automatically rescheduling checks. -# Only host and service checks that occur in the next X seconds -# (determined by this variable) will be rescheduled. This option -# only has an effect if the auto_reschedule_checks option is -# enabled. Default is 180 seconds (3 minutes). -# WARNING: THIS IS AN EXPERIMENTAL FEATURE - IT CAN DEGRADE -# PERFORMANCE, RATHER THAN INCREASE IT, IF USED IMPROPERLY - auto_rescheduling_window=180 - - - -# SLEEP TIME -# This is the number of seconds to sleep between checking for system -# events and service checks that need to be run. - -sleep_time=0.25 - - - -# TIMEOUT VALUES -# These options control how much time Nagios will allow various -# types of commands to execute before killing them off. Options -# are available for controlling maximum time allotted for -# service checks, host checks, event handlers, notifications, the -# ocsp command, and performance data commands. All values are in -# seconds. - service_check_timeout=60 host_check_timeout=30 event_handler_timeout=30 notification_timeout=30 ocsp_timeout=5 perfdata_timeout=5 - - - -# RETAIN STATE INFORMATION -# This setting determines whether or not Nagios will save state -# information for services and hosts before it shuts down. Upon -# startup Nagios will reload all saved service and host state -# information before starting to monitor. This is useful for -# maintaining long-term data on state statistics, etc, but will -# slow Nagios down a bit when it (re)starts. Since its only -# a one-time penalty, I think its well worth the additional -# startup delay. - retain_state_information=1 - - - -# STATE RETENTION FILE -# This is the file that Nagios should use to store host and -# service state information before it shuts down. The state -# information in this file is also read immediately prior to -# starting to monitor the network when Nagios is restarted. -# This file is used only if the preserve_state_information -# variable is set to 1. - -state_retention_file=/usr/local/nagios/var/retention.dat - - - -# RETENTION DATA UPDATE INTERVAL -# This setting determines how often (in minutes) that Nagios -# will automatically save retention data during normal operation. -# If you set this value to 0, Nagios will not save retention -# data at regular interval, but it will still save retention -# data before shutting down or restarting. If you have disabled -# state retention, this option has no effect. - +state_retention_file=../var/retention.dat retention_update_interval=60 - - - -# USE RETAINED PROGRAM STATE -# This setting determines whether or not Nagios will set -# program status variables based on the values saved in the -# retention file. If you want to use retained program status -# information, set this value to 1. If not, set this value -# to 0. - use_retained_program_state=1 - - - -# USE RETAINED SCHEDULING INFO -# This setting determines whether or not Nagios will retain -# the scheduling info (next check time) for hosts and services -# based on the values saved in the retention file. If you -# If you want to use retained scheduling info, set this -# value to 1. If not, set this value to 0. - use_retained_scheduling_info=1 - - - -# RETAINED ATTRIBUTE MASKS (ADVANCED FEATURE) -# The following variables are used to specify specific host and -# service attributes that should *not* be retained by Nagios during -# program restarts. -# -# The values of the masks are bitwise ANDs of values specified -# by the "MODATTR_" definitions found in include/common.h. -# For example, if you do not want the current enabled/disabled state -# of flap detection and event handlers for hosts to be retained, you -# would use a value of 24 for the host attribute mask... -# MODATTR_EVENT_HANDLER_ENABLED (8) + MODATTR_FLAP_DETECTION_ENABLED (16) = 24 - -# This mask determines what host attributes are not retained retained_host_attribute_mask=0 - -# This mask determines what service attributes are not retained retained_service_attribute_mask=0 - -# These two masks determine what process attributes are not retained. -# There are two masks, because some process attributes have host and service -# options. For example, you can disable active host checks, but leave active -# service checks enabled. retained_process_host_attribute_mask=0 retained_process_service_attribute_mask=0 - -# These two masks determine what contact attributes are not retained. -# There are two masks, because some contact attributes have host and -# service options. For example, you can disable host notifications for -# a contact, but leave service notifications enabled for them. retained_contact_host_attribute_mask=0 retained_contact_service_attribute_mask=0 - - - -# INTERVAL LENGTH -# This is the seconds per unit interval as used in the -# host/contact/service configuration files. Setting this to 60 means -# that each interval is one minute long (60 seconds). Other settings -# have not been tested much, so your mileage is likely to vary... - interval_length=60 - - - -# CHECK FOR UPDATES -# This option determines whether Nagios will automatically check to -# see if new updates (releases) are available. It is recommend that you -# enable this option to ensure that you stay on top of the latest critical -# patches to Nagios. Nagios is critical to you - make sure you keep it in -# good shape. Nagios will check once a day for new updates. Data collected -# by Nagios Enterprises from the update check is processed in accordance -# with our privacy policy - see http://api.nagios.org for details. - check_for_updates=1 - - - -# BARE UPDATE CHECK -# This option deterines what data Nagios will send to api.nagios.org when -# it checks for updates. By default, Nagios will send information on the -# current version of Nagios you have installed, as well as an indicator as -# to whether this was a new installation or not. Nagios Enterprises uses -# this data to determine the number of users running specific version of -# Nagios. Enable this option if you do not want this information to be sent. - bare_update_check=0 - - - -# AGGRESSIVE HOST CHECKING OPTION -# If you don't want to turn on aggressive host checking features, set -# this value to 0 (the default). Otherwise set this value to 1 to -# enable the aggressive check option. Read the docs for more info -# on what aggressive host check is or check out the source code in -# base/checks.c - use_aggressive_host_checking=0 - - - -# SERVICE CHECK EXECUTION OPTION -# This determines whether or not Nagios will actively execute -# service checks when it initially starts. If this option is -# disabled, checks are not actively made, but Nagios can still -# receive and process passive check results that come in. Unless -# you're implementing redundant hosts or have a special need for -# disabling the execution of service checks, leave this enabled! -# Values: 1 = enable checks, 0 = disable checks - execute_service_checks=1 - - - -# PASSIVE SERVICE CHECK ACCEPTANCE OPTION -# This determines whether or not Nagios will accept passive -# service checks results when it initially (re)starts. -# Values: 1 = accept passive checks, 0 = reject passive checks - accept_passive_service_checks=1 - - - -# HOST CHECK EXECUTION OPTION -# This determines whether or not Nagios will actively execute -# host checks when it initially starts. If this option is -# disabled, checks are not actively made, but Nagios can still -# receive and process passive check results that come in. Unless -# you're implementing redundant hosts or have a special need for -# disabling the execution of host checks, leave this enabled! -# Values: 1 = enable checks, 0 = disable checks - execute_host_checks=1 - - - -# PASSIVE HOST CHECK ACCEPTANCE OPTION -# This determines whether or not Nagios will accept passive -# host checks results when it initially (re)starts. -# Values: 1 = accept passive checks, 0 = reject passive checks - accept_passive_host_checks=1 - - - -# NOTIFICATIONS OPTION -# This determines whether or not Nagios will sent out any host or -# service notifications when it is initially (re)started. -# Values: 1 = enable notifications, 0 = disable notifications - enable_notifications=1 - - - -# EVENT HANDLER USE OPTION -# This determines whether or not Nagios will run any host or -# service event handlers when it is initially (re)started. Unless -# you're implementing redundant hosts, leave this option enabled. -# Values: 1 = enable event handlers, 0 = disable event handlers - enable_event_handlers=1 - - - -# PROCESS PERFORMANCE DATA OPTION -# This determines whether or not Nagios will process performance -# data returned from service and host checks. If this option is -# enabled, host performance data will be processed using the -# host_perfdata_command (defined below) and service performance -# data will be processed using the service_perfdata_command (also -# defined below). Read the HTML docs for more information on -# performance data. -# Values: 1 = process performance data, 0 = do not process performance data - process_performance_data=0 - - - -# HOST AND SERVICE PERFORMANCE DATA PROCESSING COMMANDS -# These commands are run after every host and service check is -# performed. These commands are executed only if the -# enable_performance_data option (above) is set to 1. The command -# argument is the short name of a command definition that you -# define in your host configuration file. Read the HTML docs for -# more information on performance data. - -#host_perfdata_command=process-host-perfdata -#service_perfdata_command=process-service-perfdata - - - -# HOST AND SERVICE PERFORMANCE DATA FILES -# These files are used to store host and service performance data. -# Performance data is only written to these files if the -# enable_performance_data option (above) is set to 1. - -#host_perfdata_file=/tmp/host-perfdata -#service_perfdata_file=/tmp/service-perfdata - - - -# HOST AND SERVICE PERFORMANCE DATA FILE TEMPLATES -# These options determine what data is written (and how) to the -# performance data files. The templates may contain macros, special -# characters (\t for tab, \r for carriage return, \n for newline) -# and plain text. A newline is automatically added after each write -# to the performance data file. Some examples of what you can do are -# shown below. - -#host_perfdata_file_template=[HOSTPERFDATA]\t$TIMET$\t$HOSTNAME$\t$HOSTEXECUTIONTIME$\t$HOSTOUTPUT$\t$HOSTPERFDATA$ -#service_perfdata_file_template=[SERVICEPERFDATA]\t$TIMET$\t$HOSTNAME$\t$SERVICEDESC$\t$SERVICEEXECUTIONTIME$\t$SERVICELATENCY$\t$SERVICEOUTPUT$\t$SERVICEPERFDATA$ - - - -# HOST AND SERVICE PERFORMANCE DATA FILE MODES -# This option determines whether or not the host and service -# performance data files are opened in write ("w") or append ("a") -# mode. If you want to use named pipes, you should use the special -# pipe ("p") mode which avoid blocking at startup, otherwise you will -# likely want the defult append ("a") mode. - -#host_perfdata_file_mode=a -#service_perfdata_file_mode=a - - - -# HOST AND SERVICE PERFORMANCE DATA FILE PROCESSING INTERVAL -# These options determine how often (in seconds) the host and service -# performance data files are processed using the commands defined -# below. A value of 0 indicates the files should not be periodically -# processed. - -#host_perfdata_file_processing_interval=0 -#service_perfdata_file_processing_interval=0 - - - -# HOST AND SERVICE PERFORMANCE DATA FILE PROCESSING COMMANDS -# These commands are used to periodically process the host and -# service performance data files. The interval at which the -# processing occurs is determined by the options above. - -#host_perfdata_file_processing_command=process-host-perfdata-file -#service_perfdata_file_processing_command=process-service-perfdata-file - - - -# OBSESS OVER SERVICE CHECKS OPTION -# This determines whether or not Nagios will obsess over service -# checks and run the ocsp_command defined below. Unless you're -# planning on implementing distributed monitoring, do not enable -# this option. Read the HTML docs for more information on -# implementing distributed monitoring. -# Values: 1 = obsess over services, 0 = do not obsess (default) - obsess_over_services=0 - - - -# OBSESSIVE COMPULSIVE SERVICE PROCESSOR COMMAND -# This is the command that is run for every service check that is -# processed by Nagios. This command is executed only if the -# obsess_over_services option (above) is set to 1. The command -# argument is the short name of a command definition that you -# define in your host configuration file. Read the HTML docs for -# more information on implementing distributed monitoring. - -#ocsp_command=somecommand - - - -# OBSESS OVER HOST CHECKS OPTION -# This determines whether or not Nagios will obsess over host -# checks and run the ochp_command defined below. Unless you're -# planning on implementing distributed monitoring, do not enable -# this option. Read the HTML docs for more information on -# implementing distributed monitoring. -# Values: 1 = obsess over hosts, 0 = do not obsess (default) - obsess_over_hosts=0 - - - -# OBSESSIVE COMPULSIVE HOST PROCESSOR COMMAND -# This is the command that is run for every host check that is -# processed by Nagios. This command is executed only if the -# obsess_over_hosts option (above) is set to 1. The command -# argument is the short name of a command definition that you -# define in your host configuration file. Read the HTML docs for -# more information on implementing distributed monitoring. - -#ochp_command=somecommand - - - -# TRANSLATE PASSIVE HOST CHECKS OPTION -# This determines whether or not Nagios will translate -# DOWN/UNREACHABLE passive host check results into their proper -# state for this instance of Nagios. This option is useful -# if you have distributed or failover monitoring setup. In -# these cases your other Nagios servers probably have a different -# "view" of the network, with regards to the parent/child relationship -# of hosts. If a distributed monitoring server thinks a host -# is DOWN, it may actually be UNREACHABLE from the point of -# this Nagios instance. Enabling this option will tell Nagios -# to translate any DOWN or UNREACHABLE host states it receives -# passively into the correct state from the view of this server. -# Values: 1 = perform translation, 0 = do not translate (default) - translate_passive_host_checks=0 - - - -# PASSIVE HOST CHECKS ARE SOFT OPTION -# This determines whether or not Nagios will treat passive host -# checks as being HARD or SOFT. By default, a passive host check -# result will put a host into a HARD state type. This can be changed -# by enabling this option. -# Values: 0 = passive checks are HARD, 1 = passive checks are SOFT - passive_host_checks_are_soft=0 - - - -# ORPHANED HOST/SERVICE CHECK OPTIONS -# These options determine whether or not Nagios will periodically -# check for orphaned host service checks. Since service checks are -# not rescheduled until the results of their previous execution -# instance are processed, there exists a possibility that some -# checks may never get rescheduled. A similar situation exists for -# host checks, although the exact scheduling details differ a bit -# from service checks. Orphaned checks seem to be a rare -# problem and should not happen under normal circumstances. -# If you have problems with service checks never getting -# rescheduled, make sure you have orphaned service checks enabled. -# Values: 1 = enable checks, 0 = disable checks - check_for_orphaned_services=1 check_for_orphaned_hosts=1 - - - -# SERVICE FRESHNESS CHECK OPTION -# This option determines whether or not Nagios will periodically -# check the "freshness" of service results. Enabling this option -# is useful for ensuring passive checks are received in a timely -# manner. -# Values: 1 = enabled freshness checking, 0 = disable freshness checking - check_service_freshness=1 - - - -# SERVICE FRESHNESS CHECK INTERVAL -# This setting determines how often (in seconds) Nagios will -# check the "freshness" of service check results. If you have -# disabled service freshness checking, this option has no effect. - service_freshness_check_interval=60 - - - -# HOST FRESHNESS CHECK OPTION -# This option determines whether or not Nagios will periodically -# check the "freshness" of host results. Enabling this option -# is useful for ensuring passive checks are received in a timely -# manner. -# Values: 1 = enabled freshness checking, 0 = disable freshness checking - check_host_freshness=0 - - - -# HOST FRESHNESS CHECK INTERVAL -# This setting determines how often (in seconds) Nagios will -# check the "freshness" of host check results. If you have -# disabled host freshness checking, this option has no effect. - host_freshness_check_interval=60 - - - - -# ADDITIONAL FRESHNESS THRESHOLD LATENCY -# This setting determines the number of seconds that Nagios -# will add to any host and service freshness thresholds that -# it calculates (those not explicitly specified by the user). - additional_freshness_latency=15 - - - - -# FLAP DETECTION OPTION -# This option determines whether or not Nagios will try -# and detect hosts and services that are "flapping". -# Flapping occurs when a host or service changes between -# states too frequently. When Nagios detects that a -# host or service is flapping, it will temporarily suppress -# notifications for that host/service until it stops -# flapping. Flap detection is very experimental, so read -# the HTML documentation before enabling this feature! -# Values: 1 = enable flap detection -# 0 = disable flap detection (default) - enable_flap_detection=1 - - - -# FLAP DETECTION THRESHOLDS FOR HOSTS AND SERVICES -# Read the HTML documentation on flap detection for -# an explanation of what this option does. This option -# has no effect if flap detection is disabled. - low_service_flap_threshold=5.0 high_service_flap_threshold=20.0 low_host_flap_threshold=5.0 high_host_flap_threshold=20.0 - - - -# DATE FORMAT OPTION -# This option determines how short dates are displayed. Valid options -# include: -# us (MM-DD-YYYY HH:MM:SS) -# euro (DD-MM-YYYY HH:MM:SS) -# iso8601 (YYYY-MM-DD HH:MM:SS) -# strict-iso8601 (YYYY-MM-DDTHH:MM:SS) -# - date_format=us - - - - -# TIMEZONE OFFSET -# This option is used to override the default timezone that this -# instance of Nagios runs in. If not specified, Nagios will use -# the system configured timezone. -# -# NOTE: In order to display the correct timezone in the CGIs, you -# will also need to alter the Apache directives for the CGI path -# to include your timezone. Example: -# -# -# SetEnv TZ "Australia/Brisbane" -# ... -# - -#use_timezone=US/Mountain -#use_timezone=Australia/Brisbane - - - - -# P1.PL FILE LOCATION -# This value determines where the p1.pl perl script (used by the -# embedded Perl interpreter) is located. If you didn't compile -# Nagios with embedded Perl support, this option has no effect. - -p1_file=/usr/local/nagios/bin/p1.pl - - - -# EMBEDDED PERL INTERPRETER OPTION -# This option determines whether or not the embedded Perl interpreter -# will be enabled during runtime. This option has no effect if Nagios -# has not been compiled with support for embedded Perl. -# Values: 0 = disable interpreter, 1 = enable interpreter - -enable_embedded_perl=1 - - - -# EMBEDDED PERL USAGE OPTION -# This option determines whether or not Nagios will process Perl plugins -# and scripts with the embedded Perl interpreter if the plugins/scripts -# do not explicitly indicate whether or not it is okay to do so. Read -# the HTML documentation on the embedded Perl interpreter for more -# information on how this option works. - -use_embedded_perl_implicitly=1 - - - -# ILLEGAL OBJECT NAME CHARACTERS -# This option allows you to specify illegal characters that cannot -# be used in host names, service descriptions, or names of other -# object types. - illegal_object_name_chars=`~!$%^&*|'"<>?,()= - - - -# ILLEGAL MACRO OUTPUT CHARACTERS -# This option allows you to specify illegal characters that are -# stripped from macros before being used in notifications, event -# handlers, etc. This DOES NOT affect macros used in service or -# host check commands. -# The following macros are stripped of the characters you specify: -# $HOSTOUTPUT$ -# $HOSTPERFDATA$ -# $HOSTACKAUTHOR$ -# $HOSTACKCOMMENT$ -# $SERVICEOUTPUT$ -# $SERVICEPERFDATA$ -# $SERVICEACKAUTHOR$ -# $SERVICEACKCOMMENT$ - illegal_macro_output_chars=`~$&|'"<> - - - -# REGULAR EXPRESSION MATCHING -# This option controls whether or not regular expression matching -# takes place in the object config files. Regular expression -# matching is used to match host, hostgroup, service, and service -# group names/descriptions in some fields of various object types. -# Values: 1 = enable regexp matching, 0 = disable regexp matching - use_regexp_matching=0 - - - -# "TRUE" REGULAR EXPRESSION MATCHING -# This option controls whether or not "true" regular expression -# matching takes place in the object config files. This option -# only has an effect if regular expression matching is enabled -# (see above). If this option is DISABLED, regular expression -# matching only occurs if a string contains wildcard characters -# (* and ?). If the option is ENABLED, regexp matching occurs -# all the time (which can be annoying). -# Values: 1 = enable true matching, 0 = disable true matching - use_true_regexp_matching=0 - - - -# ADMINISTRATOR EMAIL/PAGER ADDRESSES -# The email and pager address of a global administrator (likely you). -# Nagios never uses these values itself, but you can access them by -# using the $ADMINEMAIL$ and $ADMINPAGER$ macros in your notification -# commands. - admin_email=nagios@localhost admin_pager=pagenagios@localhost - - - -# DAEMON CORE DUMP OPTION -# This option determines whether or not Nagios is allowed to create -# a core dump when it runs as a daemon. Note that it is generally -# considered bad form to allow this, but it may be useful for -# debugging purposes. Enabling this option doesn't guarantee that -# a core file will be produced, but that's just life... -# Values: 1 - Allow core dumps -# 0 - Do not allow core dumps (default) - daemon_dumps_core=0 - - - -# LARGE INSTALLATION TWEAKS OPTION -# This option determines whether or not Nagios will take some shortcuts -# which can save on memory and CPU usage in large Nagios installations. -# Read the documentation for more information on the benefits/tradeoffs -# of enabling this option. -# Values: 1 - Enabled tweaks -# 0 - Disable tweaks (default) - use_large_installation_tweaks=0 - - - -# ENABLE ENVIRONMENT MACROS -# This option determines whether or not Nagios will make all standard -# macros available as environment variables when host/service checks -# and system commands (event handlers, notifications, etc.) are -# executed. Enabling this option can cause performance issues in -# large installations, as it will consume a bit more memory and (more -# importantly) consume more CPU. -# Values: 1 - Enable environment variable macros (default) -# 0 - Disable environment variable macros - enable_environment_macros=1 - - - -# CHILD PROCESS MEMORY OPTION -# This option determines whether or not Nagios will free memory in -# child processes (processed used to execute system commands and host/ -# service checks). If you specify a value here, it will override -# program defaults. -# Value: 1 - Free memory in child processes -# 0 - Do not free memory in child processes - -#free_child_process_memory=1 - - - -# CHILD PROCESS FORKING BEHAVIOR -# This option determines how Nagios will fork child processes -# (used to execute system commands and host/service checks). Normally -# child processes are fork()ed twice, which provides a very high level -# of isolation from problems. Fork()ing once is probably enough and will -# save a great deal on CPU usage (in large installs), so you might -# want to consider using this. If you specify a value here, it will -# program defaults. -# Value: 1 - Child processes fork() twice -# 0 - Child processes fork() just once - -#child_processes_fork_twice=1 - - - -# DEBUG LEVEL -# This option determines how much (if any) debugging information will -# be written to the debug file. OR values together to log multiple -# types of information. -# Values: -# -1 = Everything -# 0 = Nothing -# 1 = Functions -# 2 = Configuration -# 4 = Process information -# 8 = Scheduled events -# 16 = Host/service checks -# 32 = Notifications -# 64 = Event broker -# 128 = External commands -# 256 = Commands -# 512 = Scheduled downtime -# 1024 = Comments -# 2048 = Macros - debug_level=0 - - - -# DEBUG VERBOSITY -# This option determines how verbose the debug log out will be. -# Values: 0 = Brief output -# 1 = More detailed -# 2 = Very detailed - debug_verbosity=1 - - - -# DEBUG FILE -# This option determines where Nagios should write debugging information. - debug_file=/usr/local/nagios/var/nagios.debug - - - -# MAX DEBUG FILE SIZE -# This option determines the maximum size (in bytes) of the debug file. If -# the file grows larger than this size, it will be renamed with a .old -# extension. If a file already exists with a .old extension it will -# automatically be deleted. This helps ensure your disk space usage doesn't -# get out of control when debugging Nagios. - max_debug_file_size=1000000 - - diff --git a/t/etc/nagios-no-status.cfg b/t/etc/nagios-no-status.cfg index 94a9fb6..596f3ce 100644 --- a/t/etc/nagios-no-status.cfg +++ b/t/etc/nagios-no-status.cfg @@ -1,1307 +1,101 @@ -############################################################################## -# -# NAGIOS.CFG - Sample Main Config File for Nagios 3.1.0 -# -# Read the documentation for more information on this configuration -# file. I've provided some comments here, but things may not be so -# clear without further explanation. -# -# Last Modified: 12-14-2008 -# -############################################################################## - - -# LOG FILE -# This is the main log file where service and host events are logged -# for historical purposes. This should be the first option specified -# in the config file!!! - -log_file=var/nagios.log - - - -# OBJECT CONFIGURATION FILE(S) -# These are the object configuration files in which you define hosts, -# host groups, contacts, contact groups, services, etc. -# You can split your object definitions across several config files -# if you wish (as shown below), or keep them all in a single config file. - -# Note: A relative path here is relative to the location of the overall nagios.cfg file, -# not relative to the current directory +log_file=../var/nagios.log cfg_file=minimal.cfg - -# You can also tell Nagios to process all config files (with a .cfg -# extension) in a particular directory by using the cfg_dir -# directive as shown below: - -#cfg_dir=/usr/local/nagios/etc/servers -#cfg_dir=/usr/local/nagios/etc/printers -#cfg_dir=/usr/local/nagios/etc/switches -#cfg_dir=/usr/local/nagios/etc/routers - - - - -# OBJECT CACHE FILE -# This option determines where object definitions are cached when -# Nagios starts/restarts. The CGIs read object definitions from -# this cache file (rather than looking at the object config files -# directly) in order to prevent inconsistencies that can occur -# when the config files are modified after Nagios starts. - -object_cache_file=var/objects.cache - - - -# PRE-CACHED OBJECT FILE -# This options determines the location of the precached object file. -# If you run Nagios with the -p command line option, it will preprocess -# your object configuration file(s) and write the cached config to this -# file. You can then start Nagios with the -u option to have it read -# object definitions from this precached file, rather than the standard -# object configuration files (see the cfg_file and cfg_dir options above). -# Using a precached object file can speed up the time needed to (re)start -# the Nagios process if you've got a large and/or complex configuration. -# Read the documentation section on optimizing Nagios to find our more -# about how this feature works. - -precached_object_file=var/objects.precache - - - -# RESOURCE FILE -# This is an optional resource file that contains $USERx$ macro -# definitions. Multiple resource files can be specified by using -# multiple resource_file definitions. The CGIs will not attempt to -# read the contents of resource files, so information that is -# considered to be sensitive (usernames, passwords, etc) can be -# defined as macros in this file and restrictive permissions (600) -# can be placed on this file. - -resource_file=etc/resource.cfg - - - -# STATUS FILE -# This is where the current status of all monitored services and -# hosts is stored. Its contents are read and processed by the CGIs. -# The contents of the status file are deleted every time Nagios -# restarts. - -status_file=var/status.dat.no.such.file - - - -# STATUS FILE UPDATE INTERVAL -# This option determines the frequency (in seconds) that -# Nagios will periodically dump program, host, and -# service status data. - +object_cache_file=../var/objects.cache +precached_object_file=../var/objects.precache +resource_file=resource.cfg +status_file=../var/status.dat.no.such.file status_update_interval=10 - - - -# NAGIOS USER -# This determines the effective user that Nagios should run as. -# You can either supply a username or a UID. - nagios_user=nagios - - - -# NAGIOS GROUP -# This determines the effective group that Nagios should run as. -# You can either supply a group name or a GID. - nagios_group=nagios - - - -# EXTERNAL COMMAND OPTION -# This option allows you to specify whether or not Nagios should check -# for external commands (in the command file defined below). By default -# Nagios will *not* check for external commands, just to be on the -# cautious side. If you want to be able to use the CGI command interface -# you will have to enable this. -# Values: 0 = disable commands, 1 = enable commands - check_external_commands=1 - - - -# EXTERNAL COMMAND CHECK INTERVAL -# This is the interval at which Nagios should check for external commands. -# This value works of the interval_length you specify later. If you leave -# that at its default value of 60 (seconds), a value of 1 here will cause -# Nagios to check for external commands every minute. If you specify a -# number followed by an "s" (i.e. 15s), this will be interpreted to mean -# actual seconds rather than a multiple of the interval_length variable. -# Note: In addition to reading the external command file at regularly -# scheduled intervals, Nagios will also check for external commands after -# event handlers are executed. -# NOTE: Setting this value to -1 causes Nagios to check the external -# command file as often as possible. - -#command_check_interval=15s -command_check_interval=-1 - - - -# EXTERNAL COMMAND FILE -# This is the file that Nagios checks for external command requests. -# It is also where the command CGI will write commands that are submitted -# by users, so it must be writeable by the user that the web server -# is running as (usually 'nobody'). Permissions should be set at the -# directory level instead of on the file, as the file is deleted every -# time its contents are processed. - -command_file=var/rw/nagios.cmd - - - -# EXTERNAL COMMAND BUFFER SLOTS -# This settings is used to tweak the number of items or "slots" that -# the Nagios daemon should allocate to the buffer that holds incoming -# external commands before they are processed. As external commands -# are processed by the daemon, they are removed from the buffer. - -external_command_buffer_slots=4096 - - - -# LOCK FILE -# This is the lockfile that Nagios will use to store its PID number -# in when it is running in daemon mode. - -lock_file=var/nagios.lock - - - -# TEMP FILE -# This is a temporary file that is used as scratch space when Nagios -# updates the status log, cleans the comment file, etc. This file -# is created, used, and deleted throughout the time that Nagios is -# running. - -temp_file=var/nagios.tmp - - - -# TEMP PATH -# This is path where Nagios can create temp files for service and -# host check results, etc. - +command_file=../var/rw/nagios.cmd +lock_file=../var/nagios.lock +temp_file=../var/nagios.tmp temp_path=/tmp - - - -# EVENT BROKER OPTIONS -# Controls what (if any) data gets sent to the event broker. -# Values: 0 = Broker nothing -# -1 = Broker everything -# = See documentation - event_broker_options=-1 - - - -# EVENT BROKER MODULE(S) -# This directive is used to specify an event broker module that should -# by loaded by Nagios at startup. Use multiple directives if you want -# to load more than one module. Arguments that should be passed to -# the module at startup are seperated from the module path by a space. -# -#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -# WARNING !!! WARNING !!! WARNING !!! WARNING !!! WARNING !!! WARNING -#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -# -# Do NOT overwrite modules while they are being used by Nagios or Nagios -# will crash in a fiery display of SEGFAULT glory. This is a bug/limitation -# either in dlopen(), the kernel, and/or the filesystem. And maybe Nagios... -# -# The correct/safe way of updating a module is by using one of these methods: -# 1. Shutdown Nagios, replace the module file, restart Nagios -# 2. Delete the original module file, move the new module file into place, restart Nagios -# -# Example: -# -# broker_module= [moduleargs] - -#broker_module=/somewhere/module1.o -#broker_module=/somewhere/module2.o arg1 arg2=3 debug=0 - - - -# LOG ROTATION METHOD -# This is the log rotation method that Nagios should use to rotate -# the main log file. Values are as follows.. -# n = None - don't rotate the log -# h = Hourly rotation (top of the hour) -# d = Daily rotation (midnight every day) -# w = Weekly rotation (midnight on Saturday evening) -# m = Monthly rotation (midnight last day of month) - log_rotation_method=d - - - -# LOG ARCHIVE PATH -# This is the directory where archived (rotated) log files should be -# placed (assuming you've chosen to do log rotation). - log_archive_path=var/archives - - - -# LOGGING OPTIONS -# If you want messages logged to the syslog facility, as well as the -# Nagios log file set this option to 1. If not, set it to 0. - use_syslog=1 - - - -# NOTIFICATION LOGGING OPTION -# If you don't want notifications to be logged, set this value to 0. -# If notifications should be logged, set the value to 1. - log_notifications=1 - - - -# SERVICE RETRY LOGGING OPTION -# If you don't want service check retries to be logged, set this value -# to 0. If retries should be logged, set the value to 1. - log_service_retries=1 - - - -# HOST RETRY LOGGING OPTION -# If you don't want host check retries to be logged, set this value to -# 0. If retries should be logged, set the value to 1. - log_host_retries=1 - - - -# EVENT HANDLER LOGGING OPTION -# If you don't want host and service event handlers to be logged, set -# this value to 0. If event handlers should be logged, set the value -# to 1. - log_event_handlers=1 - - - -# INITIAL STATES LOGGING OPTION -# If you want Nagios to log all initial host and service states to -# the main log file (the first time the service or host is checked) -# you can enable this option by setting this value to 1. If you -# are not using an external application that does long term state -# statistics reporting, you do not need to enable this option. In -# this case, set the value to 0. - log_initial_states=0 - - - -# EXTERNAL COMMANDS LOGGING OPTION -# If you don't want Nagios to log external commands, set this value -# to 0. If external commands should be logged, set this value to 1. -# Note: This option does not include logging of passive service -# checks - see the option below for controlling whether or not -# passive checks are logged. - log_external_commands=1 - - - -# PASSIVE CHECKS LOGGING OPTION -# If you don't want Nagios to log passive host and service checks, set -# this value to 0. If passive checks should be logged, set -# this value to 1. - log_passive_checks=1 - - - -# GLOBAL HOST AND SERVICE EVENT HANDLERS -# These options allow you to specify a host and service event handler -# command that is to be run for every host or service state change. -# The global event handler is executed immediately prior to the event -# handler that you have optionally specified in each host or -# service definition. The command argument is the short name of a -# command definition that you define in your host configuration file. -# Read the HTML docs for more information. - -#global_host_event_handler=somecommand -#global_service_event_handler=somecommand - - - -# SERVICE INTER-CHECK DELAY METHOD -# This is the method that Nagios should use when initially -# "spreading out" service checks when it starts monitoring. The -# default is to use smart delay calculation, which will try to -# space all service checks out evenly to minimize CPU load. -# Using the dumb setting will cause all checks to be scheduled -# at the same time (with no delay between them)! This is not a -# good thing for production, but is useful when testing the -# parallelization functionality. -# n = None - don't use any delay between checks -# d = Use a "dumb" delay of 1 second between checks -# s = Use "smart" inter-check delay calculation -# x.xx = Use an inter-check delay of x.xx seconds - service_inter_check_delay_method=s - - - -# MAXIMUM SERVICE CHECK SPREAD -# This variable determines the timeframe (in minutes) from the -# program start time that an initial check of all services should -# be completed. Default is 30 minutes. - max_service_check_spread=30 - - - -# SERVICE CHECK INTERLEAVE FACTOR -# This variable determines how service checks are interleaved. -# Interleaving the service checks allows for a more even -# distribution of service checks and reduced load on remote -# hosts. Setting this value to 1 is equivalent to how versions -# of Nagios previous to 0.0.5 did service checks. Set this -# value to s (smart) for automatic calculation of the interleave -# factor unless you have a specific reason to change it. -# s = Use "smart" interleave factor calculation -# x = Use an interleave factor of x, where x is a -# number greater than or equal to 1. - service_interleave_factor=s - - - -# HOST INTER-CHECK DELAY METHOD -# This is the method that Nagios should use when initially -# "spreading out" host checks when it starts monitoring. The -# default is to use smart delay calculation, which will try to -# space all host checks out evenly to minimize CPU load. -# Using the dumb setting will cause all checks to be scheduled -# at the same time (with no delay between them)! -# n = None - don't use any delay between checks -# d = Use a "dumb" delay of 1 second between checks -# s = Use "smart" inter-check delay calculation -# x.xx = Use an inter-check delay of x.xx seconds - host_inter_check_delay_method=s - - - -# MAXIMUM HOST CHECK SPREAD -# This variable determines the timeframe (in minutes) from the -# program start time that an initial check of all hosts should -# be completed. Default is 30 minutes. - max_host_check_spread=30 - - - -# MAXIMUM CONCURRENT SERVICE CHECKS -# This option allows you to specify the maximum number of -# service checks that can be run in parallel at any given time. -# Specifying a value of 1 for this variable essentially prevents -# any service checks from being parallelized. A value of 0 -# will not restrict the number of concurrent checks that are -# being executed. - max_concurrent_checks=0 - - - -# HOST AND SERVICE CHECK REAPER FREQUENCY -# This is the frequency (in seconds!) that Nagios will process -# the results of host and service checks. - check_result_reaper_frequency=10 - - - - -# MAX CHECK RESULT REAPER TIME -# This is the max amount of time (in seconds) that a single -# check result reaper event will be allowed to run before -# returning control back to Nagios so it can perform other -# duties. - max_check_result_reaper_time=30 - - - - -# CHECK RESULT PATH -# This is directory where Nagios stores the results of host and -# service checks that have not yet been processed. -# -# Note: Make sure that only one instance of Nagios has access -# to this directory! - -check_result_path=var/spool/checkresults - - - - -# MAX CHECK RESULT FILE AGE -# This option determines the maximum age (in seconds) which check -# result files are considered to be valid. Files older than this -# threshold will be mercilessly deleted without further processing. - +check_result_path=/tmp max_check_result_file_age=3600 - - - - -# CACHED HOST CHECK HORIZON -# This option determines the maximum amount of time (in seconds) -# that the state of a previous host check is considered current. -# Cached host states (from host checks that were performed more -# recently that the timeframe specified by this value) can immensely -# improve performance in regards to the host check logic. -# Too high of a value for this option may result in inaccurate host -# states being used by Nagios, while a lower value may result in a -# performance hit for host checks. Use a value of 0 to disable host -# check caching. - cached_host_check_horizon=15 - - - -# CACHED SERVICE CHECK HORIZON -# This option determines the maximum amount of time (in seconds) -# that the state of a previous service check is considered current. -# Cached service states (from service checks that were performed more -# recently that the timeframe specified by this value) can immensely -# improve performance in regards to predictive dependency checks. -# Use a value of 0 to disable service check caching. - cached_service_check_horizon=15 - - - -# ENABLE PREDICTIVE HOST DEPENDENCY CHECKS -# This option determines whether or not Nagios will attempt to execute -# checks of hosts when it predicts that future dependency logic test -# may be needed. These predictive checks can help ensure that your -# host dependency logic works well. -# Values: -# 0 = Disable predictive checks -# 1 = Enable predictive checks (default) - enable_predictive_host_dependency_checks=1 - - - -# ENABLE PREDICTIVE SERVICE DEPENDENCY CHECKS -# This option determines whether or not Nagios will attempt to execute -# checks of service when it predicts that future dependency logic test -# may be needed. These predictive checks can help ensure that your -# service dependency logic works well. -# Values: -# 0 = Disable predictive checks -# 1 = Enable predictive checks (default) - enable_predictive_service_dependency_checks=1 - - - -# SOFT STATE DEPENDENCIES -# This option determines whether or not Nagios will use soft state -# information when checking host and service dependencies. Normally -# Nagios will only use the latest hard host or service state when -# checking dependencies. If you want it to use the latest state (regardless -# of whether its a soft or hard state type), enable this option. -# Values: -# 0 = Don't use soft state dependencies (default) -# 1 = Use soft state dependencies - soft_state_dependencies=0 - - - -# TIME CHANGE ADJUSTMENT THRESHOLDS -# These options determine when Nagios will react to detected changes -# in system time (either forward or backwards). - -#time_change_threshold=900 - - - -# AUTO-RESCHEDULING OPTION -# This option determines whether or not Nagios will attempt to -# automatically reschedule active host and service checks to -# "smooth" them out over time. This can help balance the load on -# the monitoring server. -# WARNING: THIS IS AN EXPERIMENTAL FEATURE - IT CAN DEGRADE -# PERFORMANCE, RATHER THAN INCREASE IT, IF USED IMPROPERLY - auto_reschedule_checks=0 - - - -# AUTO-RESCHEDULING INTERVAL -# This option determines how often (in seconds) Nagios will -# attempt to automatically reschedule checks. This option only -# has an effect if the auto_reschedule_checks option is enabled. -# Default is 30 seconds. -# WARNING: THIS IS AN EXPERIMENTAL FEATURE - IT CAN DEGRADE -# PERFORMANCE, RATHER THAN INCREASE IT, IF USED IMPROPERLY - auto_rescheduling_interval=30 - - - -# AUTO-RESCHEDULING WINDOW -# This option determines the "window" of time (in seconds) that -# Nagios will look at when automatically rescheduling checks. -# Only host and service checks that occur in the next X seconds -# (determined by this variable) will be rescheduled. This option -# only has an effect if the auto_reschedule_checks option is -# enabled. Default is 180 seconds (3 minutes). -# WARNING: THIS IS AN EXPERIMENTAL FEATURE - IT CAN DEGRADE -# PERFORMANCE, RATHER THAN INCREASE IT, IF USED IMPROPERLY - auto_rescheduling_window=180 - - - -# SLEEP TIME -# This is the number of seconds to sleep between checking for system -# events and service checks that need to be run. - -sleep_time=0.25 - - - -# TIMEOUT VALUES -# These options control how much time Nagios will allow various -# types of commands to execute before killing them off. Options -# are available for controlling maximum time allotted for -# service checks, host checks, event handlers, notifications, the -# ocsp command, and performance data commands. All values are in -# seconds. - service_check_timeout=60 host_check_timeout=30 event_handler_timeout=30 notification_timeout=30 ocsp_timeout=5 perfdata_timeout=5 - - - -# RETAIN STATE INFORMATION -# This setting determines whether or not Nagios will save state -# information for services and hosts before it shuts down. Upon -# startup Nagios will reload all saved service and host state -# information before starting to monitor. This is useful for -# maintaining long-term data on state statistics, etc, but will -# slow Nagios down a bit when it (re)starts. Since its only -# a one-time penalty, I think its well worth the additional -# startup delay. - retain_state_information=1 - - - -# STATE RETENTION FILE -# This is the file that Nagios should use to store host and -# service state information before it shuts down. The state -# information in this file is also read immediately prior to -# starting to monitor the network when Nagios is restarted. -# This file is used only if the preserve_state_information -# variable is set to 1. - state_retention_file=var/retention.dat - - - -# RETENTION DATA UPDATE INTERVAL -# This setting determines how often (in minutes) that Nagios -# will automatically save retention data during normal operation. -# If you set this value to 0, Nagios will not save retention -# data at regular interval, but it will still save retention -# data before shutting down or restarting. If you have disabled -# state retention, this option has no effect. - retention_update_interval=60 - - - -# USE RETAINED PROGRAM STATE -# This setting determines whether or not Nagios will set -# program status variables based on the values saved in the -# retention file. If you want to use retained program status -# information, set this value to 1. If not, set this value -# to 0. - use_retained_program_state=1 - - - -# USE RETAINED SCHEDULING INFO -# This setting determines whether or not Nagios will retain -# the scheduling info (next check time) for hosts and services -# based on the values saved in the retention file. If you -# If you want to use retained scheduling info, set this -# value to 1. If not, set this value to 0. - use_retained_scheduling_info=1 - - - -# RETAINED ATTRIBUTE MASKS (ADVANCED FEATURE) -# The following variables are used to specify specific host and -# service attributes that should *not* be retained by Nagios during -# program restarts. -# -# The values of the masks are bitwise ANDs of values specified -# by the "MODATTR_" definitions found in include/common.h. -# For example, if you do not want the current enabled/disabled state -# of flap detection and event handlers for hosts to be retained, you -# would use a value of 24 for the host attribute mask... -# MODATTR_EVENT_HANDLER_ENABLED (8) + MODATTR_FLAP_DETECTION_ENABLED (16) = 24 - -# This mask determines what host attributes are not retained retained_host_attribute_mask=0 - -# This mask determines what service attributes are not retained retained_service_attribute_mask=0 - -# These two masks determine what process attributes are not retained. -# There are two masks, because some process attributes have host and service -# options. For example, you can disable active host checks, but leave active -# service checks enabled. retained_process_host_attribute_mask=0 retained_process_service_attribute_mask=0 - -# These two masks determine what contact attributes are not retained. -# There are two masks, because some contact attributes have host and -# service options. For example, you can disable host notifications for -# a contact, but leave service notifications enabled for them. retained_contact_host_attribute_mask=0 retained_contact_service_attribute_mask=0 - - - -# INTERVAL LENGTH -# This is the seconds per unit interval as used in the -# host/contact/service configuration files. Setting this to 60 means -# that each interval is one minute long (60 seconds). Other settings -# have not been tested much, so your mileage is likely to vary... - interval_length=60 - - - -# CHECK FOR UPDATES -# This option determines whether Nagios will automatically check to -# see if new updates (releases) are available. It is recommend that you -# enable this option to ensure that you stay on top of the latest critical -# patches to Nagios. Nagios is critical to you - make sure you keep it in -# good shape. Nagios will check once a day for new updates. Data collected -# by Nagios Enterprises from the update check is processed in accordance -# with our privacy policy - see http://api.nagios.org for details. - check_for_updates=1 - - - -# BARE UPDATE CHECK -# This option deterines what data Nagios will send to api.nagios.org when -# it checks for updates. By default, Nagios will send information on the -# current version of Nagios you have installed, as well as an indicator as -# to whether this was a new installation or not. Nagios Enterprises uses -# this data to determine the number of users running specific version of -# Nagios. Enable this option if you do not want this information to be sent. - bare_update_check=0 - - - -# AGGRESSIVE HOST CHECKING OPTION -# If you don't want to turn on aggressive host checking features, set -# this value to 0 (the default). Otherwise set this value to 1 to -# enable the aggressive check option. Read the docs for more info -# on what aggressive host check is or check out the source code in -# base/checks.c - use_aggressive_host_checking=0 - - - -# SERVICE CHECK EXECUTION OPTION -# This determines whether or not Nagios will actively execute -# service checks when it initially starts. If this option is -# disabled, checks are not actively made, but Nagios can still -# receive and process passive check results that come in. Unless -# you're implementing redundant hosts or have a special need for -# disabling the execution of service checks, leave this enabled! -# Values: 1 = enable checks, 0 = disable checks - execute_service_checks=1 - - - -# PASSIVE SERVICE CHECK ACCEPTANCE OPTION -# This determines whether or not Nagios will accept passive -# service checks results when it initially (re)starts. -# Values: 1 = accept passive checks, 0 = reject passive checks - accept_passive_service_checks=1 - - - -# HOST CHECK EXECUTION OPTION -# This determines whether or not Nagios will actively execute -# host checks when it initially starts. If this option is -# disabled, checks are not actively made, but Nagios can still -# receive and process passive check results that come in. Unless -# you're implementing redundant hosts or have a special need for -# disabling the execution of host checks, leave this enabled! -# Values: 1 = enable checks, 0 = disable checks - execute_host_checks=1 - - - -# PASSIVE HOST CHECK ACCEPTANCE OPTION -# This determines whether or not Nagios will accept passive -# host checks results when it initially (re)starts. -# Values: 1 = accept passive checks, 0 = reject passive checks - accept_passive_host_checks=1 - - - -# NOTIFICATIONS OPTION -# This determines whether or not Nagios will sent out any host or -# service notifications when it is initially (re)started. -# Values: 1 = enable notifications, 0 = disable notifications - enable_notifications=1 - - - -# EVENT HANDLER USE OPTION -# This determines whether or not Nagios will run any host or -# service event handlers when it is initially (re)started. Unless -# you're implementing redundant hosts, leave this option enabled. -# Values: 1 = enable event handlers, 0 = disable event handlers - enable_event_handlers=1 - - - -# PROCESS PERFORMANCE DATA OPTION -# This determines whether or not Nagios will process performance -# data returned from service and host checks. If this option is -# enabled, host performance data will be processed using the -# host_perfdata_command (defined below) and service performance -# data will be processed using the service_perfdata_command (also -# defined below). Read the HTML docs for more information on -# performance data. -# Values: 1 = process performance data, 0 = do not process performance data - process_performance_data=0 - - - -# HOST AND SERVICE PERFORMANCE DATA PROCESSING COMMANDS -# These commands are run after every host and service check is -# performed. These commands are executed only if the -# enable_performance_data option (above) is set to 1. The command -# argument is the short name of a command definition that you -# define in your host configuration file. Read the HTML docs for -# more information on performance data. - -#host_perfdata_command=process-host-perfdata -#service_perfdata_command=process-service-perfdata - - - -# HOST AND SERVICE PERFORMANCE DATA FILES -# These files are used to store host and service performance data. -# Performance data is only written to these files if the -# enable_performance_data option (above) is set to 1. - -#host_perfdata_file=/tmp/host-perfdata -#service_perfdata_file=/tmp/service-perfdata - - - -# HOST AND SERVICE PERFORMANCE DATA FILE TEMPLATES -# These options determine what data is written (and how) to the -# performance data files. The templates may contain macros, special -# characters (\t for tab, \r for carriage return, \n for newline) -# and plain text. A newline is automatically added after each write -# to the performance data file. Some examples of what you can do are -# shown below. - -#host_perfdata_file_template=[HOSTPERFDATA]\t$TIMET$\t$HOSTNAME$\t$HOSTEXECUTIONTIME$\t$HOSTOUTPUT$\t$HOSTPERFDATA$ -#service_perfdata_file_template=[SERVICEPERFDATA]\t$TIMET$\t$HOSTNAME$\t$SERVICEDESC$\t$SERVICEEXECUTIONTIME$\t$SERVICELATENCY$\t$SERVICEOUTPUT$\t$SERVICEPERFDATA$ - - - -# HOST AND SERVICE PERFORMANCE DATA FILE MODES -# This option determines whether or not the host and service -# performance data files are opened in write ("w") or append ("a") -# mode. If you want to use named pipes, you should use the special -# pipe ("p") mode which avoid blocking at startup, otherwise you will -# likely want the defult append ("a") mode. - -#host_perfdata_file_mode=a -#service_perfdata_file_mode=a - - - -# HOST AND SERVICE PERFORMANCE DATA FILE PROCESSING INTERVAL -# These options determine how often (in seconds) the host and service -# performance data files are processed using the commands defined -# below. A value of 0 indicates the files should not be periodically -# processed. - -#host_perfdata_file_processing_interval=0 -#service_perfdata_file_processing_interval=0 - - - -# HOST AND SERVICE PERFORMANCE DATA FILE PROCESSING COMMANDS -# These commands are used to periodically process the host and -# service performance data files. The interval at which the -# processing occurs is determined by the options above. - -#host_perfdata_file_processing_command=process-host-perfdata-file -#service_perfdata_file_processing_command=process-service-perfdata-file - - - -# OBSESS OVER SERVICE CHECKS OPTION -# This determines whether or not Nagios will obsess over service -# checks and run the ocsp_command defined below. Unless you're -# planning on implementing distributed monitoring, do not enable -# this option. Read the HTML docs for more information on -# implementing distributed monitoring. -# Values: 1 = obsess over services, 0 = do not obsess (default) - obsess_over_services=0 - - - -# OBSESSIVE COMPULSIVE SERVICE PROCESSOR COMMAND -# This is the command that is run for every service check that is -# processed by Nagios. This command is executed only if the -# obsess_over_services option (above) is set to 1. The command -# argument is the short name of a command definition that you -# define in your host configuration file. Read the HTML docs for -# more information on implementing distributed monitoring. - -#ocsp_command=somecommand - - - -# OBSESS OVER HOST CHECKS OPTION -# This determines whether or not Nagios will obsess over host -# checks and run the ochp_command defined below. Unless you're -# planning on implementing distributed monitoring, do not enable -# this option. Read the HTML docs for more information on -# implementing distributed monitoring. -# Values: 1 = obsess over hosts, 0 = do not obsess (default) - obsess_over_hosts=0 - - - -# OBSESSIVE COMPULSIVE HOST PROCESSOR COMMAND -# This is the command that is run for every host check that is -# processed by Nagios. This command is executed only if the -# obsess_over_hosts option (above) is set to 1. The command -# argument is the short name of a command definition that you -# define in your host configuration file. Read the HTML docs for -# more information on implementing distributed monitoring. - -#ochp_command=somecommand - - - -# TRANSLATE PASSIVE HOST CHECKS OPTION -# This determines whether or not Nagios will translate -# DOWN/UNREACHABLE passive host check results into their proper -# state for this instance of Nagios. This option is useful -# if you have distributed or failover monitoring setup. In -# these cases your other Nagios servers probably have a different -# "view" of the network, with regards to the parent/child relationship -# of hosts. If a distributed monitoring server thinks a host -# is DOWN, it may actually be UNREACHABLE from the point of -# this Nagios instance. Enabling this option will tell Nagios -# to translate any DOWN or UNREACHABLE host states it receives -# passively into the correct state from the view of this server. -# Values: 1 = perform translation, 0 = do not translate (default) - translate_passive_host_checks=0 - - - -# PASSIVE HOST CHECKS ARE SOFT OPTION -# This determines whether or not Nagios will treat passive host -# checks as being HARD or SOFT. By default, a passive host check -# result will put a host into a HARD state type. This can be changed -# by enabling this option. -# Values: 0 = passive checks are HARD, 1 = passive checks are SOFT - passive_host_checks_are_soft=0 - - - -# ORPHANED HOST/SERVICE CHECK OPTIONS -# These options determine whether or not Nagios will periodically -# check for orphaned host service checks. Since service checks are -# not rescheduled until the results of their previous execution -# instance are processed, there exists a possibility that some -# checks may never get rescheduled. A similar situation exists for -# host checks, although the exact scheduling details differ a bit -# from service checks. Orphaned checks seem to be a rare -# problem and should not happen under normal circumstances. -# If you have problems with service checks never getting -# rescheduled, make sure you have orphaned service checks enabled. -# Values: 1 = enable checks, 0 = disable checks - check_for_orphaned_services=1 check_for_orphaned_hosts=1 - - - -# SERVICE FRESHNESS CHECK OPTION -# This option determines whether or not Nagios will periodically -# check the "freshness" of service results. Enabling this option -# is useful for ensuring passive checks are received in a timely -# manner. -# Values: 1 = enabled freshness checking, 0 = disable freshness checking - check_service_freshness=1 - - - -# SERVICE FRESHNESS CHECK INTERVAL -# This setting determines how often (in seconds) Nagios will -# check the "freshness" of service check results. If you have -# disabled service freshness checking, this option has no effect. - service_freshness_check_interval=60 - - - -# HOST FRESHNESS CHECK OPTION -# This option determines whether or not Nagios will periodically -# check the "freshness" of host results. Enabling this option -# is useful for ensuring passive checks are received in a timely -# manner. -# Values: 1 = enabled freshness checking, 0 = disable freshness checking - check_host_freshness=0 - - - -# HOST FRESHNESS CHECK INTERVAL -# This setting determines how often (in seconds) Nagios will -# check the "freshness" of host check results. If you have -# disabled host freshness checking, this option has no effect. - host_freshness_check_interval=60 - - - - -# ADDITIONAL FRESHNESS THRESHOLD LATENCY -# This setting determines the number of seconds that Nagios -# will add to any host and service freshness thresholds that -# it calculates (those not explicitly specified by the user). - additional_freshness_latency=15 - - - - -# FLAP DETECTION OPTION -# This option determines whether or not Nagios will try -# and detect hosts and services that are "flapping". -# Flapping occurs when a host or service changes between -# states too frequently. When Nagios detects that a -# host or service is flapping, it will temporarily suppress -# notifications for that host/service until it stops -# flapping. Flap detection is very experimental, so read -# the HTML documentation before enabling this feature! -# Values: 1 = enable flap detection -# 0 = disable flap detection (default) - enable_flap_detection=1 - - - -# FLAP DETECTION THRESHOLDS FOR HOSTS AND SERVICES -# Read the HTML documentation on flap detection for -# an explanation of what this option does. This option -# has no effect if flap detection is disabled. - low_service_flap_threshold=5.0 high_service_flap_threshold=20.0 low_host_flap_threshold=5.0 high_host_flap_threshold=20.0 - - - -# DATE FORMAT OPTION -# This option determines how short dates are displayed. Valid options -# include: -# us (MM-DD-YYYY HH:MM:SS) -# euro (DD-MM-YYYY HH:MM:SS) -# iso8601 (YYYY-MM-DD HH:MM:SS) -# strict-iso8601 (YYYY-MM-DDTHH:MM:SS) -# - date_format=us - - - - -# TIMEZONE OFFSET -# This option is used to override the default timezone that this -# instance of Nagios runs in. If not specified, Nagios will use -# the system configured timezone. -# -# NOTE: In order to display the correct timezone in the CGIs, you -# will also need to alter the Apache directives for the CGI path -# to include your timezone. Example: -# -# -# SetEnv TZ "Australia/Brisbane" -# ... -# - -#use_timezone=US/Mountain -#use_timezone=Australia/Brisbane - - - - -# P1.PL FILE LOCATION -# This value determines where the p1.pl perl script (used by the -# embedded Perl interpreter) is located. If you didn't compile -# Nagios with embedded Perl support, this option has no effect. - -p1_file=/usr/local/nagios/bin/p1.pl - - - -# EMBEDDED PERL INTERPRETER OPTION -# This option determines whether or not the embedded Perl interpreter -# will be enabled during runtime. This option has no effect if Nagios -# has not been compiled with support for embedded Perl. -# Values: 0 = disable interpreter, 1 = enable interpreter - -enable_embedded_perl=1 - - - -# EMBEDDED PERL USAGE OPTION -# This option determines whether or not Nagios will process Perl plugins -# and scripts with the embedded Perl interpreter if the plugins/scripts -# do not explicitly indicate whether or not it is okay to do so. Read -# the HTML documentation on the embedded Perl interpreter for more -# information on how this option works. - -use_embedded_perl_implicitly=1 - - - -# ILLEGAL OBJECT NAME CHARACTERS -# This option allows you to specify illegal characters that cannot -# be used in host names, service descriptions, or names of other -# object types. - illegal_object_name_chars=`~!$%^&*|'"<>?,()= - - - -# ILLEGAL MACRO OUTPUT CHARACTERS -# This option allows you to specify illegal characters that are -# stripped from macros before being used in notifications, event -# handlers, etc. This DOES NOT affect macros used in service or -# host check commands. -# The following macros are stripped of the characters you specify: -# $HOSTOUTPUT$ -# $HOSTPERFDATA$ -# $HOSTACKAUTHOR$ -# $HOSTACKCOMMENT$ -# $SERVICEOUTPUT$ -# $SERVICEPERFDATA$ -# $SERVICEACKAUTHOR$ -# $SERVICEACKCOMMENT$ - illegal_macro_output_chars=`~$&|'"<> - - - -# REGULAR EXPRESSION MATCHING -# This option controls whether or not regular expression matching -# takes place in the object config files. Regular expression -# matching is used to match host, hostgroup, service, and service -# group names/descriptions in some fields of various object types. -# Values: 1 = enable regexp matching, 0 = disable regexp matching - use_regexp_matching=0 - - - -# "TRUE" REGULAR EXPRESSION MATCHING -# This option controls whether or not "true" regular expression -# matching takes place in the object config files. This option -# only has an effect if regular expression matching is enabled -# (see above). If this option is DISABLED, regular expression -# matching only occurs if a string contains wildcard characters -# (* and ?). If the option is ENABLED, regexp matching occurs -# all the time (which can be annoying). -# Values: 1 = enable true matching, 0 = disable true matching - use_true_regexp_matching=0 - - - -# ADMINISTRATOR EMAIL/PAGER ADDRESSES -# The email and pager address of a global administrator (likely you). -# Nagios never uses these values itself, but you can access them by -# using the $ADMINEMAIL$ and $ADMINPAGER$ macros in your notification -# commands. - admin_email=nagios@localhost admin_pager=pagenagios@localhost - - - -# DAEMON CORE DUMP OPTION -# This option determines whether or not Nagios is allowed to create -# a core dump when it runs as a daemon. Note that it is generally -# considered bad form to allow this, but it may be useful for -# debugging purposes. Enabling this option doesn't guarantee that -# a core file will be produced, but that's just life... -# Values: 1 - Allow core dumps -# 0 - Do not allow core dumps (default) - daemon_dumps_core=0 - - - -# LARGE INSTALLATION TWEAKS OPTION -# This option determines whether or not Nagios will take some shortcuts -# which can save on memory and CPU usage in large Nagios installations. -# Read the documentation for more information on the benefits/tradeoffs -# of enabling this option. -# Values: 1 - Enabled tweaks -# 0 - Disable tweaks (default) - use_large_installation_tweaks=0 - - - -# ENABLE ENVIRONMENT MACROS -# This option determines whether or not Nagios will make all standard -# macros available as environment variables when host/service checks -# and system commands (event handlers, notifications, etc.) are -# executed. Enabling this option can cause performance issues in -# large installations, as it will consume a bit more memory and (more -# importantly) consume more CPU. -# Values: 1 - Enable environment variable macros (default) -# 0 - Disable environment variable macros - enable_environment_macros=1 - - - -# CHILD PROCESS MEMORY OPTION -# This option determines whether or not Nagios will free memory in -# child processes (processed used to execute system commands and host/ -# service checks). If you specify a value here, it will override -# program defaults. -# Value: 1 - Free memory in child processes -# 0 - Do not free memory in child processes - -#free_child_process_memory=1 - - - -# CHILD PROCESS FORKING BEHAVIOR -# This option determines how Nagios will fork child processes -# (used to execute system commands and host/service checks). Normally -# child processes are fork()ed twice, which provides a very high level -# of isolation from problems. Fork()ing once is probably enough and will -# save a great deal on CPU usage (in large installs), so you might -# want to consider using this. If you specify a value here, it will -# program defaults. -# Value: 1 - Child processes fork() twice -# 0 - Child processes fork() just once - -#child_processes_fork_twice=1 - - - -# DEBUG LEVEL -# This option determines how much (if any) debugging information will -# be written to the debug file. OR values together to log multiple -# types of information. -# Values: -# -1 = Everything -# 0 = Nothing -# 1 = Functions -# 2 = Configuration -# 4 = Process information -# 8 = Scheduled events -# 16 = Host/service checks -# 32 = Notifications -# 64 = Event broker -# 128 = External commands -# 256 = Commands -# 512 = Scheduled downtime -# 1024 = Comments -# 2048 = Macros - debug_level=0 - - - -# DEBUG VERBOSITY -# This option determines how verbose the debug log out will be. -# Values: 0 = Brief output -# 1 = More detailed -# 2 = Very detailed - debug_verbosity=1 - - - -# DEBUG FILE -# This option determines where Nagios should write debugging information. - debug_file=var/nagios.debug - - - -# MAX DEBUG FILE SIZE -# This option determines the maximum size (in bytes) of the debug file. If -# the file grows larger than this size, it will be renamed with a .old -# extension. If a file already exists with a .old extension it will -# automatically be deleted. This helps ensure your disk space usage doesn't -# get out of control when debugging Nagios. - max_debug_file_size=1000000 - - diff --git a/t/etc/nagios-test-downtime.cfg b/t/etc/nagios-test-downtime.cfg new file mode 100644 index 0000000..6b5f12c --- /dev/null +++ b/t/etc/nagios-test-downtime.cfg @@ -0,0 +1,101 @@ +log_file=nagios.log +cfg_file=test_downtime.cfg +object_cache_file=objects.cache +precached_object_file=objects.precache +resource_file=resource.cfg +status_file=status.dat +status_update_interval=10 +nagios_user=nagios +nagios_group=nagios +check_external_commands=1 +command_file=nagios.cmd +lock_file=nagios.lock +temp_file=nagios.tmp +temp_path=. +event_broker_options=-1 +log_rotation_method=d +log_archive_path=. +use_syslog=1 +log_notifications=1 +log_service_retries=1 +log_host_retries=1 +log_event_handlers=1 +log_initial_states=0 +log_external_commands=1 +log_passive_checks=1 +service_inter_check_delay_method=s +max_service_check_spread=30 +service_interleave_factor=s +host_inter_check_delay_method=s +max_host_check_spread=30 +max_concurrent_checks=0 +check_result_reaper_frequency=10 +max_check_result_reaper_time=30 +check_result_path=. +max_check_result_file_age=3600 +cached_host_check_horizon=15 +cached_service_check_horizon=15 +enable_predictive_host_dependency_checks=1 +enable_predictive_service_dependency_checks=1 +soft_state_dependencies=0 +auto_reschedule_checks=0 +auto_rescheduling_interval=30 +auto_rescheduling_window=180 +service_check_timeout=60 +host_check_timeout=30 +event_handler_timeout=30 +notification_timeout=30 +ocsp_timeout=5 +perfdata_timeout=5 +retain_state_information=1 +state_retention_file=retention.dat +retention_update_interval=60 +use_retained_program_state=1 +use_retained_scheduling_info=1 +retained_host_attribute_mask=0 +retained_service_attribute_mask=0 +retained_process_host_attribute_mask=0 +retained_process_service_attribute_mask=0 +retained_contact_host_attribute_mask=0 +retained_contact_service_attribute_mask=0 +interval_length=60 +check_for_updates=1 +bare_update_check=0 +use_aggressive_host_checking=0 +execute_service_checks=1 +accept_passive_service_checks=1 +execute_host_checks=1 +accept_passive_host_checks=1 +enable_notifications=1 +enable_event_handlers=1 +process_performance_data=0 +obsess_over_services=0 +obsess_over_hosts=0 +translate_passive_host_checks=0 +passive_host_checks_are_soft=0 +check_for_orphaned_services=1 +check_for_orphaned_hosts=1 +check_service_freshness=1 +service_freshness_check_interval=60 +check_host_freshness=0 +host_freshness_check_interval=60 +additional_freshness_latency=15 +enable_flap_detection=1 +low_service_flap_threshold=5.0 +high_service_flap_threshold=20.0 +low_host_flap_threshold=5.0 +high_host_flap_threshold=20.0 +date_format=us +illegal_object_name_chars=`~!$%^&*|'"<>?,()= +illegal_macro_output_chars=`~$&|'"<> +use_regexp_matching=0 +use_true_regexp_matching=0 +admin_email=nagios@localhost +admin_pager=pagenagios@localhost +daemon_dumps_core=0 +use_large_installation_tweaks=0 +enable_environment_macros=1 +debug_level=0 +debug_verbosity=1 +debug_file=nagios.debug +max_debug_file_size=1000000 diff --git a/t/etc/nagios-test-events.cfg b/t/etc/nagios-test-events.cfg new file mode 100644 index 0000000..11fb53e --- /dev/null +++ b/t/etc/nagios-test-events.cfg @@ -0,0 +1,101 @@ +log_file=nagios.log +cfg_file=test_events.cfg +object_cache_file=objects.cache +precached_object_file=objects.precache +resource_file=resource.cfg +status_file=status.dat +status_update_interval=10 +nagios_user=nagios +nagios_group=nagios +check_external_commands=1 +command_file=nagios.cmd +lock_file=nagios.lock +temp_file=nagios.tmp +temp_path=. +event_broker_options=-1 +log_rotation_method=d +log_archive_path=. +use_syslog=1 +log_notifications=1 +log_service_retries=1 +log_host_retries=1 +log_event_handlers=1 +log_initial_states=0 +log_external_commands=1 +log_passive_checks=1 +service_inter_check_delay_method=s +max_service_check_spread=30 +service_interleave_factor=s +host_inter_check_delay_method=s +max_host_check_spread=30 +max_concurrent_checks=0 +check_result_reaper_frequency=10 +max_check_result_reaper_time=30 +check_result_path=. +max_check_result_file_age=3600 +cached_host_check_horizon=15 +cached_service_check_horizon=15 +enable_predictive_host_dependency_checks=1 +enable_predictive_service_dependency_checks=1 +soft_state_dependencies=0 +auto_reschedule_checks=0 +auto_rescheduling_interval=30 +auto_rescheduling_window=180 +service_check_timeout=60 +host_check_timeout=30 +event_handler_timeout=30 +notification_timeout=30 +ocsp_timeout=5 +perfdata_timeout=5 +retain_state_information=1 +state_retention_file=retention.dat +retention_update_interval=60 +use_retained_program_state=1 +use_retained_scheduling_info=1 +retained_host_attribute_mask=0 +retained_service_attribute_mask=0 +retained_process_host_attribute_mask=0 +retained_process_service_attribute_mask=0 +retained_contact_host_attribute_mask=0 +retained_contact_service_attribute_mask=0 +interval_length=60 +check_for_updates=1 +bare_update_check=0 +use_aggressive_host_checking=0 +execute_service_checks=1 +accept_passive_service_checks=1 +execute_host_checks=1 +accept_passive_host_checks=1 +enable_notifications=1 +enable_event_handlers=1 +process_performance_data=0 +obsess_over_services=0 +obsess_over_hosts=0 +translate_passive_host_checks=0 +passive_host_checks_are_soft=0 +check_for_orphaned_services=1 +check_for_orphaned_hosts=1 +check_service_freshness=1 +service_freshness_check_interval=60 +check_host_freshness=0 +host_freshness_check_interval=60 +additional_freshness_latency=15 +enable_flap_detection=1 +low_service_flap_threshold=5.0 +high_service_flap_threshold=20.0 +low_host_flap_threshold=5.0 +high_host_flap_threshold=20.0 +date_format=us +illegal_object_name_chars=`~!$%^&*|'"<>?,()= +illegal_macro_output_chars=`~$&|'"<> +use_regexp_matching=0 +use_true_regexp_matching=0 +admin_email=nagios@localhost +admin_pager=pagenagios@localhost +daemon_dumps_core=0 +use_large_installation_tweaks=0 +enable_environment_macros=1 +debug_level=0 +debug_verbosity=1 +debug_file=nagios.debug +max_debug_file_size=1000000 diff --git a/t/etc/nagios-with-generated-status.cfg b/t/etc/nagios-with-generated-status.cfg index f438919..851945e 100644 --- a/t/etc/nagios-with-generated-status.cfg +++ b/t/etc/nagios-with-generated-status.cfg @@ -1,1307 +1,101 @@ -############################################################################## -# -# NAGIOS.CFG - Sample Main Config File for Nagios 3.1.0 -# -# Read the documentation for more information on this configuration -# file. I've provided some comments here, but things may not be so -# clear without further explanation. -# -# Last Modified: 12-14-2008 -# -############################################################################## - - -# LOG FILE -# This is the main log file where service and host events are logged -# for historical purposes. This should be the first option specified -# in the config file!!! - -log_file=var/nagios.log - - - -# OBJECT CONFIGURATION FILE(S) -# These are the object configuration files in which you define hosts, -# host groups, contacts, contact groups, services, etc. -# You can split your object definitions across several config files -# if you wish (as shown below), or keep them all in a single config file. - -# Note: A relative path here is relative to the location of the overall nagios.cfg file, -# not relative to the current directory +log_file=../var/nagios.log cfg_file=minimal.cfg - -# You can also tell Nagios to process all config files (with a .cfg -# extension) in a particular directory by using the cfg_dir -# directive as shown below: - -#cfg_dir=/usr/local/nagios/etc/servers -#cfg_dir=/usr/local/nagios/etc/printers -#cfg_dir=/usr/local/nagios/etc/switches -#cfg_dir=/usr/local/nagios/etc/routers - - - - -# OBJECT CACHE FILE -# This option determines where object definitions are cached when -# Nagios starts/restarts. The CGIs read object definitions from -# this cache file (rather than looking at the object config files -# directly) in order to prevent inconsistencies that can occur -# when the config files are modified after Nagios starts. - -object_cache_file=var/objects.cache - - - -# PRE-CACHED OBJECT FILE -# This options determines the location of the precached object file. -# If you run Nagios with the -p command line option, it will preprocess -# your object configuration file(s) and write the cached config to this -# file. You can then start Nagios with the -u option to have it read -# object definitions from this precached file, rather than the standard -# object configuration files (see the cfg_file and cfg_dir options above). -# Using a precached object file can speed up the time needed to (re)start -# the Nagios process if you've got a large and/or complex configuration. -# Read the documentation section on optimizing Nagios to find our more -# about how this feature works. - -precached_object_file=var/objects.precache - - - -# RESOURCE FILE -# This is an optional resource file that contains $USERx$ macro -# definitions. Multiple resource files can be specified by using -# multiple resource_file definitions. The CGIs will not attempt to -# read the contents of resource files, so information that is -# considered to be sensitive (usernames, passwords, etc) can be -# defined as macros in this file and restrictive permissions (600) -# can be placed on this file. - -resource_file=etc/resource.cfg - - - -# STATUS FILE -# This is where the current status of all monitored services and -# hosts is stored. Its contents are read and processed by the CGIs. -# The contents of the status file are deleted every time Nagios -# restarts. - -status_file=var/status-generated.dat - - - -# STATUS FILE UPDATE INTERVAL -# This option determines the frequency (in seconds) that -# Nagios will periodically dump program, host, and -# service status data. - +object_cache_file=../var/objects.cache +precached_object_file=../var/objects.precache +resource_file=resource.cfg +status_file=../var/status-generated.dat status_update_interval=10 - - - -# NAGIOS USER -# This determines the effective user that Nagios should run as. -# You can either supply a username or a UID. - nagios_user=nagios - - - -# NAGIOS GROUP -# This determines the effective group that Nagios should run as. -# You can either supply a group name or a GID. - nagios_group=nagios - - - -# EXTERNAL COMMAND OPTION -# This option allows you to specify whether or not Nagios should check -# for external commands (in the command file defined below). By default -# Nagios will *not* check for external commands, just to be on the -# cautious side. If you want to be able to use the CGI command interface -# you will have to enable this. -# Values: 0 = disable commands, 1 = enable commands - check_external_commands=1 - - - -# EXTERNAL COMMAND CHECK INTERVAL -# This is the interval at which Nagios should check for external commands. -# This value works of the interval_length you specify later. If you leave -# that at its default value of 60 (seconds), a value of 1 here will cause -# Nagios to check for external commands every minute. If you specify a -# number followed by an "s" (i.e. 15s), this will be interpreted to mean -# actual seconds rather than a multiple of the interval_length variable. -# Note: In addition to reading the external command file at regularly -# scheduled intervals, Nagios will also check for external commands after -# event handlers are executed. -# NOTE: Setting this value to -1 causes Nagios to check the external -# command file as often as possible. - -#command_check_interval=15s -command_check_interval=-1 - - - -# EXTERNAL COMMAND FILE -# This is the file that Nagios checks for external command requests. -# It is also where the command CGI will write commands that are submitted -# by users, so it must be writeable by the user that the web server -# is running as (usually 'nobody'). Permissions should be set at the -# directory level instead of on the file, as the file is deleted every -# time its contents are processed. - -command_file=var/rw/nagios.cmd - - - -# EXTERNAL COMMAND BUFFER SLOTS -# This settings is used to tweak the number of items or "slots" that -# the Nagios daemon should allocate to the buffer that holds incoming -# external commands before they are processed. As external commands -# are processed by the daemon, they are removed from the buffer. - -external_command_buffer_slots=4096 - - - -# LOCK FILE -# This is the lockfile that Nagios will use to store its PID number -# in when it is running in daemon mode. - -lock_file=var/nagios.lock - - - -# TEMP FILE -# This is a temporary file that is used as scratch space when Nagios -# updates the status log, cleans the comment file, etc. This file -# is created, used, and deleted throughout the time that Nagios is -# running. - -temp_file=var/nagios.tmp - - - -# TEMP PATH -# This is path where Nagios can create temp files for service and -# host check results, etc. - +command_file=../var/rw/nagios.cmd +lock_file=../var/nagios.lock +temp_file=../var/nagios.tmp temp_path=/tmp - - - -# EVENT BROKER OPTIONS -# Controls what (if any) data gets sent to the event broker. -# Values: 0 = Broker nothing -# -1 = Broker everything -# = See documentation - event_broker_options=-1 - - - -# EVENT BROKER MODULE(S) -# This directive is used to specify an event broker module that should -# by loaded by Nagios at startup. Use multiple directives if you want -# to load more than one module. Arguments that should be passed to -# the module at startup are seperated from the module path by a space. -# -#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -# WARNING !!! WARNING !!! WARNING !!! WARNING !!! WARNING !!! WARNING -#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -# -# Do NOT overwrite modules while they are being used by Nagios or Nagios -# will crash in a fiery display of SEGFAULT glory. This is a bug/limitation -# either in dlopen(), the kernel, and/or the filesystem. And maybe Nagios... -# -# The correct/safe way of updating a module is by using one of these methods: -# 1. Shutdown Nagios, replace the module file, restart Nagios -# 2. Delete the original module file, move the new module file into place, restart Nagios -# -# Example: -# -# broker_module= [moduleargs] - -#broker_module=/somewhere/module1.o -#broker_module=/somewhere/module2.o arg1 arg2=3 debug=0 - - - -# LOG ROTATION METHOD -# This is the log rotation method that Nagios should use to rotate -# the main log file. Values are as follows.. -# n = None - don't rotate the log -# h = Hourly rotation (top of the hour) -# d = Daily rotation (midnight every day) -# w = Weekly rotation (midnight on Saturday evening) -# m = Monthly rotation (midnight last day of month) - log_rotation_method=d - - - -# LOG ARCHIVE PATH -# This is the directory where archived (rotated) log files should be -# placed (assuming you've chosen to do log rotation). - -log_archive_path=var/archives - - - -# LOGGING OPTIONS -# If you want messages logged to the syslog facility, as well as the -# Nagios log file set this option to 1. If not, set it to 0. - +log_archive_path=../var/archives use_syslog=1 - - - -# NOTIFICATION LOGGING OPTION -# If you don't want notifications to be logged, set this value to 0. -# If notifications should be logged, set the value to 1. - log_notifications=1 - - - -# SERVICE RETRY LOGGING OPTION -# If you don't want service check retries to be logged, set this value -# to 0. If retries should be logged, set the value to 1. - log_service_retries=1 - - - -# HOST RETRY LOGGING OPTION -# If you don't want host check retries to be logged, set this value to -# 0. If retries should be logged, set the value to 1. - log_host_retries=1 - - - -# EVENT HANDLER LOGGING OPTION -# If you don't want host and service event handlers to be logged, set -# this value to 0. If event handlers should be logged, set the value -# to 1. - log_event_handlers=1 - - - -# INITIAL STATES LOGGING OPTION -# If you want Nagios to log all initial host and service states to -# the main log file (the first time the service or host is checked) -# you can enable this option by setting this value to 1. If you -# are not using an external application that does long term state -# statistics reporting, you do not need to enable this option. In -# this case, set the value to 0. - log_initial_states=0 - - - -# EXTERNAL COMMANDS LOGGING OPTION -# If you don't want Nagios to log external commands, set this value -# to 0. If external commands should be logged, set this value to 1. -# Note: This option does not include logging of passive service -# checks - see the option below for controlling whether or not -# passive checks are logged. - log_external_commands=1 - - - -# PASSIVE CHECKS LOGGING OPTION -# If you don't want Nagios to log passive host and service checks, set -# this value to 0. If passive checks should be logged, set -# this value to 1. - log_passive_checks=1 - - - -# GLOBAL HOST AND SERVICE EVENT HANDLERS -# These options allow you to specify a host and service event handler -# command that is to be run for every host or service state change. -# The global event handler is executed immediately prior to the event -# handler that you have optionally specified in each host or -# service definition. The command argument is the short name of a -# command definition that you define in your host configuration file. -# Read the HTML docs for more information. - -#global_host_event_handler=somecommand -#global_service_event_handler=somecommand - - - -# SERVICE INTER-CHECK DELAY METHOD -# This is the method that Nagios should use when initially -# "spreading out" service checks when it starts monitoring. The -# default is to use smart delay calculation, which will try to -# space all service checks out evenly to minimize CPU load. -# Using the dumb setting will cause all checks to be scheduled -# at the same time (with no delay between them)! This is not a -# good thing for production, but is useful when testing the -# parallelization functionality. -# n = None - don't use any delay between checks -# d = Use a "dumb" delay of 1 second between checks -# s = Use "smart" inter-check delay calculation -# x.xx = Use an inter-check delay of x.xx seconds - service_inter_check_delay_method=s - - - -# MAXIMUM SERVICE CHECK SPREAD -# This variable determines the timeframe (in minutes) from the -# program start time that an initial check of all services should -# be completed. Default is 30 minutes. - max_service_check_spread=30 - - - -# SERVICE CHECK INTERLEAVE FACTOR -# This variable determines how service checks are interleaved. -# Interleaving the service checks allows for a more even -# distribution of service checks and reduced load on remote -# hosts. Setting this value to 1 is equivalent to how versions -# of Nagios previous to 0.0.5 did service checks. Set this -# value to s (smart) for automatic calculation of the interleave -# factor unless you have a specific reason to change it. -# s = Use "smart" interleave factor calculation -# x = Use an interleave factor of x, where x is a -# number greater than or equal to 1. - service_interleave_factor=s - - - -# HOST INTER-CHECK DELAY METHOD -# This is the method that Nagios should use when initially -# "spreading out" host checks when it starts monitoring. The -# default is to use smart delay calculation, which will try to -# space all host checks out evenly to minimize CPU load. -# Using the dumb setting will cause all checks to be scheduled -# at the same time (with no delay between them)! -# n = None - don't use any delay between checks -# d = Use a "dumb" delay of 1 second between checks -# s = Use "smart" inter-check delay calculation -# x.xx = Use an inter-check delay of x.xx seconds - host_inter_check_delay_method=s - - - -# MAXIMUM HOST CHECK SPREAD -# This variable determines the timeframe (in minutes) from the -# program start time that an initial check of all hosts should -# be completed. Default is 30 minutes. - max_host_check_spread=30 - - - -# MAXIMUM CONCURRENT SERVICE CHECKS -# This option allows you to specify the maximum number of -# service checks that can be run in parallel at any given time. -# Specifying a value of 1 for this variable essentially prevents -# any service checks from being parallelized. A value of 0 -# will not restrict the number of concurrent checks that are -# being executed. - max_concurrent_checks=0 - - - -# HOST AND SERVICE CHECK REAPER FREQUENCY -# This is the frequency (in seconds!) that Nagios will process -# the results of host and service checks. - check_result_reaper_frequency=10 - - - - -# MAX CHECK RESULT REAPER TIME -# This is the max amount of time (in seconds) that a single -# check result reaper event will be allowed to run before -# returning control back to Nagios so it can perform other -# duties. - max_check_result_reaper_time=30 - - - - -# CHECK RESULT PATH -# This is directory where Nagios stores the results of host and -# service checks that have not yet been processed. -# -# Note: Make sure that only one instance of Nagios has access -# to this directory! - -check_result_path=var/spool/checkresults - - - - -# MAX CHECK RESULT FILE AGE -# This option determines the maximum age (in seconds) which check -# result files are considered to be valid. Files older than this -# threshold will be mercilessly deleted without further processing. - +check_result_path=/tmp max_check_result_file_age=3600 - - - - -# CACHED HOST CHECK HORIZON -# This option determines the maximum amount of time (in seconds) -# that the state of a previous host check is considered current. -# Cached host states (from host checks that were performed more -# recently that the timeframe specified by this value) can immensely -# improve performance in regards to the host check logic. -# Too high of a value for this option may result in inaccurate host -# states being used by Nagios, while a lower value may result in a -# performance hit for host checks. Use a value of 0 to disable host -# check caching. - cached_host_check_horizon=15 - - - -# CACHED SERVICE CHECK HORIZON -# This option determines the maximum amount of time (in seconds) -# that the state of a previous service check is considered current. -# Cached service states (from service checks that were performed more -# recently that the timeframe specified by this value) can immensely -# improve performance in regards to predictive dependency checks. -# Use a value of 0 to disable service check caching. - cached_service_check_horizon=15 - - - -# ENABLE PREDICTIVE HOST DEPENDENCY CHECKS -# This option determines whether or not Nagios will attempt to execute -# checks of hosts when it predicts that future dependency logic test -# may be needed. These predictive checks can help ensure that your -# host dependency logic works well. -# Values: -# 0 = Disable predictive checks -# 1 = Enable predictive checks (default) - enable_predictive_host_dependency_checks=1 - - - -# ENABLE PREDICTIVE SERVICE DEPENDENCY CHECKS -# This option determines whether or not Nagios will attempt to execute -# checks of service when it predicts that future dependency logic test -# may be needed. These predictive checks can help ensure that your -# service dependency logic works well. -# Values: -# 0 = Disable predictive checks -# 1 = Enable predictive checks (default) - enable_predictive_service_dependency_checks=1 - - - -# SOFT STATE DEPENDENCIES -# This option determines whether or not Nagios will use soft state -# information when checking host and service dependencies. Normally -# Nagios will only use the latest hard host or service state when -# checking dependencies. If you want it to use the latest state (regardless -# of whether its a soft or hard state type), enable this option. -# Values: -# 0 = Don't use soft state dependencies (default) -# 1 = Use soft state dependencies - soft_state_dependencies=0 - - - -# TIME CHANGE ADJUSTMENT THRESHOLDS -# These options determine when Nagios will react to detected changes -# in system time (either forward or backwards). - -#time_change_threshold=900 - - - -# AUTO-RESCHEDULING OPTION -# This option determines whether or not Nagios will attempt to -# automatically reschedule active host and service checks to -# "smooth" them out over time. This can help balance the load on -# the monitoring server. -# WARNING: THIS IS AN EXPERIMENTAL FEATURE - IT CAN DEGRADE -# PERFORMANCE, RATHER THAN INCREASE IT, IF USED IMPROPERLY - auto_reschedule_checks=0 - - - -# AUTO-RESCHEDULING INTERVAL -# This option determines how often (in seconds) Nagios will -# attempt to automatically reschedule checks. This option only -# has an effect if the auto_reschedule_checks option is enabled. -# Default is 30 seconds. -# WARNING: THIS IS AN EXPERIMENTAL FEATURE - IT CAN DEGRADE -# PERFORMANCE, RATHER THAN INCREASE IT, IF USED IMPROPERLY - auto_rescheduling_interval=30 - - - -# AUTO-RESCHEDULING WINDOW -# This option determines the "window" of time (in seconds) that -# Nagios will look at when automatically rescheduling checks. -# Only host and service checks that occur in the next X seconds -# (determined by this variable) will be rescheduled. This option -# only has an effect if the auto_reschedule_checks option is -# enabled. Default is 180 seconds (3 minutes). -# WARNING: THIS IS AN EXPERIMENTAL FEATURE - IT CAN DEGRADE -# PERFORMANCE, RATHER THAN INCREASE IT, IF USED IMPROPERLY - auto_rescheduling_window=180 - - - -# SLEEP TIME -# This is the number of seconds to sleep between checking for system -# events and service checks that need to be run. - -sleep_time=0.25 - - - -# TIMEOUT VALUES -# These options control how much time Nagios will allow various -# types of commands to execute before killing them off. Options -# are available for controlling maximum time allotted for -# service checks, host checks, event handlers, notifications, the -# ocsp command, and performance data commands. All values are in -# seconds. - service_check_timeout=60 host_check_timeout=30 event_handler_timeout=30 notification_timeout=30 ocsp_timeout=5 perfdata_timeout=5 - - - -# RETAIN STATE INFORMATION -# This setting determines whether or not Nagios will save state -# information for services and hosts before it shuts down. Upon -# startup Nagios will reload all saved service and host state -# information before starting to monitor. This is useful for -# maintaining long-term data on state statistics, etc, but will -# slow Nagios down a bit when it (re)starts. Since its only -# a one-time penalty, I think its well worth the additional -# startup delay. - retain_state_information=1 - - - -# STATE RETENTION FILE -# This is the file that Nagios should use to store host and -# service state information before it shuts down. The state -# information in this file is also read immediately prior to -# starting to monitor the network when Nagios is restarted. -# This file is used only if the preserve_state_information -# variable is set to 1. - state_retention_file=var/retention.dat - - - -# RETENTION DATA UPDATE INTERVAL -# This setting determines how often (in minutes) that Nagios -# will automatically save retention data during normal operation. -# If you set this value to 0, Nagios will not save retention -# data at regular interval, but it will still save retention -# data before shutting down or restarting. If you have disabled -# state retention, this option has no effect. - retention_update_interval=60 - - - -# USE RETAINED PROGRAM STATE -# This setting determines whether or not Nagios will set -# program status variables based on the values saved in the -# retention file. If you want to use retained program status -# information, set this value to 1. If not, set this value -# to 0. - use_retained_program_state=1 - - - -# USE RETAINED SCHEDULING INFO -# This setting determines whether or not Nagios will retain -# the scheduling info (next check time) for hosts and services -# based on the values saved in the retention file. If you -# If you want to use retained scheduling info, set this -# value to 1. If not, set this value to 0. - use_retained_scheduling_info=1 - - - -# RETAINED ATTRIBUTE MASKS (ADVANCED FEATURE) -# The following variables are used to specify specific host and -# service attributes that should *not* be retained by Nagios during -# program restarts. -# -# The values of the masks are bitwise ANDs of values specified -# by the "MODATTR_" definitions found in include/common.h. -# For example, if you do not want the current enabled/disabled state -# of flap detection and event handlers for hosts to be retained, you -# would use a value of 24 for the host attribute mask... -# MODATTR_EVENT_HANDLER_ENABLED (8) + MODATTR_FLAP_DETECTION_ENABLED (16) = 24 - -# This mask determines what host attributes are not retained retained_host_attribute_mask=0 - -# This mask determines what service attributes are not retained retained_service_attribute_mask=0 - -# These two masks determine what process attributes are not retained. -# There are two masks, because some process attributes have host and service -# options. For example, you can disable active host checks, but leave active -# service checks enabled. retained_process_host_attribute_mask=0 retained_process_service_attribute_mask=0 - -# These two masks determine what contact attributes are not retained. -# There are two masks, because some contact attributes have host and -# service options. For example, you can disable host notifications for -# a contact, but leave service notifications enabled for them. retained_contact_host_attribute_mask=0 retained_contact_service_attribute_mask=0 - - - -# INTERVAL LENGTH -# This is the seconds per unit interval as used in the -# host/contact/service configuration files. Setting this to 60 means -# that each interval is one minute long (60 seconds). Other settings -# have not been tested much, so your mileage is likely to vary... - interval_length=60 - - - -# CHECK FOR UPDATES -# This option determines whether Nagios will automatically check to -# see if new updates (releases) are available. It is recommend that you -# enable this option to ensure that you stay on top of the latest critical -# patches to Nagios. Nagios is critical to you - make sure you keep it in -# good shape. Nagios will check once a day for new updates. Data collected -# by Nagios Enterprises from the update check is processed in accordance -# with our privacy policy - see http://api.nagios.org for details. - check_for_updates=1 - - - -# BARE UPDATE CHECK -# This option deterines what data Nagios will send to api.nagios.org when -# it checks for updates. By default, Nagios will send information on the -# current version of Nagios you have installed, as well as an indicator as -# to whether this was a new installation or not. Nagios Enterprises uses -# this data to determine the number of users running specific version of -# Nagios. Enable this option if you do not want this information to be sent. - bare_update_check=0 - - - -# AGGRESSIVE HOST CHECKING OPTION -# If you don't want to turn on aggressive host checking features, set -# this value to 0 (the default). Otherwise set this value to 1 to -# enable the aggressive check option. Read the docs for more info -# on what aggressive host check is or check out the source code in -# base/checks.c - use_aggressive_host_checking=0 - - - -# SERVICE CHECK EXECUTION OPTION -# This determines whether or not Nagios will actively execute -# service checks when it initially starts. If this option is -# disabled, checks are not actively made, but Nagios can still -# receive and process passive check results that come in. Unless -# you're implementing redundant hosts or have a special need for -# disabling the execution of service checks, leave this enabled! -# Values: 1 = enable checks, 0 = disable checks - execute_service_checks=1 - - - -# PASSIVE SERVICE CHECK ACCEPTANCE OPTION -# This determines whether or not Nagios will accept passive -# service checks results when it initially (re)starts. -# Values: 1 = accept passive checks, 0 = reject passive checks - accept_passive_service_checks=1 - - - -# HOST CHECK EXECUTION OPTION -# This determines whether or not Nagios will actively execute -# host checks when it initially starts. If this option is -# disabled, checks are not actively made, but Nagios can still -# receive and process passive check results that come in. Unless -# you're implementing redundant hosts or have a special need for -# disabling the execution of host checks, leave this enabled! -# Values: 1 = enable checks, 0 = disable checks - execute_host_checks=1 - - - -# PASSIVE HOST CHECK ACCEPTANCE OPTION -# This determines whether or not Nagios will accept passive -# host checks results when it initially (re)starts. -# Values: 1 = accept passive checks, 0 = reject passive checks - accept_passive_host_checks=1 - - - -# NOTIFICATIONS OPTION -# This determines whether or not Nagios will sent out any host or -# service notifications when it is initially (re)started. -# Values: 1 = enable notifications, 0 = disable notifications - enable_notifications=1 - - - -# EVENT HANDLER USE OPTION -# This determines whether or not Nagios will run any host or -# service event handlers when it is initially (re)started. Unless -# you're implementing redundant hosts, leave this option enabled. -# Values: 1 = enable event handlers, 0 = disable event handlers - enable_event_handlers=1 - - - -# PROCESS PERFORMANCE DATA OPTION -# This determines whether or not Nagios will process performance -# data returned from service and host checks. If this option is -# enabled, host performance data will be processed using the -# host_perfdata_command (defined below) and service performance -# data will be processed using the service_perfdata_command (also -# defined below). Read the HTML docs for more information on -# performance data. -# Values: 1 = process performance data, 0 = do not process performance data - process_performance_data=0 - - - -# HOST AND SERVICE PERFORMANCE DATA PROCESSING COMMANDS -# These commands are run after every host and service check is -# performed. These commands are executed only if the -# enable_performance_data option (above) is set to 1. The command -# argument is the short name of a command definition that you -# define in your host configuration file. Read the HTML docs for -# more information on performance data. - -#host_perfdata_command=process-host-perfdata -#service_perfdata_command=process-service-perfdata - - - -# HOST AND SERVICE PERFORMANCE DATA FILES -# These files are used to store host and service performance data. -# Performance data is only written to these files if the -# enable_performance_data option (above) is set to 1. - -#host_perfdata_file=/tmp/host-perfdata -#service_perfdata_file=/tmp/service-perfdata - - - -# HOST AND SERVICE PERFORMANCE DATA FILE TEMPLATES -# These options determine what data is written (and how) to the -# performance data files. The templates may contain macros, special -# characters (\t for tab, \r for carriage return, \n for newline) -# and plain text. A newline is automatically added after each write -# to the performance data file. Some examples of what you can do are -# shown below. - -#host_perfdata_file_template=[HOSTPERFDATA]\t$TIMET$\t$HOSTNAME$\t$HOSTEXECUTIONTIME$\t$HOSTOUTPUT$\t$HOSTPERFDATA$ -#service_perfdata_file_template=[SERVICEPERFDATA]\t$TIMET$\t$HOSTNAME$\t$SERVICEDESC$\t$SERVICEEXECUTIONTIME$\t$SERVICELATENCY$\t$SERVICEOUTPUT$\t$SERVICEPERFDATA$ - - - -# HOST AND SERVICE PERFORMANCE DATA FILE MODES -# This option determines whether or not the host and service -# performance data files are opened in write ("w") or append ("a") -# mode. If you want to use named pipes, you should use the special -# pipe ("p") mode which avoid blocking at startup, otherwise you will -# likely want the defult append ("a") mode. - -#host_perfdata_file_mode=a -#service_perfdata_file_mode=a - - - -# HOST AND SERVICE PERFORMANCE DATA FILE PROCESSING INTERVAL -# These options determine how often (in seconds) the host and service -# performance data files are processed using the commands defined -# below. A value of 0 indicates the files should not be periodically -# processed. - -#host_perfdata_file_processing_interval=0 -#service_perfdata_file_processing_interval=0 - - - -# HOST AND SERVICE PERFORMANCE DATA FILE PROCESSING COMMANDS -# These commands are used to periodically process the host and -# service performance data files. The interval at which the -# processing occurs is determined by the options above. - -#host_perfdata_file_processing_command=process-host-perfdata-file -#service_perfdata_file_processing_command=process-service-perfdata-file - - - -# OBSESS OVER SERVICE CHECKS OPTION -# This determines whether or not Nagios will obsess over service -# checks and run the ocsp_command defined below. Unless you're -# planning on implementing distributed monitoring, do not enable -# this option. Read the HTML docs for more information on -# implementing distributed monitoring. -# Values: 1 = obsess over services, 0 = do not obsess (default) - obsess_over_services=0 - - - -# OBSESSIVE COMPULSIVE SERVICE PROCESSOR COMMAND -# This is the command that is run for every service check that is -# processed by Nagios. This command is executed only if the -# obsess_over_services option (above) is set to 1. The command -# argument is the short name of a command definition that you -# define in your host configuration file. Read the HTML docs for -# more information on implementing distributed monitoring. - -#ocsp_command=somecommand - - - -# OBSESS OVER HOST CHECKS OPTION -# This determines whether or not Nagios will obsess over host -# checks and run the ochp_command defined below. Unless you're -# planning on implementing distributed monitoring, do not enable -# this option. Read the HTML docs for more information on -# implementing distributed monitoring. -# Values: 1 = obsess over hosts, 0 = do not obsess (default) - obsess_over_hosts=0 - - - -# OBSESSIVE COMPULSIVE HOST PROCESSOR COMMAND -# This is the command that is run for every host check that is -# processed by Nagios. This command is executed only if the -# obsess_over_hosts option (above) is set to 1. The command -# argument is the short name of a command definition that you -# define in your host configuration file. Read the HTML docs for -# more information on implementing distributed monitoring. - -#ochp_command=somecommand - - - -# TRANSLATE PASSIVE HOST CHECKS OPTION -# This determines whether or not Nagios will translate -# DOWN/UNREACHABLE passive host check results into their proper -# state for this instance of Nagios. This option is useful -# if you have distributed or failover monitoring setup. In -# these cases your other Nagios servers probably have a different -# "view" of the network, with regards to the parent/child relationship -# of hosts. If a distributed monitoring server thinks a host -# is DOWN, it may actually be UNREACHABLE from the point of -# this Nagios instance. Enabling this option will tell Nagios -# to translate any DOWN or UNREACHABLE host states it receives -# passively into the correct state from the view of this server. -# Values: 1 = perform translation, 0 = do not translate (default) - translate_passive_host_checks=0 - - - -# PASSIVE HOST CHECKS ARE SOFT OPTION -# This determines whether or not Nagios will treat passive host -# checks as being HARD or SOFT. By default, a passive host check -# result will put a host into a HARD state type. This can be changed -# by enabling this option. -# Values: 0 = passive checks are HARD, 1 = passive checks are SOFT - passive_host_checks_are_soft=0 - - - -# ORPHANED HOST/SERVICE CHECK OPTIONS -# These options determine whether or not Nagios will periodically -# check for orphaned host service checks. Since service checks are -# not rescheduled until the results of their previous execution -# instance are processed, there exists a possibility that some -# checks may never get rescheduled. A similar situation exists for -# host checks, although the exact scheduling details differ a bit -# from service checks. Orphaned checks seem to be a rare -# problem and should not happen under normal circumstances. -# If you have problems with service checks never getting -# rescheduled, make sure you have orphaned service checks enabled. -# Values: 1 = enable checks, 0 = disable checks - check_for_orphaned_services=1 check_for_orphaned_hosts=1 - - - -# SERVICE FRESHNESS CHECK OPTION -# This option determines whether or not Nagios will periodically -# check the "freshness" of service results. Enabling this option -# is useful for ensuring passive checks are received in a timely -# manner. -# Values: 1 = enabled freshness checking, 0 = disable freshness checking - check_service_freshness=1 - - - -# SERVICE FRESHNESS CHECK INTERVAL -# This setting determines how often (in seconds) Nagios will -# check the "freshness" of service check results. If you have -# disabled service freshness checking, this option has no effect. - service_freshness_check_interval=60 - - - -# HOST FRESHNESS CHECK OPTION -# This option determines whether or not Nagios will periodically -# check the "freshness" of host results. Enabling this option -# is useful for ensuring passive checks are received in a timely -# manner. -# Values: 1 = enabled freshness checking, 0 = disable freshness checking - check_host_freshness=0 - - - -# HOST FRESHNESS CHECK INTERVAL -# This setting determines how often (in seconds) Nagios will -# check the "freshness" of host check results. If you have -# disabled host freshness checking, this option has no effect. - host_freshness_check_interval=60 - - - - -# ADDITIONAL FRESHNESS THRESHOLD LATENCY -# This setting determines the number of seconds that Nagios -# will add to any host and service freshness thresholds that -# it calculates (those not explicitly specified by the user). - additional_freshness_latency=15 - - - - -# FLAP DETECTION OPTION -# This option determines whether or not Nagios will try -# and detect hosts and services that are "flapping". -# Flapping occurs when a host or service changes between -# states too frequently. When Nagios detects that a -# host or service is flapping, it will temporarily suppress -# notifications for that host/service until it stops -# flapping. Flap detection is very experimental, so read -# the HTML documentation before enabling this feature! -# Values: 1 = enable flap detection -# 0 = disable flap detection (default) - enable_flap_detection=1 - - - -# FLAP DETECTION THRESHOLDS FOR HOSTS AND SERVICES -# Read the HTML documentation on flap detection for -# an explanation of what this option does. This option -# has no effect if flap detection is disabled. - low_service_flap_threshold=5.0 high_service_flap_threshold=20.0 low_host_flap_threshold=5.0 high_host_flap_threshold=20.0 - - - -# DATE FORMAT OPTION -# This option determines how short dates are displayed. Valid options -# include: -# us (MM-DD-YYYY HH:MM:SS) -# euro (DD-MM-YYYY HH:MM:SS) -# iso8601 (YYYY-MM-DD HH:MM:SS) -# strict-iso8601 (YYYY-MM-DDTHH:MM:SS) -# - date_format=us - - - - -# TIMEZONE OFFSET -# This option is used to override the default timezone that this -# instance of Nagios runs in. If not specified, Nagios will use -# the system configured timezone. -# -# NOTE: In order to display the correct timezone in the CGIs, you -# will also need to alter the Apache directives for the CGI path -# to include your timezone. Example: -# -# -# SetEnv TZ "Australia/Brisbane" -# ... -# - -#use_timezone=US/Mountain -#use_timezone=Australia/Brisbane - - - - -# P1.PL FILE LOCATION -# This value determines where the p1.pl perl script (used by the -# embedded Perl interpreter) is located. If you didn't compile -# Nagios with embedded Perl support, this option has no effect. - -p1_file=/usr/local/nagios/bin/p1.pl - - - -# EMBEDDED PERL INTERPRETER OPTION -# This option determines whether or not the embedded Perl interpreter -# will be enabled during runtime. This option has no effect if Nagios -# has not been compiled with support for embedded Perl. -# Values: 0 = disable interpreter, 1 = enable interpreter - -enable_embedded_perl=1 - - - -# EMBEDDED PERL USAGE OPTION -# This option determines whether or not Nagios will process Perl plugins -# and scripts with the embedded Perl interpreter if the plugins/scripts -# do not explicitly indicate whether or not it is okay to do so. Read -# the HTML documentation on the embedded Perl interpreter for more -# information on how this option works. - -use_embedded_perl_implicitly=1 - - - -# ILLEGAL OBJECT NAME CHARACTERS -# This option allows you to specify illegal characters that cannot -# be used in host names, service descriptions, or names of other -# object types. - illegal_object_name_chars=`~!$%^&*|'"<>?,()= - - - -# ILLEGAL MACRO OUTPUT CHARACTERS -# This option allows you to specify illegal characters that are -# stripped from macros before being used in notifications, event -# handlers, etc. This DOES NOT affect macros used in service or -# host check commands. -# The following macros are stripped of the characters you specify: -# $HOSTOUTPUT$ -# $HOSTPERFDATA$ -# $HOSTACKAUTHOR$ -# $HOSTACKCOMMENT$ -# $SERVICEOUTPUT$ -# $SERVICEPERFDATA$ -# $SERVICEACKAUTHOR$ -# $SERVICEACKCOMMENT$ - illegal_macro_output_chars=`~$&|'"<> - - - -# REGULAR EXPRESSION MATCHING -# This option controls whether or not regular expression matching -# takes place in the object config files. Regular expression -# matching is used to match host, hostgroup, service, and service -# group names/descriptions in some fields of various object types. -# Values: 1 = enable regexp matching, 0 = disable regexp matching - use_regexp_matching=0 - - - -# "TRUE" REGULAR EXPRESSION MATCHING -# This option controls whether or not "true" regular expression -# matching takes place in the object config files. This option -# only has an effect if regular expression matching is enabled -# (see above). If this option is DISABLED, regular expression -# matching only occurs if a string contains wildcard characters -# (* and ?). If the option is ENABLED, regexp matching occurs -# all the time (which can be annoying). -# Values: 1 = enable true matching, 0 = disable true matching - use_true_regexp_matching=0 - - - -# ADMINISTRATOR EMAIL/PAGER ADDRESSES -# The email and pager address of a global administrator (likely you). -# Nagios never uses these values itself, but you can access them by -# using the $ADMINEMAIL$ and $ADMINPAGER$ macros in your notification -# commands. - admin_email=nagios@localhost admin_pager=pagenagios@localhost - - - -# DAEMON CORE DUMP OPTION -# This option determines whether or not Nagios is allowed to create -# a core dump when it runs as a daemon. Note that it is generally -# considered bad form to allow this, but it may be useful for -# debugging purposes. Enabling this option doesn't guarantee that -# a core file will be produced, but that's just life... -# Values: 1 - Allow core dumps -# 0 - Do not allow core dumps (default) - daemon_dumps_core=0 - - - -# LARGE INSTALLATION TWEAKS OPTION -# This option determines whether or not Nagios will take some shortcuts -# which can save on memory and CPU usage in large Nagios installations. -# Read the documentation for more information on the benefits/tradeoffs -# of enabling this option. -# Values: 1 - Enabled tweaks -# 0 - Disable tweaks (default) - use_large_installation_tweaks=0 - - - -# ENABLE ENVIRONMENT MACROS -# This option determines whether or not Nagios will make all standard -# macros available as environment variables when host/service checks -# and system commands (event handlers, notifications, etc.) are -# executed. Enabling this option can cause performance issues in -# large installations, as it will consume a bit more memory and (more -# importantly) consume more CPU. -# Values: 1 - Enable environment variable macros (default) -# 0 - Disable environment variable macros - enable_environment_macros=1 - - - -# CHILD PROCESS MEMORY OPTION -# This option determines whether or not Nagios will free memory in -# child processes (processed used to execute system commands and host/ -# service checks). If you specify a value here, it will override -# program defaults. -# Value: 1 - Free memory in child processes -# 0 - Do not free memory in child processes - -#free_child_process_memory=1 - - - -# CHILD PROCESS FORKING BEHAVIOR -# This option determines how Nagios will fork child processes -# (used to execute system commands and host/service checks). Normally -# child processes are fork()ed twice, which provides a very high level -# of isolation from problems. Fork()ing once is probably enough and will -# save a great deal on CPU usage (in large installs), so you might -# want to consider using this. If you specify a value here, it will -# program defaults. -# Value: 1 - Child processes fork() twice -# 0 - Child processes fork() just once - -#child_processes_fork_twice=1 - - - -# DEBUG LEVEL -# This option determines how much (if any) debugging information will -# be written to the debug file. OR values together to log multiple -# types of information. -# Values: -# -1 = Everything -# 0 = Nothing -# 1 = Functions -# 2 = Configuration -# 4 = Process information -# 8 = Scheduled events -# 16 = Host/service checks -# 32 = Notifications -# 64 = Event broker -# 128 = External commands -# 256 = Commands -# 512 = Scheduled downtime -# 1024 = Comments -# 2048 = Macros - debug_level=0 - - - -# DEBUG VERBOSITY -# This option determines how verbose the debug log out will be. -# Values: 0 = Brief output -# 1 = More detailed -# 2 = Very detailed - debug_verbosity=1 - - - -# DEBUG FILE -# This option determines where Nagios should write debugging information. - debug_file=var/nagios.debug - - - -# MAX DEBUG FILE SIZE -# This option determines the maximum size (in bytes) of the debug file. If -# the file grows larger than this size, it will be renamed with a .old -# extension. If a file already exists with a .old extension it will -# automatically be deleted. This helps ensure your disk space usage doesn't -# get out of control when debugging Nagios. - max_debug_file_size=1000000 - - diff --git a/t/etc/nagios.cfg b/t/etc/nagios.cfg index c5d2923..eb684f8 100644 --- a/t/etc/nagios.cfg +++ b/t/etc/nagios.cfg @@ -1,1307 +1,101 @@ -############################################################################## -# -# NAGIOS.CFG - Sample Main Config File for Nagios 3.1.0 -# -# Read the documentation for more information on this configuration -# file. I've provided some comments here, but things may not be so -# clear without further explanation. -# -# Last Modified: 12-14-2008 -# -############################################################################## - - -# LOG FILE -# This is the main log file where service and host events are logged -# for historical purposes. This should be the first option specified -# in the config file!!! - -log_file=var/nagios.log - - - -# OBJECT CONFIGURATION FILE(S) -# These are the object configuration files in which you define hosts, -# host groups, contacts, contact groups, services, etc. -# You can split your object definitions across several config files -# if you wish (as shown below), or keep them all in a single config file. - -# Note: A relative path here is relative to the location of the overall nagios.cfg file, -# not relative to the current directory +log_file=../var/nagios.log cfg_file=minimal.cfg - -# You can also tell Nagios to process all config files (with a .cfg -# extension) in a particular directory by using the cfg_dir -# directive as shown below: - -#cfg_dir=/usr/local/nagios/etc/servers -#cfg_dir=/usr/local/nagios/etc/printers -#cfg_dir=/usr/local/nagios/etc/switches -#cfg_dir=/usr/local/nagios/etc/routers - - - - -# OBJECT CACHE FILE -# This option determines where object definitions are cached when -# Nagios starts/restarts. The CGIs read object definitions from -# this cache file (rather than looking at the object config files -# directly) in order to prevent inconsistencies that can occur -# when the config files are modified after Nagios starts. - -object_cache_file=var/objects.cache - - - -# PRE-CACHED OBJECT FILE -# This options determines the location of the precached object file. -# If you run Nagios with the -p command line option, it will preprocess -# your object configuration file(s) and write the cached config to this -# file. You can then start Nagios with the -u option to have it read -# object definitions from this precached file, rather than the standard -# object configuration files (see the cfg_file and cfg_dir options above). -# Using a precached object file can speed up the time needed to (re)start -# the Nagios process if you've got a large and/or complex configuration. -# Read the documentation section on optimizing Nagios to find our more -# about how this feature works. - -precached_object_file=var/objects.precache - - - -# RESOURCE FILE -# This is an optional resource file that contains $USERx$ macro -# definitions. Multiple resource files can be specified by using -# multiple resource_file definitions. The CGIs will not attempt to -# read the contents of resource files, so information that is -# considered to be sensitive (usernames, passwords, etc) can be -# defined as macros in this file and restrictive permissions (600) -# can be placed on this file. - -resource_file=etc/resource.cfg - - - -# STATUS FILE -# This is where the current status of all monitored services and -# hosts is stored. Its contents are read and processed by the CGIs. -# The contents of the status file are deleted every time Nagios -# restarts. - -status_file=var/status.dat - - - -# STATUS FILE UPDATE INTERVAL -# This option determines the frequency (in seconds) that -# Nagios will periodically dump program, host, and -# service status data. - +object_cache_file=../var/objects.cache +precached_object_file=../var/objects.precache +resource_file=resource.cfg +status_file=../var/status.dat status_update_interval=10 - - - -# NAGIOS USER -# This determines the effective user that Nagios should run as. -# You can either supply a username or a UID. - nagios_user=nagios - - - -# NAGIOS GROUP -# This determines the effective group that Nagios should run as. -# You can either supply a group name or a GID. - nagios_group=nagios - - - -# EXTERNAL COMMAND OPTION -# This option allows you to specify whether or not Nagios should check -# for external commands (in the command file defined below). By default -# Nagios will *not* check for external commands, just to be on the -# cautious side. If you want to be able to use the CGI command interface -# you will have to enable this. -# Values: 0 = disable commands, 1 = enable commands - check_external_commands=1 - - - -# EXTERNAL COMMAND CHECK INTERVAL -# This is the interval at which Nagios should check for external commands. -# This value works of the interval_length you specify later. If you leave -# that at its default value of 60 (seconds), a value of 1 here will cause -# Nagios to check for external commands every minute. If you specify a -# number followed by an "s" (i.e. 15s), this will be interpreted to mean -# actual seconds rather than a multiple of the interval_length variable. -# Note: In addition to reading the external command file at regularly -# scheduled intervals, Nagios will also check for external commands after -# event handlers are executed. -# NOTE: Setting this value to -1 causes Nagios to check the external -# command file as often as possible. - -#command_check_interval=15s -command_check_interval=-1 - - - -# EXTERNAL COMMAND FILE -# This is the file that Nagios checks for external command requests. -# It is also where the command CGI will write commands that are submitted -# by users, so it must be writeable by the user that the web server -# is running as (usually 'nobody'). Permissions should be set at the -# directory level instead of on the file, as the file is deleted every -# time its contents are processed. - -command_file=var/rw/nagios.cmd - - - -# EXTERNAL COMMAND BUFFER SLOTS -# This settings is used to tweak the number of items or "slots" that -# the Nagios daemon should allocate to the buffer that holds incoming -# external commands before they are processed. As external commands -# are processed by the daemon, they are removed from the buffer. - -external_command_buffer_slots=4096 - - - -# LOCK FILE -# This is the lockfile that Nagios will use to store its PID number -# in when it is running in daemon mode. - -lock_file=var/nagios.lock - - - -# TEMP FILE -# This is a temporary file that is used as scratch space when Nagios -# updates the status log, cleans the comment file, etc. This file -# is created, used, and deleted throughout the time that Nagios is -# running. - -temp_file=var/nagios.tmp - - - -# TEMP PATH -# This is path where Nagios can create temp files for service and -# host check results, etc. - +command_file=../var/rw/nagios.cmd +lock_file=../var/nagios.lock +temp_file=../var/nagios.tmp temp_path=/tmp - - - -# EVENT BROKER OPTIONS -# Controls what (if any) data gets sent to the event broker. -# Values: 0 = Broker nothing -# -1 = Broker everything -# = See documentation - event_broker_options=-1 - - - -# EVENT BROKER MODULE(S) -# This directive is used to specify an event broker module that should -# by loaded by Nagios at startup. Use multiple directives if you want -# to load more than one module. Arguments that should be passed to -# the module at startup are seperated from the module path by a space. -# -#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -# WARNING !!! WARNING !!! WARNING !!! WARNING !!! WARNING !!! WARNING -#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -# -# Do NOT overwrite modules while they are being used by Nagios or Nagios -# will crash in a fiery display of SEGFAULT glory. This is a bug/limitation -# either in dlopen(), the kernel, and/or the filesystem. And maybe Nagios... -# -# The correct/safe way of updating a module is by using one of these methods: -# 1. Shutdown Nagios, replace the module file, restart Nagios -# 2. Delete the original module file, move the new module file into place, restart Nagios -# -# Example: -# -# broker_module= [moduleargs] - -#broker_module=/somewhere/module1.o -#broker_module=/somewhere/module2.o arg1 arg2=3 debug=0 - - - -# LOG ROTATION METHOD -# This is the log rotation method that Nagios should use to rotate -# the main log file. Values are as follows.. -# n = None - don't rotate the log -# h = Hourly rotation (top of the hour) -# d = Daily rotation (midnight every day) -# w = Weekly rotation (midnight on Saturday evening) -# m = Monthly rotation (midnight last day of month) - log_rotation_method=d - - - -# LOG ARCHIVE PATH -# This is the directory where archived (rotated) log files should be -# placed (assuming you've chosen to do log rotation). - -log_archive_path=var/archives - - - -# LOGGING OPTIONS -# If you want messages logged to the syslog facility, as well as the -# Nagios log file set this option to 1. If not, set it to 0. - +log_archive_path=../var/archives use_syslog=1 - - - -# NOTIFICATION LOGGING OPTION -# If you don't want notifications to be logged, set this value to 0. -# If notifications should be logged, set the value to 1. - log_notifications=1 - - - -# SERVICE RETRY LOGGING OPTION -# If you don't want service check retries to be logged, set this value -# to 0. If retries should be logged, set the value to 1. - log_service_retries=1 - - - -# HOST RETRY LOGGING OPTION -# If you don't want host check retries to be logged, set this value to -# 0. If retries should be logged, set the value to 1. - log_host_retries=1 - - - -# EVENT HANDLER LOGGING OPTION -# If you don't want host and service event handlers to be logged, set -# this value to 0. If event handlers should be logged, set the value -# to 1. - log_event_handlers=1 - - - -# INITIAL STATES LOGGING OPTION -# If you want Nagios to log all initial host and service states to -# the main log file (the first time the service or host is checked) -# you can enable this option by setting this value to 1. If you -# are not using an external application that does long term state -# statistics reporting, you do not need to enable this option. In -# this case, set the value to 0. - log_initial_states=0 - - - -# EXTERNAL COMMANDS LOGGING OPTION -# If you don't want Nagios to log external commands, set this value -# to 0. If external commands should be logged, set this value to 1. -# Note: This option does not include logging of passive service -# checks - see the option below for controlling whether or not -# passive checks are logged. - log_external_commands=1 - - - -# PASSIVE CHECKS LOGGING OPTION -# If you don't want Nagios to log passive host and service checks, set -# this value to 0. If passive checks should be logged, set -# this value to 1. - log_passive_checks=1 - - - -# GLOBAL HOST AND SERVICE EVENT HANDLERS -# These options allow you to specify a host and service event handler -# command that is to be run for every host or service state change. -# The global event handler is executed immediately prior to the event -# handler that you have optionally specified in each host or -# service definition. The command argument is the short name of a -# command definition that you define in your host configuration file. -# Read the HTML docs for more information. - -#global_host_event_handler=somecommand -#global_service_event_handler=somecommand - - - -# SERVICE INTER-CHECK DELAY METHOD -# This is the method that Nagios should use when initially -# "spreading out" service checks when it starts monitoring. The -# default is to use smart delay calculation, which will try to -# space all service checks out evenly to minimize CPU load. -# Using the dumb setting will cause all checks to be scheduled -# at the same time (with no delay between them)! This is not a -# good thing for production, but is useful when testing the -# parallelization functionality. -# n = None - don't use any delay between checks -# d = Use a "dumb" delay of 1 second between checks -# s = Use "smart" inter-check delay calculation -# x.xx = Use an inter-check delay of x.xx seconds - service_inter_check_delay_method=s - - - -# MAXIMUM SERVICE CHECK SPREAD -# This variable determines the timeframe (in minutes) from the -# program start time that an initial check of all services should -# be completed. Default is 30 minutes. - max_service_check_spread=30 - - - -# SERVICE CHECK INTERLEAVE FACTOR -# This variable determines how service checks are interleaved. -# Interleaving the service checks allows for a more even -# distribution of service checks and reduced load on remote -# hosts. Setting this value to 1 is equivalent to how versions -# of Nagios previous to 0.0.5 did service checks. Set this -# value to s (smart) for automatic calculation of the interleave -# factor unless you have a specific reason to change it. -# s = Use "smart" interleave factor calculation -# x = Use an interleave factor of x, where x is a -# number greater than or equal to 1. - service_interleave_factor=s - - - -# HOST INTER-CHECK DELAY METHOD -# This is the method that Nagios should use when initially -# "spreading out" host checks when it starts monitoring. The -# default is to use smart delay calculation, which will try to -# space all host checks out evenly to minimize CPU load. -# Using the dumb setting will cause all checks to be scheduled -# at the same time (with no delay between them)! -# n = None - don't use any delay between checks -# d = Use a "dumb" delay of 1 second between checks -# s = Use "smart" inter-check delay calculation -# x.xx = Use an inter-check delay of x.xx seconds - host_inter_check_delay_method=s - - - -# MAXIMUM HOST CHECK SPREAD -# This variable determines the timeframe (in minutes) from the -# program start time that an initial check of all hosts should -# be completed. Default is 30 minutes. - max_host_check_spread=30 - - - -# MAXIMUM CONCURRENT SERVICE CHECKS -# This option allows you to specify the maximum number of -# service checks that can be run in parallel at any given time. -# Specifying a value of 1 for this variable essentially prevents -# any service checks from being parallelized. A value of 0 -# will not restrict the number of concurrent checks that are -# being executed. - max_concurrent_checks=0 - - - -# HOST AND SERVICE CHECK REAPER FREQUENCY -# This is the frequency (in seconds!) that Nagios will process -# the results of host and service checks. - check_result_reaper_frequency=10 - - - - -# MAX CHECK RESULT REAPER TIME -# This is the max amount of time (in seconds) that a single -# check result reaper event will be allowed to run before -# returning control back to Nagios so it can perform other -# duties. - max_check_result_reaper_time=30 - - - - -# CHECK RESULT PATH -# This is directory where Nagios stores the results of host and -# service checks that have not yet been processed. -# -# Note: Make sure that only one instance of Nagios has access -# to this directory! - -check_result_path=var/spool/checkresults - - - - -# MAX CHECK RESULT FILE AGE -# This option determines the maximum age (in seconds) which check -# result files are considered to be valid. Files older than this -# threshold will be mercilessly deleted without further processing. - +check_result_path=../var/spool/checkresults max_check_result_file_age=3600 - - - - -# CACHED HOST CHECK HORIZON -# This option determines the maximum amount of time (in seconds) -# that the state of a previous host check is considered current. -# Cached host states (from host checks that were performed more -# recently that the timeframe specified by this value) can immensely -# improve performance in regards to the host check logic. -# Too high of a value for this option may result in inaccurate host -# states being used by Nagios, while a lower value may result in a -# performance hit for host checks. Use a value of 0 to disable host -# check caching. - cached_host_check_horizon=15 - - - -# CACHED SERVICE CHECK HORIZON -# This option determines the maximum amount of time (in seconds) -# that the state of a previous service check is considered current. -# Cached service states (from service checks that were performed more -# recently that the timeframe specified by this value) can immensely -# improve performance in regards to predictive dependency checks. -# Use a value of 0 to disable service check caching. - cached_service_check_horizon=15 - - - -# ENABLE PREDICTIVE HOST DEPENDENCY CHECKS -# This option determines whether or not Nagios will attempt to execute -# checks of hosts when it predicts that future dependency logic test -# may be needed. These predictive checks can help ensure that your -# host dependency logic works well. -# Values: -# 0 = Disable predictive checks -# 1 = Enable predictive checks (default) - enable_predictive_host_dependency_checks=1 - - - -# ENABLE PREDICTIVE SERVICE DEPENDENCY CHECKS -# This option determines whether or not Nagios will attempt to execute -# checks of service when it predicts that future dependency logic test -# may be needed. These predictive checks can help ensure that your -# service dependency logic works well. -# Values: -# 0 = Disable predictive checks -# 1 = Enable predictive checks (default) - enable_predictive_service_dependency_checks=1 - - - -# SOFT STATE DEPENDENCIES -# This option determines whether or not Nagios will use soft state -# information when checking host and service dependencies. Normally -# Nagios will only use the latest hard host or service state when -# checking dependencies. If you want it to use the latest state (regardless -# of whether its a soft or hard state type), enable this option. -# Values: -# 0 = Don't use soft state dependencies (default) -# 1 = Use soft state dependencies - soft_state_dependencies=0 - - - -# TIME CHANGE ADJUSTMENT THRESHOLDS -# These options determine when Nagios will react to detected changes -# in system time (either forward or backwards). - -#time_change_threshold=900 - - - -# AUTO-RESCHEDULING OPTION -# This option determines whether or not Nagios will attempt to -# automatically reschedule active host and service checks to -# "smooth" them out over time. This can help balance the load on -# the monitoring server. -# WARNING: THIS IS AN EXPERIMENTAL FEATURE - IT CAN DEGRADE -# PERFORMANCE, RATHER THAN INCREASE IT, IF USED IMPROPERLY - auto_reschedule_checks=0 - - - -# AUTO-RESCHEDULING INTERVAL -# This option determines how often (in seconds) Nagios will -# attempt to automatically reschedule checks. This option only -# has an effect if the auto_reschedule_checks option is enabled. -# Default is 30 seconds. -# WARNING: THIS IS AN EXPERIMENTAL FEATURE - IT CAN DEGRADE -# PERFORMANCE, RATHER THAN INCREASE IT, IF USED IMPROPERLY - auto_rescheduling_interval=30 - - - -# AUTO-RESCHEDULING WINDOW -# This option determines the "window" of time (in seconds) that -# Nagios will look at when automatically rescheduling checks. -# Only host and service checks that occur in the next X seconds -# (determined by this variable) will be rescheduled. This option -# only has an effect if the auto_reschedule_checks option is -# enabled. Default is 180 seconds (3 minutes). -# WARNING: THIS IS AN EXPERIMENTAL FEATURE - IT CAN DEGRADE -# PERFORMANCE, RATHER THAN INCREASE IT, IF USED IMPROPERLY - auto_rescheduling_window=180 - - - -# SLEEP TIME -# This is the number of seconds to sleep between checking for system -# events and service checks that need to be run. - -sleep_time=0.25 - - - -# TIMEOUT VALUES -# These options control how much time Nagios will allow various -# types of commands to execute before killing them off. Options -# are available for controlling maximum time allotted for -# service checks, host checks, event handlers, notifications, the -# ocsp command, and performance data commands. All values are in -# seconds. - service_check_timeout=60 host_check_timeout=30 event_handler_timeout=30 notification_timeout=30 ocsp_timeout=5 perfdata_timeout=5 - - - -# RETAIN STATE INFORMATION -# This setting determines whether or not Nagios will save state -# information for services and hosts before it shuts down. Upon -# startup Nagios will reload all saved service and host state -# information before starting to monitor. This is useful for -# maintaining long-term data on state statistics, etc, but will -# slow Nagios down a bit when it (re)starts. Since its only -# a one-time penalty, I think its well worth the additional -# startup delay. - retain_state_information=1 - - - -# STATE RETENTION FILE -# This is the file that Nagios should use to store host and -# service state information before it shuts down. The state -# information in this file is also read immediately prior to -# starting to monitor the network when Nagios is restarted. -# This file is used only if the preserve_state_information -# variable is set to 1. - -state_retention_file=var/retention.dat - - - -# RETENTION DATA UPDATE INTERVAL -# This setting determines how often (in minutes) that Nagios -# will automatically save retention data during normal operation. -# If you set this value to 0, Nagios will not save retention -# data at regular interval, but it will still save retention -# data before shutting down or restarting. If you have disabled -# state retention, this option has no effect. - +state_retention_file=../var/retention.dat retention_update_interval=60 - - - -# USE RETAINED PROGRAM STATE -# This setting determines whether or not Nagios will set -# program status variables based on the values saved in the -# retention file. If you want to use retained program status -# information, set this value to 1. If not, set this value -# to 0. - use_retained_program_state=1 - - - -# USE RETAINED SCHEDULING INFO -# This setting determines whether or not Nagios will retain -# the scheduling info (next check time) for hosts and services -# based on the values saved in the retention file. If you -# If you want to use retained scheduling info, set this -# value to 1. If not, set this value to 0. - use_retained_scheduling_info=1 - - - -# RETAINED ATTRIBUTE MASKS (ADVANCED FEATURE) -# The following variables are used to specify specific host and -# service attributes that should *not* be retained by Nagios during -# program restarts. -# -# The values of the masks are bitwise ANDs of values specified -# by the "MODATTR_" definitions found in include/common.h. -# For example, if you do not want the current enabled/disabled state -# of flap detection and event handlers for hosts to be retained, you -# would use a value of 24 for the host attribute mask... -# MODATTR_EVENT_HANDLER_ENABLED (8) + MODATTR_FLAP_DETECTION_ENABLED (16) = 24 - -# This mask determines what host attributes are not retained retained_host_attribute_mask=0 - -# This mask determines what service attributes are not retained retained_service_attribute_mask=0 - -# These two masks determine what process attributes are not retained. -# There are two masks, because some process attributes have host and service -# options. For example, you can disable active host checks, but leave active -# service checks enabled. retained_process_host_attribute_mask=0 retained_process_service_attribute_mask=0 - -# These two masks determine what contact attributes are not retained. -# There are two masks, because some contact attributes have host and -# service options. For example, you can disable host notifications for -# a contact, but leave service notifications enabled for them. retained_contact_host_attribute_mask=0 retained_contact_service_attribute_mask=0 - - - -# INTERVAL LENGTH -# This is the seconds per unit interval as used in the -# host/contact/service configuration files. Setting this to 60 means -# that each interval is one minute long (60 seconds). Other settings -# have not been tested much, so your mileage is likely to vary... - interval_length=60 - - - -# CHECK FOR UPDATES -# This option determines whether Nagios will automatically check to -# see if new updates (releases) are available. It is recommend that you -# enable this option to ensure that you stay on top of the latest critical -# patches to Nagios. Nagios is critical to you - make sure you keep it in -# good shape. Nagios will check once a day for new updates. Data collected -# by Nagios Enterprises from the update check is processed in accordance -# with our privacy policy - see http://api.nagios.org for details. - check_for_updates=1 - - - -# BARE UPDATE CHECK -# This option deterines what data Nagios will send to api.nagios.org when -# it checks for updates. By default, Nagios will send information on the -# current version of Nagios you have installed, as well as an indicator as -# to whether this was a new installation or not. Nagios Enterprises uses -# this data to determine the number of users running specific version of -# Nagios. Enable this option if you do not want this information to be sent. - bare_update_check=0 - - - -# AGGRESSIVE HOST CHECKING OPTION -# If you don't want to turn on aggressive host checking features, set -# this value to 0 (the default). Otherwise set this value to 1 to -# enable the aggressive check option. Read the docs for more info -# on what aggressive host check is or check out the source code in -# base/checks.c - use_aggressive_host_checking=0 - - - -# SERVICE CHECK EXECUTION OPTION -# This determines whether or not Nagios will actively execute -# service checks when it initially starts. If this option is -# disabled, checks are not actively made, but Nagios can still -# receive and process passive check results that come in. Unless -# you're implementing redundant hosts or have a special need for -# disabling the execution of service checks, leave this enabled! -# Values: 1 = enable checks, 0 = disable checks - execute_service_checks=1 - - - -# PASSIVE SERVICE CHECK ACCEPTANCE OPTION -# This determines whether or not Nagios will accept passive -# service checks results when it initially (re)starts. -# Values: 1 = accept passive checks, 0 = reject passive checks - accept_passive_service_checks=1 - - - -# HOST CHECK EXECUTION OPTION -# This determines whether or not Nagios will actively execute -# host checks when it initially starts. If this option is -# disabled, checks are not actively made, but Nagios can still -# receive and process passive check results that come in. Unless -# you're implementing redundant hosts or have a special need for -# disabling the execution of host checks, leave this enabled! -# Values: 1 = enable checks, 0 = disable checks - execute_host_checks=1 - - - -# PASSIVE HOST CHECK ACCEPTANCE OPTION -# This determines whether or not Nagios will accept passive -# host checks results when it initially (re)starts. -# Values: 1 = accept passive checks, 0 = reject passive checks - accept_passive_host_checks=1 - - - -# NOTIFICATIONS OPTION -# This determines whether or not Nagios will sent out any host or -# service notifications when it is initially (re)started. -# Values: 1 = enable notifications, 0 = disable notifications - enable_notifications=1 - - - -# EVENT HANDLER USE OPTION -# This determines whether or not Nagios will run any host or -# service event handlers when it is initially (re)started. Unless -# you're implementing redundant hosts, leave this option enabled. -# Values: 1 = enable event handlers, 0 = disable event handlers - enable_event_handlers=1 - - - -# PROCESS PERFORMANCE DATA OPTION -# This determines whether or not Nagios will process performance -# data returned from service and host checks. If this option is -# enabled, host performance data will be processed using the -# host_perfdata_command (defined below) and service performance -# data will be processed using the service_perfdata_command (also -# defined below). Read the HTML docs for more information on -# performance data. -# Values: 1 = process performance data, 0 = do not process performance data - process_performance_data=0 - - - -# HOST AND SERVICE PERFORMANCE DATA PROCESSING COMMANDS -# These commands are run after every host and service check is -# performed. These commands are executed only if the -# enable_performance_data option (above) is set to 1. The command -# argument is the short name of a command definition that you -# define in your host configuration file. Read the HTML docs for -# more information on performance data. - -#host_perfdata_command=process-host-perfdata -#service_perfdata_command=process-service-perfdata - - - -# HOST AND SERVICE PERFORMANCE DATA FILES -# These files are used to store host and service performance data. -# Performance data is only written to these files if the -# enable_performance_data option (above) is set to 1. - -#host_perfdata_file=/tmp/host-perfdata -#service_perfdata_file=/tmp/service-perfdata - - - -# HOST AND SERVICE PERFORMANCE DATA FILE TEMPLATES -# These options determine what data is written (and how) to the -# performance data files. The templates may contain macros, special -# characters (\t for tab, \r for carriage return, \n for newline) -# and plain text. A newline is automatically added after each write -# to the performance data file. Some examples of what you can do are -# shown below. - -#host_perfdata_file_template=[HOSTPERFDATA]\t$TIMET$\t$HOSTNAME$\t$HOSTEXECUTIONTIME$\t$HOSTOUTPUT$\t$HOSTPERFDATA$ -#service_perfdata_file_template=[SERVICEPERFDATA]\t$TIMET$\t$HOSTNAME$\t$SERVICEDESC$\t$SERVICEEXECUTIONTIME$\t$SERVICELATENCY$\t$SERVICEOUTPUT$\t$SERVICEPERFDATA$ - - - -# HOST AND SERVICE PERFORMANCE DATA FILE MODES -# This option determines whether or not the host and service -# performance data files are opened in write ("w") or append ("a") -# mode. If you want to use named pipes, you should use the special -# pipe ("p") mode which avoid blocking at startup, otherwise you will -# likely want the defult append ("a") mode. - -#host_perfdata_file_mode=a -#service_perfdata_file_mode=a - - - -# HOST AND SERVICE PERFORMANCE DATA FILE PROCESSING INTERVAL -# These options determine how often (in seconds) the host and service -# performance data files are processed using the commands defined -# below. A value of 0 indicates the files should not be periodically -# processed. - -#host_perfdata_file_processing_interval=0 -#service_perfdata_file_processing_interval=0 - - - -# HOST AND SERVICE PERFORMANCE DATA FILE PROCESSING COMMANDS -# These commands are used to periodically process the host and -# service performance data files. The interval at which the -# processing occurs is determined by the options above. - -#host_perfdata_file_processing_command=process-host-perfdata-file -#service_perfdata_file_processing_command=process-service-perfdata-file - - - -# OBSESS OVER SERVICE CHECKS OPTION -# This determines whether or not Nagios will obsess over service -# checks and run the ocsp_command defined below. Unless you're -# planning on implementing distributed monitoring, do not enable -# this option. Read the HTML docs for more information on -# implementing distributed monitoring. -# Values: 1 = obsess over services, 0 = do not obsess (default) - obsess_over_services=0 - - - -# OBSESSIVE COMPULSIVE SERVICE PROCESSOR COMMAND -# This is the command that is run for every service check that is -# processed by Nagios. This command is executed only if the -# obsess_over_services option (above) is set to 1. The command -# argument is the short name of a command definition that you -# define in your host configuration file. Read the HTML docs for -# more information on implementing distributed monitoring. - -#ocsp_command=somecommand - - - -# OBSESS OVER HOST CHECKS OPTION -# This determines whether or not Nagios will obsess over host -# checks and run the ochp_command defined below. Unless you're -# planning on implementing distributed monitoring, do not enable -# this option. Read the HTML docs for more information on -# implementing distributed monitoring. -# Values: 1 = obsess over hosts, 0 = do not obsess (default) - obsess_over_hosts=0 - - - -# OBSESSIVE COMPULSIVE HOST PROCESSOR COMMAND -# This is the command that is run for every host check that is -# processed by Nagios. This command is executed only if the -# obsess_over_hosts option (above) is set to 1. The command -# argument is the short name of a command definition that you -# define in your host configuration file. Read the HTML docs for -# more information on implementing distributed monitoring. - -#ochp_command=somecommand - - - -# TRANSLATE PASSIVE HOST CHECKS OPTION -# This determines whether or not Nagios will translate -# DOWN/UNREACHABLE passive host check results into their proper -# state for this instance of Nagios. This option is useful -# if you have distributed or failover monitoring setup. In -# these cases your other Nagios servers probably have a different -# "view" of the network, with regards to the parent/child relationship -# of hosts. If a distributed monitoring server thinks a host -# is DOWN, it may actually be UNREACHABLE from the point of -# this Nagios instance. Enabling this option will tell Nagios -# to translate any DOWN or UNREACHABLE host states it receives -# passively into the correct state from the view of this server. -# Values: 1 = perform translation, 0 = do not translate (default) - translate_passive_host_checks=0 - - - -# PASSIVE HOST CHECKS ARE SOFT OPTION -# This determines whether or not Nagios will treat passive host -# checks as being HARD or SOFT. By default, a passive host check -# result will put a host into a HARD state type. This can be changed -# by enabling this option. -# Values: 0 = passive checks are HARD, 1 = passive checks are SOFT - passive_host_checks_are_soft=0 - - - -# ORPHANED HOST/SERVICE CHECK OPTIONS -# These options determine whether or not Nagios will periodically -# check for orphaned host service checks. Since service checks are -# not rescheduled until the results of their previous execution -# instance are processed, there exists a possibility that some -# checks may never get rescheduled. A similar situation exists for -# host checks, although the exact scheduling details differ a bit -# from service checks. Orphaned checks seem to be a rare -# problem and should not happen under normal circumstances. -# If you have problems with service checks never getting -# rescheduled, make sure you have orphaned service checks enabled. -# Values: 1 = enable checks, 0 = disable checks - check_for_orphaned_services=1 check_for_orphaned_hosts=1 - - - -# SERVICE FRESHNESS CHECK OPTION -# This option determines whether or not Nagios will periodically -# check the "freshness" of service results. Enabling this option -# is useful for ensuring passive checks are received in a timely -# manner. -# Values: 1 = enabled freshness checking, 0 = disable freshness checking - check_service_freshness=1 - - - -# SERVICE FRESHNESS CHECK INTERVAL -# This setting determines how often (in seconds) Nagios will -# check the "freshness" of service check results. If you have -# disabled service freshness checking, this option has no effect. - service_freshness_check_interval=60 - - - -# HOST FRESHNESS CHECK OPTION -# This option determines whether or not Nagios will periodically -# check the "freshness" of host results. Enabling this option -# is useful for ensuring passive checks are received in a timely -# manner. -# Values: 1 = enabled freshness checking, 0 = disable freshness checking - check_host_freshness=0 - - - -# HOST FRESHNESS CHECK INTERVAL -# This setting determines how often (in seconds) Nagios will -# check the "freshness" of host check results. If you have -# disabled host freshness checking, this option has no effect. - host_freshness_check_interval=60 - - - - -# ADDITIONAL FRESHNESS THRESHOLD LATENCY -# This setting determines the number of seconds that Nagios -# will add to any host and service freshness thresholds that -# it calculates (those not explicitly specified by the user). - additional_freshness_latency=15 - - - - -# FLAP DETECTION OPTION -# This option determines whether or not Nagios will try -# and detect hosts and services that are "flapping". -# Flapping occurs when a host or service changes between -# states too frequently. When Nagios detects that a -# host or service is flapping, it will temporarily suppress -# notifications for that host/service until it stops -# flapping. Flap detection is very experimental, so read -# the HTML documentation before enabling this feature! -# Values: 1 = enable flap detection -# 0 = disable flap detection (default) - enable_flap_detection=1 - - - -# FLAP DETECTION THRESHOLDS FOR HOSTS AND SERVICES -# Read the HTML documentation on flap detection for -# an explanation of what this option does. This option -# has no effect if flap detection is disabled. - low_service_flap_threshold=5.0 high_service_flap_threshold=20.0 low_host_flap_threshold=5.0 high_host_flap_threshold=20.0 - - - -# DATE FORMAT OPTION -# This option determines how short dates are displayed. Valid options -# include: -# us (MM-DD-YYYY HH:MM:SS) -# euro (DD-MM-YYYY HH:MM:SS) -# iso8601 (YYYY-MM-DD HH:MM:SS) -# strict-iso8601 (YYYY-MM-DDTHH:MM:SS) -# - date_format=us - - - - -# TIMEZONE OFFSET -# This option is used to override the default timezone that this -# instance of Nagios runs in. If not specified, Nagios will use -# the system configured timezone. -# -# NOTE: In order to display the correct timezone in the CGIs, you -# will also need to alter the Apache directives for the CGI path -# to include your timezone. Example: -# -# -# SetEnv TZ "Australia/Brisbane" -# ... -# - -#use_timezone=US/Mountain -#use_timezone=Australia/Brisbane - - - - -# P1.PL FILE LOCATION -# This value determines where the p1.pl perl script (used by the -# embedded Perl interpreter) is located. If you didn't compile -# Nagios with embedded Perl support, this option has no effect. - -p1_file=/usr/local/nagios/bin/p1.pl - - - -# EMBEDDED PERL INTERPRETER OPTION -# This option determines whether or not the embedded Perl interpreter -# will be enabled during runtime. This option has no effect if Nagios -# has not been compiled with support for embedded Perl. -# Values: 0 = disable interpreter, 1 = enable interpreter - -enable_embedded_perl=1 - - - -# EMBEDDED PERL USAGE OPTION -# This option determines whether or not Nagios will process Perl plugins -# and scripts with the embedded Perl interpreter if the plugins/scripts -# do not explicitly indicate whether or not it is okay to do so. Read -# the HTML documentation on the embedded Perl interpreter for more -# information on how this option works. - -use_embedded_perl_implicitly=1 - - - -# ILLEGAL OBJECT NAME CHARACTERS -# This option allows you to specify illegal characters that cannot -# be used in host names, service descriptions, or names of other -# object types. - illegal_object_name_chars=`~!$%^&*|'"<>?,()= - - - -# ILLEGAL MACRO OUTPUT CHARACTERS -# This option allows you to specify illegal characters that are -# stripped from macros before being used in notifications, event -# handlers, etc. This DOES NOT affect macros used in service or -# host check commands. -# The following macros are stripped of the characters you specify: -# $HOSTOUTPUT$ -# $HOSTPERFDATA$ -# $HOSTACKAUTHOR$ -# $HOSTACKCOMMENT$ -# $SERVICEOUTPUT$ -# $SERVICEPERFDATA$ -# $SERVICEACKAUTHOR$ -# $SERVICEACKCOMMENT$ - illegal_macro_output_chars=`~$&|'"<> - - - -# REGULAR EXPRESSION MATCHING -# This option controls whether or not regular expression matching -# takes place in the object config files. Regular expression -# matching is used to match host, hostgroup, service, and service -# group names/descriptions in some fields of various object types. -# Values: 1 = enable regexp matching, 0 = disable regexp matching - use_regexp_matching=0 - - - -# "TRUE" REGULAR EXPRESSION MATCHING -# This option controls whether or not "true" regular expression -# matching takes place in the object config files. This option -# only has an effect if regular expression matching is enabled -# (see above). If this option is DISABLED, regular expression -# matching only occurs if a string contains wildcard characters -# (* and ?). If the option is ENABLED, regexp matching occurs -# all the time (which can be annoying). -# Values: 1 = enable true matching, 0 = disable true matching - use_true_regexp_matching=0 - - - -# ADMINISTRATOR EMAIL/PAGER ADDRESSES -# The email and pager address of a global administrator (likely you). -# Nagios never uses these values itself, but you can access them by -# using the $ADMINEMAIL$ and $ADMINPAGER$ macros in your notification -# commands. - admin_email=nagios@localhost admin_pager=pagenagios@localhost - - - -# DAEMON CORE DUMP OPTION -# This option determines whether or not Nagios is allowed to create -# a core dump when it runs as a daemon. Note that it is generally -# considered bad form to allow this, but it may be useful for -# debugging purposes. Enabling this option doesn't guarantee that -# a core file will be produced, but that's just life... -# Values: 1 - Allow core dumps -# 0 - Do not allow core dumps (default) - daemon_dumps_core=0 - - - -# LARGE INSTALLATION TWEAKS OPTION -# This option determines whether or not Nagios will take some shortcuts -# which can save on memory and CPU usage in large Nagios installations. -# Read the documentation for more information on the benefits/tradeoffs -# of enabling this option. -# Values: 1 - Enabled tweaks -# 0 - Disable tweaks (default) - use_large_installation_tweaks=0 - - - -# ENABLE ENVIRONMENT MACROS -# This option determines whether or not Nagios will make all standard -# macros available as environment variables when host/service checks -# and system commands (event handlers, notifications, etc.) are -# executed. Enabling this option can cause performance issues in -# large installations, as it will consume a bit more memory and (more -# importantly) consume more CPU. -# Values: 1 - Enable environment variable macros (default) -# 0 - Disable environment variable macros - enable_environment_macros=1 - - - -# CHILD PROCESS MEMORY OPTION -# This option determines whether or not Nagios will free memory in -# child processes (processed used to execute system commands and host/ -# service checks). If you specify a value here, it will override -# program defaults. -# Value: 1 - Free memory in child processes -# 0 - Do not free memory in child processes - -#free_child_process_memory=1 - - - -# CHILD PROCESS FORKING BEHAVIOR -# This option determines how Nagios will fork child processes -# (used to execute system commands and host/service checks). Normally -# child processes are fork()ed twice, which provides a very high level -# of isolation from problems. Fork()ing once is probably enough and will -# save a great deal on CPU usage (in large installs), so you might -# want to consider using this. If you specify a value here, it will -# program defaults. -# Value: 1 - Child processes fork() twice -# 0 - Child processes fork() just once - -#child_processes_fork_twice=1 - - - -# DEBUG LEVEL -# This option determines how much (if any) debugging information will -# be written to the debug file. OR values together to log multiple -# types of information. -# Values: -# -1 = Everything -# 0 = Nothing -# 1 = Functions -# 2 = Configuration -# 4 = Process information -# 8 = Scheduled events -# 16 = Host/service checks -# 32 = Notifications -# 64 = Event broker -# 128 = External commands -# 256 = Commands -# 512 = Scheduled downtime -# 1024 = Comments -# 2048 = Macros - debug_level=0 - - - -# DEBUG VERBOSITY -# This option determines how verbose the debug log out will be. -# Values: 0 = Brief output -# 1 = More detailed -# 2 = Very detailed - debug_verbosity=1 - - - -# DEBUG FILE -# This option determines where Nagios should write debugging information. - -debug_file=var/nagios.debug - - - -# MAX DEBUG FILE SIZE -# This option determines the maximum size (in bytes) of the debug file. If -# the file grows larger than this size, it will be renamed with a .old -# extension. If a file already exists with a .old extension it will -# automatically be deleted. This helps ensure your disk space usage doesn't -# get out of control when debugging Nagios. - +debug_file=../var/nagios.debug max_debug_file_size=1000000 - - diff --git a/t/etc/no-contactgroup-error.cfg b/t/etc/no-contactgroup-error.cfg index 01dac44..e4fe009 100644 --- a/t/etc/no-contactgroup-error.cfg +++ b/t/etc/no-contactgroup-error.cfg @@ -8,7 +8,6 @@ define host { notification_interval 60 notification_period none } - define host { host_name host2 alias host2 test @@ -19,7 +18,6 @@ define host { notification_interval 60 notification_period none } - define service { host_name host1 service_description Dummy service @@ -32,7 +30,6 @@ define service { notification_period none contacts nagiosadmin } - define service { host_name host1,host2 service_description Uses important check command @@ -46,41 +43,34 @@ define service { contacts nagiosadmin use service-distributed } - define service { name service-distributed check_command !set_to_stale register 0 } - define command { command_name set_to_stale command_line /usr/local/nagios/libexec/set_to_stale } - define command { command_name check_me command_line /usr/local/nagios/libexec/check_me } - define command { command_name with_continuation_lines command_line $USER1$/check_foo one\ two } - define command { command_name multiple_continuation_lines_with_spaces_intermingled command_line \ check_nrpe_arg!30!\ check_fs_ping!/mnt/account-p,/mnt/prepro-p,/mnt/webapp-ssl,/mnt/rollout-p } - define timeperiod { timeperiod_name none alias Nothing } - define contact { contact_name nagiosadmin host_notifications_enabled 0 @@ -91,14 +81,12 @@ define contact { service_notification_options w,u,c,r,f,s host_notification_commands notify-none service_notification_commands notify-none - contact_groups nonexistantone + contact_groups nonexistentone } - define command { command_name notify-none command_line /usr/local/nagios/notifications/notify-none } - define contact { contact_name second host_notifications_enabled 0 @@ -116,12 +104,10 @@ define contactgroup { alias This causes a test failure by having a comma separated list before the empty contactgroup members nagiosadmin,second } - define contactgroup { contactgroup_name empty alias No members defined - this should pass validation } - define serviceescalation { host_name * service_description *,!Dummy service diff --git a/t/etc/no-service-error.cfg b/t/etc/no-service-error.cfg index df3a151..4d02461 100644 --- a/t/etc/no-service-error.cfg +++ b/t/etc/no-service-error.cfg @@ -8,17 +8,14 @@ define host { notification_interval 60 notification_period none } - define command { command_name check_me command_line /usr/local/nagios/libexec/check_me } - define timeperiod { timeperiod_name none alias Nothing } - define contact { contact_name nagiosadmin host_notifications_enabled 0 @@ -30,12 +27,10 @@ define contact { host_notification_commands notify-none service_notification_commands notify-none } - define command { command_name notify-none command_line /usr/local/nagios/notifications/notify-none } - define contact { contact_name second host_notifications_enabled 0 @@ -53,9 +48,7 @@ define contactgroup { alias This causes a test failure by having a comma separated list before the empty contactgroup members nagiosadmin,second } - define contactgroup { contactgroup_name empty alias No members defined - this should pass validation } - diff --git a/t/etc/resource.cfg b/t/etc/resource.cfg index 153d8ca..e69de29 100644 --- a/t/etc/resource.cfg +++ b/t/etc/resource.cfg @@ -1 +0,0 @@ -#Empty file diff --git a/t/etc/test_downtime.cfg b/t/etc/test_downtime.cfg new file mode 100644 index 0000000..2d169a5 --- /dev/null +++ b/t/etc/test_downtime.cfg @@ -0,0 +1,120 @@ +define host { + host_name host1 + alias host1 test + address 127.0.0.1 + max_check_attempts 2 + check_period 24x7 + check_interval 5 + retry_interval 1 + check_command check_me + contacts nagiosadmin + notification_interval 60 + notification_period none +} + +define host { + host_name host2 + alias host2 test + address 127.0.0.1 + max_check_attempts 2 + check_period 24x7 + check_interval 5 + retry_interval 1 + check_command check_me + contacts nagiosadmin + notification_interval 60 + notification_period none +} + +define host { + host_name host3 + alias host3 test + address 127.0.0.1 + max_check_attempts 2 + check_period 24x7 + check_interval 5 + retry_interval 1 + check_command check_me + contacts nagiosadmin + notification_interval 60 + notification_period none +} + +define host { + host_name host4 + alias host4 test + address 127.0.0.1 + max_check_attempts 2 + check_period 24x7 + check_interval 5 + retry_interval 1 + check_command check_me + contacts nagiosadmin + notification_interval 60 + notification_period none +} + +define service { + host_name host1,host2,host3,host4 + service_description svc + check_command check_me + max_check_attempts 3 + check_interval 32 + retry_interval 1 + check_period 24x7 + notification_interval 60 + notification_period none + contacts nagiosadmin +} + +define service { + host_name host1,host2,host3,host4 + service_description svc2 + check_command check_me + max_check_attempts 3 + check_interval 32 + retry_interval 1 + check_period 24x7 + notification_interval 60 + notification_period none + contacts nagiosadmin +} + +define command { + command_name check_me + command_line /usr/local/nagios/libexec/check_me +} + +define timeperiod { + timeperiod_name none + alias Nothing +} + +define timeperiod { + timeperiod_name 24x7 + alias 24x7 base on weekdays + monday 00:00-24:00 + tuesday 00:00-24:00 + wednesday 00:00-24:00 + thursday 00:00-24:00 + friday 00:00-24:00 + saturday 00:00-24:00 + sunday 00:00-24:00 +} + +define contact { + contact_name nagiosadmin + host_notifications_enabled 0 + service_notifications_enabled 0 + host_notification_period none + service_notification_period none + host_notification_options d,u,f,r,s + service_notification_options w,u,c,r,f,s + host_notification_commands notify-none + service_notification_commands notify-none +} + +define command { + command_name notify-none + command_line /usr/local/nagios/notifications/notify-none +} diff --git a/t/etc/test_events.cfg b/t/etc/test_events.cfg new file mode 100644 index 0000000..7419a15 --- /dev/null +++ b/t/etc/test_events.cfg @@ -0,0 +1,91 @@ +define host { + host_name host1 + alias host1 test + address 127.0.0.1 + max_check_attempts 2 + check_period 24x7 + check_interval 5 + retry_interval 1 + check_command check_me + contacts nagiosadmin + notification_interval 60 + notification_period none +} + +define service { + host_name host1 + service_description Normal service + check_command check_me + max_check_attempts 3 + check_interval 32 + retry_interval 1 + check_period 24x7 + notification_interval 60 + notification_period none + contacts nagiosadmin +} + +define service { + host_name host1 + service_description Normal service 2 + check_command check_me + max_check_attempts 3 + check_interval 32 + retry_interval 1 + check_period 24x7 + notification_interval 60 + notification_period none + contacts nagiosadmin +} + +define service { + host_name host1 + service_description To be nudged + check_command check_me + max_check_attempts 2 + check_interval 32 + retry_interval 1 + check_period 24x7 + notification_interval 60 + notification_period none + contacts nagiosadmin +} + +define command { + command_name check_me + command_line /usr/local/nagios/libexec/check_me +} + +define timeperiod { + timeperiod_name none + alias Nothing +} + +define timeperiod { + timeperiod_name 24x7 + alias 24x7 base on weekdays + monday 00:00-24:00 + tuesday 00:00-24:00 + wednesday 00:00-24:00 + thursday 00:00-24:00 + friday 00:00-24:00 + saturday 00:00-24:00 + sunday 00:00-24:00 +} + +define contact { + contact_name nagiosadmin + host_notifications_enabled 0 + service_notifications_enabled 0 + host_notification_period none + service_notification_period none + host_notification_options d,u,f,r,s + service_notification_options w,u,c,r,f,s + host_notification_commands notify-none + service_notification_commands notify-none +} + +define command { + command_name notify-none + command_line /usr/local/nagios/notifications/notify-none +} diff --git a/t/var/nagios.log b/t/var/nagios.log index 9a79cd3..e69de29 100644 --- a/t/var/nagios.log +++ b/t/var/nagios.log @@ -1,8 +0,0 @@ -[1242341771] Nagios 3.1.0 starting... (PID=48448) -[1242341771] Local time is Thu May 14 23:56:11 BST 2009 -[1242341771] LOG VERSION: 2.0 -[1242341771] Error: Could not create external command file 'var/rw/nagios.cmd' as named pipe: (2) -> No such file or directory. If this file already exists and you are sure that another copy of Nagios is not running, you should delete this file. -[1242341771] Bailing out due to errors encountered while trying to initialize the external command file... (PID=48448) -[1242341791] Nagios 3.1.0 starting... (PID=48451) -[1242341791] Local time is Thu May 14 23:56:31 BST 2009 -[1242341791] LOG VERSION: 2.0 diff --git a/t/var/objects.cache b/t/var/objects.cache index a661b7c..2e02ce8 100644 --- a/t/var/objects.cache +++ b/t/var/objects.cache @@ -28,6 +28,12 @@ define contactgroup { members second,nagiosadmin } +define contactgroup { + contactgroup_name normalhostcontactgroup + alias This contact group is assigned to a host normally + members second + } + define contactgroup { contactgroup_name empty alias No members defined - this should pass validation @@ -69,6 +75,7 @@ define host { address 192.168.1.1 check_period none contacts nagiosadmin + contact_groups normalhostcontactgroup notification_period none initial_state o check_interval 5.000000 @@ -90,7 +97,6 @@ define host { first_notification_delay 0.000000 stalking_options n process_perf_data 1 - failure_prediction_enabled 1 retain_status_information 1 retain_nonstatus_information 1 } @@ -122,7 +128,6 @@ define host { first_notification_delay 0.000000 stalking_options n process_perf_data 1 - failure_prediction_enabled 1 retain_status_information 1 retain_nonstatus_information 1 } @@ -133,6 +138,7 @@ define service { check_period none check_command check_me contacts nagiosadmin + contact_groups normalhostcontactgroup notification_period none initial_state o check_interval 32.000000 @@ -156,7 +162,6 @@ define service { first_notification_delay 0.000000 stalking_options n process_perf_data 1 - failure_prediction_enabled 1 retain_status_information 1 retain_nonstatus_information 1 } @@ -190,7 +195,6 @@ define service { first_notification_delay 0.000000 stalking_options n process_perf_data 1 - failure_prediction_enabled 1 retain_status_information 1 retain_nonstatus_information 1 } diff --git a/t/var/objects.cache.hosturgencies b/t/var/objects.cache.hosturgencies index ddda905..94f8065 100644 --- a/t/var/objects.cache.hosturgencies +++ b/t/var/objects.cache.hosturgencies @@ -197,7 +197,99 @@ define host { first_notification_delay 0.000000 stalking_options n process_perf_data 1 - failure_prediction_enabled 1 + retain_status_information 1 + retain_nonstatus_information 1 + } + +define host { + host_name host2 + alias host2 test + address 192.168.1.1 + check_period none + contacts nagiosadmin + notification_period none + initial_state o + check_interval 5.000000 + retry_interval 1.000000 + max_check_attempts 2 + active_checks_enabled 1 + passive_checks_enabled 1 + obsess_over_host 1 + event_handler_enabled 1 + low_flap_threshold 0.000000 + high_flap_threshold 0.000000 + flap_detection_enabled 1 + flap_detection_options o,d,u + freshness_threshold 0 + check_freshness 0 + notification_options d,u,r,f,s + notifications_enabled 1 + notification_interval 60.000000 + first_notification_delay 0.000000 + stalking_options n + process_perf_data 1 + retain_status_information 1 + retain_nonstatus_information 1 + } + +define host { + host_name host3 + alias host3 test + address 192.168.1.1 + check_period none + contacts nagiosadmin + notification_period none + initial_state o + check_interval 5.000000 + retry_interval 1.000000 + max_check_attempts 2 + active_checks_enabled 1 + passive_checks_enabled 1 + obsess_over_host 1 + event_handler_enabled 1 + low_flap_threshold 0.000000 + high_flap_threshold 0.000000 + flap_detection_enabled 1 + flap_detection_options o,d,u + freshness_threshold 0 + check_freshness 0 + notification_options d,u,r,f,s + notifications_enabled 1 + notification_interval 60.000000 + first_notification_delay 0.000000 + stalking_options n + process_perf_data 1 + retain_status_information 1 + retain_nonstatus_information 1 + } + +define host { + host_name host4 + alias host1 test + address 192.168.1.1 + check_period none + contacts nagiosadmin + notification_period none + initial_state o + check_interval 5.000000 + retry_interval 1.000000 + max_check_attempts 2 + active_checks_enabled 1 + passive_checks_enabled 1 + obsess_over_host 1 + event_handler_enabled 1 + low_flap_threshold 0.000000 + high_flap_threshold 0.000000 + flap_detection_enabled 1 + flap_detection_options o,d,u + freshness_threshold 0 + check_freshness 0 + notification_options d,u,r,f,s + notifications_enabled 1 + notification_interval 60.000000 + first_notification_delay 0.000000 + stalking_options n + process_perf_data 1 retain_status_information 1 retain_nonstatus_information 1 } @@ -229,7 +321,6 @@ define host { first_notification_delay 0.000000 stalking_options n process_perf_data 1 - failure_prediction_enabled 1 retain_status_information 1 retain_nonstatus_information 1 } @@ -263,7 +354,6 @@ define service { first_notification_delay 0.000000 stalking_options n process_perf_data 1 - failure_prediction_enabled 1 retain_status_information 1 retain_nonstatus_information 1 } @@ -297,7 +387,6 @@ define service { first_notification_delay 0.000000 stalking_options n process_perf_data 1 - failure_prediction_enabled 1 retain_status_information 1 retain_nonstatus_information 1 } @@ -331,7 +420,6 @@ define service { first_notification_delay 0.000000 stalking_options n process_perf_data 1 - failure_prediction_enabled 1 retain_status_information 1 retain_nonstatus_information 1 } diff --git a/t/var/objects.precache.expected b/t/var/objects.precache.expected index 34da93d..2af9759 100644 --- a/t/var/objects.precache.expected +++ b/t/var/objects.precache.expected @@ -61,12 +61,14 @@ define servicegroup { define contact { contact_name nagiosadmin + alias nagiosadmin service_notification_period none host_notification_period none - service_notification_options w,u,c,r,f,s - host_notification_options d,u,r,f,s + service_notification_options r,w,u,c,f,s + host_notification_options r,d,u,f,s service_notification_commands notify-none host_notification_commands notify-none + minimum_value 1 host_notifications_enabled 0 service_notifications_enabled 0 can_submit_commands 1 @@ -76,12 +78,14 @@ define contact { define contact { contact_name second + alias second service_notification_period none host_notification_period none - service_notification_options w,u,c,r,f,s - host_notification_options d,u,r,f,s + service_notification_options r,w,u,c,f,s + host_notification_options r,d,u,f,s service_notification_commands notify-none host_notification_commands notify-none + minimum_value 1 host_notifications_enabled 0 service_notifications_enabled 0 can_submit_commands 1 @@ -97,26 +101,26 @@ define host { contacts nagiosadmin notification_period none initial_state o + hourly_value 3 check_interval 5.000000 retry_interval 1.000000 max_check_attempts 2 active_checks_enabled 1 passive_checks_enabled 1 - obsess_over_host 1 + obsess 1 event_handler_enabled 1 low_flap_threshold 0.000000 high_flap_threshold 0.000000 flap_detection_enabled 1 - flap_detection_options o,d,u + flap_detection_options a freshness_threshold 0 check_freshness 0 - notification_options d,u,r,f,s + notification_options a notifications_enabled 1 notification_interval 60.000000 first_notification_delay 0.000000 stalking_options n process_perf_data 1 - failure_prediction_enabled 1 retain_status_information 1 retain_nonstatus_information 1 } @@ -129,26 +133,26 @@ define host { contacts nagiosadmin notification_period none initial_state o + hourly_value 2 check_interval 5.000000 retry_interval 1.000000 max_check_attempts 2 active_checks_enabled 1 passive_checks_enabled 1 - obsess_over_host 1 + obsess 1 event_handler_enabled 1 low_flap_threshold 0.000000 high_flap_threshold 0.000000 flap_detection_enabled 1 - flap_detection_options o,d,u + flap_detection_options a freshness_threshold 0 check_freshness 0 - notification_options d,u,r,f,s + notification_options a notifications_enabled 1 notification_interval 60.000000 first_notification_delay 0.000000 stalking_options n process_perf_data 1 - failure_prediction_enabled 1 retain_status_information 1 retain_nonstatus_information 1 } @@ -161,26 +165,26 @@ define host { contacts nagiosadmin notification_period none initial_state o + hourly_value 3 check_interval 5.000000 retry_interval 1.000000 max_check_attempts 2 active_checks_enabled 1 passive_checks_enabled 1 - obsess_over_host 1 + obsess 1 event_handler_enabled 1 low_flap_threshold 0.000000 high_flap_threshold 0.000000 flap_detection_enabled 1 - flap_detection_options o,d,u + flap_detection_options a freshness_threshold 0 check_freshness 0 - notification_options d,u,r,f,s + notification_options a notifications_enabled 1 notification_interval 60.000000 first_notification_delay 0.000000 stalking_options n process_perf_data 1 - failure_prediction_enabled 1 retain_status_information 1 retain_nonstatus_information 1 } @@ -193,6 +197,7 @@ define service { contacts nagiosadmin notification_period none initial_state o + hourly_value 1 check_interval 32.000000 retry_interval 1.000000 max_check_attempts 3 @@ -200,21 +205,20 @@ define service { parallelize_check 1 active_checks_enabled 1 passive_checks_enabled 1 - obsess_over_service 1 + obsess 1 event_handler_enabled 1 low_flap_threshold 0.000000 high_flap_threshold 0.000000 flap_detection_enabled 1 - flap_detection_options o,w,u,c + flap_detection_options a freshness_threshold 0 check_freshness 0 - notification_options u,w,c,r,f,s + notification_options a notifications_enabled 1 notification_interval 60.000000 first_notification_delay 0.000000 stalking_options n process_perf_data 1 - failure_prediction_enabled 1 retain_status_information 1 retain_nonstatus_information 1 } @@ -227,6 +231,7 @@ define service { contacts nagiosadmin notification_period none initial_state o + hourly_value 1 check_interval 15.000000 retry_interval 1.000000 max_check_attempts 5 @@ -234,21 +239,20 @@ define service { parallelize_check 1 active_checks_enabled 1 passive_checks_enabled 1 - obsess_over_service 1 + obsess 1 event_handler_enabled 1 low_flap_threshold 0.000000 high_flap_threshold 0.000000 flap_detection_enabled 1 - flap_detection_options o,w,u,c + flap_detection_options a freshness_threshold 0 check_freshness 0 - notification_options u,w,c,r,f,s + notification_options a notifications_enabled 1 notification_interval 65.000000 first_notification_delay 0.000000 stalking_options n process_perf_data 1 - failure_prediction_enabled 1 retain_status_information 1 retain_nonstatus_information 1 } @@ -261,6 +265,7 @@ define service { contacts nagiosadmin notification_period none initial_state o + hourly_value 1 check_interval 15.000000 retry_interval 1.000000 max_check_attempts 5 @@ -268,21 +273,20 @@ define service { parallelize_check 1 active_checks_enabled 1 passive_checks_enabled 1 - obsess_over_service 1 + obsess 1 event_handler_enabled 1 low_flap_threshold 0.000000 high_flap_threshold 0.000000 flap_detection_enabled 1 - flap_detection_options o,w,u,c + flap_detection_options a freshness_threshold 0 check_freshness 0 - notification_options u,w,c,r,f,s + notification_options a notifications_enabled 1 notification_interval 65.000000 first_notification_delay 0.000000 stalking_options n process_perf_data 1 - failure_prediction_enabled 1 retain_status_information 1 retain_nonstatus_information 1 } @@ -295,6 +299,7 @@ define service { contacts nagiosadmin notification_period none initial_state o + hourly_value 1 check_interval 15.000000 retry_interval 1.000000 max_check_attempts 5 @@ -302,21 +307,20 @@ define service { parallelize_check 1 active_checks_enabled 1 passive_checks_enabled 1 - obsess_over_service 1 + obsess 1 event_handler_enabled 1 low_flap_threshold 0.000000 high_flap_threshold 0.000000 flap_detection_enabled 1 - flap_detection_options o,w,u,c + flap_detection_options a freshness_threshold 0 check_freshness 0 - notification_options u,w,c,r,f,s + notification_options a notifications_enabled 1 notification_interval 65.000000 first_notification_delay 0.000000 stalking_options n process_perf_data 1 - failure_prediction_enabled 1 retain_status_information 1 retain_nonstatus_information 1 } @@ -329,6 +333,7 @@ define service { contacts nagiosadmin notification_period none initial_state o + hourly_value 1 check_interval 15.000000 retry_interval 1.000000 max_check_attempts 5 @@ -336,21 +341,20 @@ define service { parallelize_check 1 active_checks_enabled 1 passive_checks_enabled 1 - obsess_over_service 1 + obsess 1 event_handler_enabled 1 low_flap_threshold 0.000000 high_flap_threshold 0.000000 flap_detection_enabled 1 - flap_detection_options o,w,u,c + flap_detection_options a freshness_threshold 0 check_freshness 0 - notification_options u,w,c,r,f,s + notification_options a notifications_enabled 1 notification_interval 65.000000 first_notification_delay 0.000000 stalking_options n process_perf_data 1 - failure_prediction_enabled 1 retain_status_information 1 retain_nonstatus_information 1 } @@ -362,7 +366,6 @@ define servicedependency { dependent_service_description dependent-service inherits_parent 0 notification_failure_options u,c - execution_failure_options n } define serviceescalation { @@ -372,7 +375,7 @@ define serviceescalation { last_notification -2 notification_interval 65.000000 escalation_period none - escalation_options w,u,c,r + escalation_options a contacts nagiosadmin } @@ -383,7 +386,7 @@ define serviceescalation { last_notification -2 notification_interval 65.000000 escalation_period none - escalation_options w,u,c,r + escalation_options a contacts nagiosadmin } @@ -394,7 +397,7 @@ define serviceescalation { last_notification -2 notification_interval 65.000000 escalation_period none - escalation_options w,u,c,r + escalation_options a contacts nagiosadmin } @@ -405,7 +408,7 @@ define serviceescalation { last_notification -2 notification_interval 65.000000 escalation_period none - escalation_options w,u,c,r + escalation_options a contacts nagiosadmin } diff --git a/t/var/status-hosturgencies.dat b/t/var/status-hosturgencies.dat index dead32c..a386d3a 100644 --- a/t/var/status-hosturgencies.dat +++ b/t/var/status-hosturgencies.dat @@ -20,7 +20,6 @@ programstatus { nagios_pid=48451 daemon_mode=0 program_start=1242341791 - last_command_check=0 last_log_rotation=0 enable_notifications=1 active_service_checks_enabled=1 @@ -33,7 +32,6 @@ programstatus { check_service_freshness=1 check_host_freshness=0 enable_flap_detection=1 - enable_failure_prediction=1 process_performance_data=0 global_host_event_handler= global_service_event_handler= @@ -42,9 +40,6 @@ programstatus { next_event_id=1 next_problem_id=0 next_notification_id=1 - total_external_command_buffer_slots=4096 - used_external_command_buffer_slots=0 - high_external_command_buffer_slots=0 active_scheduled_host_check_stats=0,0,0 active_ondemand_host_check_stats=0,0,0 passive_host_check_stats=0,0,0 @@ -106,7 +101,6 @@ hoststatus { passive_checks_enabled=1 event_handler_enabled=1 flap_detection_enabled=1 - failure_prediction_enabled=1 process_performance_data=1 obsess_over_host=1 last_update=1242341791 @@ -163,7 +157,6 @@ hoststatus { passive_checks_enabled=1 event_handler_enabled=1 flap_detection_enabled=1 - failure_prediction_enabled=1 process_performance_data=1 obsess_over_host=1 last_update=1242341791 @@ -220,7 +213,6 @@ hoststatus { passive_checks_enabled=1 event_handler_enabled=1 flap_detection_enabled=1 - failure_prediction_enabled=1 process_performance_data=1 obsess_over_host=1 last_update=1242341791 @@ -277,7 +269,6 @@ hoststatus { passive_checks_enabled=1 event_handler_enabled=1 flap_detection_enabled=1 - failure_prediction_enabled=1 process_performance_data=1 obsess_over_host=1 last_update=1242341791 @@ -336,7 +327,6 @@ servicestatus { problem_has_been_acknowledged=0 acknowledgement_type=0 flap_detection_enabled=1 - failure_prediction_enabled=1 process_performance_data=1 obsess_over_service=1 last_update=1242341791 @@ -395,7 +385,6 @@ servicestatus { problem_has_been_acknowledged=0 acknowledgement_type=0 flap_detection_enabled=1 - failure_prediction_enabled=1 process_performance_data=1 obsess_over_service=1 last_update=1242341791 @@ -454,7 +443,6 @@ servicestatus { problem_has_been_acknowledged=0 acknowledgement_type=0 flap_detection_enabled=1 - failure_prediction_enabled=1 process_performance_data=1 obsess_over_service=1 last_update=1242341791 @@ -513,7 +501,6 @@ servicestatus { problem_has_been_acknowledged=0 acknowledgement_type=0 flap_detection_enabled=1 - failure_prediction_enabled=1 process_performance_data=1 obsess_over_service=1 last_update=1242341791 diff --git a/t/var/status.dat b/t/var/status.dat index 56e37cd..9c79aeb 100644 --- a/t/var/status.dat +++ b/t/var/status.dat @@ -20,7 +20,6 @@ programstatus { nagios_pid=48451 daemon_mode=0 program_start=1242341791 - last_command_check=0 last_log_rotation=0 enable_notifications=1 active_service_checks_enabled=1 @@ -33,7 +32,6 @@ programstatus { check_service_freshness=1 check_host_freshness=0 enable_flap_detection=1 - enable_failure_prediction=1 process_performance_data=0 global_host_event_handler= global_service_event_handler= @@ -42,9 +40,6 @@ programstatus { next_event_id=1 next_problem_id=0 next_notification_id=1 - total_external_command_buffer_slots=4096 - used_external_command_buffer_slots=0 - high_external_command_buffer_slots=0 active_scheduled_host_check_stats=0,0,0 active_ondemand_host_check_stats=0,0,0 passive_host_check_stats=0,0,0 @@ -106,7 +101,6 @@ hoststatus { passive_checks_enabled=1 event_handler_enabled=1 flap_detection_enabled=1 - failure_prediction_enabled=1 process_performance_data=1 obsess_over_host=1 last_update=1242341791 @@ -163,7 +157,6 @@ hoststatus { passive_checks_enabled=1 event_handler_enabled=1 flap_detection_enabled=1 - failure_prediction_enabled=1 process_performance_data=1 obsess_over_host=1 last_update=1242341791 @@ -222,7 +215,6 @@ servicestatus { problem_has_been_acknowledged=0 acknowledgement_type=0 flap_detection_enabled=1 - failure_prediction_enabled=1 process_performance_data=1 obsess_over_service=1 last_update=1242341791 @@ -281,7 +273,6 @@ servicestatus { problem_has_been_acknowledged=0 acknowledgement_type=0 flap_detection_enabled=1 - failure_prediction_enabled=1 process_performance_data=1 obsess_over_service=1 last_update=1242341791 diff --git a/tap/aclocal.m4 b/tap/aclocal.m4 index c7c523e..4c54f04 100644 --- a/tap/aclocal.m4 +++ b/tap/aclocal.m4 @@ -1662,7 +1662,7 @@ AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl cygwin* | mingw*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. - # Worse, since 9x/ME are not pre-emptively multitasking, + # Worse, since 9x/ME are not preemptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by @@ -5425,7 +5425,7 @@ case `$NM -V 2>&1` in symcode='[[ABCDGIRSTW]]' ;; esac -# Try without a prefix undercore, then with it. +# Try without a prefix underscore, then with it. for ac_symprfx in "" "_"; do # Write the raw and C identifiers. diff --git a/tap/configure b/tap/configure index ab9c021..85c82a7 100755 --- a/tap/configure +++ b/tap/configure @@ -5409,7 +5409,7 @@ else cygwin* | mingw*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. - # Worse, since 9x/ME are not pre-emptively multitasking, + # Worse, since 9x/ME are not preemptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by @@ -5546,7 +5546,7 @@ case `$NM -V 2>&1` in symcode='[ABCDGIRSTW]' ;; esac -# Try without a prefix undercore, then with it. +# Try without a prefix underscore, then with it. for ac_symprfx in "" "_"; do # Write the raw and C identifiers. diff --git a/tap/depcomp b/tap/depcomp index 11e2d3b..b369e8b 100755 --- a/tap/depcomp +++ b/tap/depcomp @@ -45,7 +45,7 @@ Environment variables: object Object file output by `PROGRAMS ARGS'. DEPDIR directory where to store dependencies. depfile Dependency file to output. - tmpdepfile Temporary file to use when outputing dependencies. + tmpdepfile Temporary file to use when outputting dependencies. libtool Whether libtool is used (yes/no). Report bugs to . diff --git a/tap/ltmain.sh b/tap/ltmain.sh index c888819..8bfc361 100644 --- a/tap/ltmain.sh +++ b/tap/ltmain.sh @@ -5633,7 +5633,7 @@ relink_command=\"$relink_command\"" relink_command= # To insure that "foo" is sourced, and not "foo.exe", - # finese the cygwin/MSYS system by explicitly sourcing "foo." + # finesse the cygwin/MSYS system by explicitly sourcing "foo." # which disallows the automatic-append-.exe behavior. case $build in *cygwin* | *mingw*) wrapperdot=${wrapper}. ;; @@ -5671,7 +5671,7 @@ relink_command=\"$relink_command\"" relink_command= # To insure that "foo" is sourced, and not "foo.exe", - # finese the cygwin/MSYS system by explicitly sourcing "foo." + # finesse the cygwin/MSYS system by explicitly sourcing "foo." # which disallows the automatic-append-.exe behavior. case $build in *cygwin* | *mingw*) wrapperdot=${wrapper}. ;; diff --git a/tap/src/tap.h b/tap/src/tap.h index e64f9d5..ca6aab2 100644 --- a/tap/src/tap.h +++ b/tap/src/tap.h @@ -25,7 +25,7 @@ */ /* '## __VA_ARGS__' is a gcc'ism. C99 doesn't allow the token pasting - and requires the caller to add the final comma if they've ommitted + and requires the caller to add the final comma if they've omitted the optional arguments */ #ifdef __GNUC__ # define ok(e, test, ...) ((e) ? \ diff --git a/test/test-downtime.pl b/test/test-downtime.pl new file mode 100755 index 0000000..d8784f4 --- /dev/null +++ b/test/test-downtime.pl @@ -0,0 +1,1759 @@ +#!/usr/bin/perl -w + +# Script to test downtime in Nagios with and without restarts + +use English; +use Getopt::Long; +use Algorithm::Permute; + +my $testPaused = 0; + +my @SLEEPTICKS = ( "-", "\\", "|", "/", "-", "\\", "|", "/"); +my $USESLEEPTICKS = 0; + +my $maxStatusLevel = 3; + +sub statusString { + my $level = shift; + my $message = shift; + + return if( $level > $maxStatusLevel); + return sprintf( " %s %s", humanTime( time), $message); +} + +# Read the contents of a .dat file such as status.dat or retention.dat +sub readDatFile { + my $file = shift; + + # Read the entire file into a variable + my $oldrs = $RS; + $RS = undef; + open( FILE, "$file") || die "Unable to open $file for reading"; + my $contents = ; + close( FILE) || die "Unable to close $file"; + $RS = $oldrs; + + # Strip comment and blank lines + $contents =~ s/#.*\n//g; + $contents =~ s/^\s*\n//g; + $contents =~ s/\n\s*\n/\n/g; + + # Break into sections + my @sections = split( /}\n/, $contents); + + my %contents; + + # Parse each section + for( my $x = 0; $x < @sections; $x++) { + my @lines = split( /\n/, $sections[ $x]); + + # Get the section type + chomp $lines[ 0]; + $lines[ 0] =~ s/^\s*//g; + $lines[ 0] =~ s/\s+{\s*$//g; + + # Create a hash of the remaining lines + my $href = {}; + for( my $y = 1; $y < @lines; $y++) { + next if( $lines[ $y] =~ /^\s*$/); + chomp( $lines[ $y]); + $lines[ $y] =~ s/^\s*//; + $lines[ $y] =~ s/\s*$//; + die "Unknown format for line: " . $lines[ $y] unless( $lines[ $y] =~ /^([^=]+)=(.*)$/); + my( $key, $value) = ( $1, $2); + $href->{ $key} = $value; + } + + # Enter stuff into the contents hash + if( $lines[ 0] =~ /^(info|program|programstatus)$/) { + $contents{ $lines[ 0]} = $href; + } + elsif( $lines[ 0] =~ /^(contact|contactstatus|host|hoststatus|service|servicecomment|servicedowntime|servicestatus)$/) { + $contents{ $lines[ 0]} = [] unless( exists( $contents{ $lines[ 0]})); + push( @{ $contents{ $lines[ 0]}}, $href); + } + else { + die "Unanticipated section encountered: " . $lines[ 0]; + } + } + + return \%contents; +} + +# Read the contents of the objects.cache file +sub readObjectCache { + my $file = shift; + + # Read the entire file into a variable + my $oldrs = $RS; + $RS = undef; + open( FILE, "$file") || die "Unable to open $file for reading"; + my $contents = ; + close( FILE) || die "Unable to close $file"; + $RS = $oldrs; + + # Strip comment and blank lines + $contents =~ s/#.*\n//g; + $contents =~ s/^\s*\n//g; + $contents =~ s/\n\s*\n/\n/g; + + # Break into sections + my @sections = split( /}\n/, $contents); + + my %contents; + + # Parse each definition + for( my $x = 0; $x < @sections; $x++) { + my @lines = split( /\n/, $sections[ $x]); + + # Get the definition type + chomp $lines[ 0]; + my $definitionType = undef; + if( $lines[ 0] =~ /define\s+(\S+)\s*{/) { + $definitionType = $1; + } + die "Unknown definition line: " . $lines[ 0] if( !defined( $definitionType)); + + # Create a hash of the remaining lines + my $href = {}; + for( my $y = 1; $y < @lines; $y++) { + chomp( $lines[ $y]); + next if( $lines[ $y] =~ /^\s*$/); + die "Unknown format for line: " . $lines[ $y] unless( $lines[ $y] =~ /^\s*(\S+)\s+(.*)\s*$/); + my( $key, $value) = ( $1, $2); + $href->{ $key} = $value; + } + + # Enter stuff into the contents hash + $contents{ $definitionType} = [] unless( exists( $contents{ $definitionType})); + push( @{ $contents{ $definitionType}}, $href); + } + + return \%contents; +} + +# Read the contents of the nagios.cfg file. +# NOTE: This function does not recursively read the contents of configuration +# files specified in the cfg_file and cfg_dir directives. +sub readCfgFile { + my $file = shift; + + my %cfg; + + open( FILE, "$file") || die "Unable to open $file for reading"; + while( ) { + chomp; + next if( /^\s*#/); + next if( /^\s*$/); + if( /^([^=]+)\s*=\s*(.*)$/) { + my( $key, $value) = ( $1, $2); + if( $key =~ /cfg_file|cfg_dir/) { + $cfg{ $key} = [] unless( exists( $cfg{ $key})); + push( @{ $cfg{ $key}}, $value); + } + else { + die "Parameter $key already exists" if( exists( $cfg{ $key})); + $cfg{ $key} = $value; + } + } + else { + die "Unknown formatting for line: $_"; + } + } + + return \%cfg; +} + +# Send a command to Nagios to schedule downtime +sub scheduleDowntime { + my $service = shift; + my $start = shift; + my $end = shift; + my $fixed = shift; + my $duration = shift; + my $comment = shift; + + my $cmd = sprintf( "%s;%s;%s;%lu;%lu;%d;%u;%u;%s;%s", + "SCHEDULE_SVC_DOWNTIME", $service->{ "host_name"}, + $service->{ "service_description"}, $start, $end, $fixed, + 0, $duration, "Downtime Testing", $comment); + + my $cmdfile = "/usr/local/nagios/var/rw/nagios.cmd"; + open( CMD, ">$cmdfile") || die "Cannot open $cmdfile for writing"; + print CMD sprintf( "[%lu] %s\n", time, $cmd); + close( CMD) || die "Unable to close $cmdfile"; + sleep 1; +} + +# Send a command to Nagios to delete downtime +sub deleteDowntime { + my $id = shift; + my $cfg = shift; + my $service = shift; + + # There is a bug in Nagios that currently causes Nagios to crash when + # deleting a downtime. Instead of deleting the downtime, we'll just + # have to wait until it ends. + my $datfile = readDatFile( $cfg->{ "status_file"}); + my $downtimes = findServiceDowntimes( $datfile, $service); + while( scalar( @$downtimes) > 0) { + sleep 1; + $datfile = readDatFile( $cfg->{ "status_file"}); + $downtimes = findServiceDowntimes( $datfile, $service); + } + return; + + my $cmd = sprintf( "%s;%u", "DEL_SVC_DOWNTIME", $id); + my $cmdfile = "/usr/local/nagios/var/rw/nagios.cmd"; + open( CMD, ">$cmdfile") || die "Cannot open $cmdfile for writing"; + print CMD sprintf( "[%lu] %s\n", time, $cmd); + close( CMD) || die "Unable to close $cmdfile"; +} + +# Send a command to Nagios to process passive service check results +sub sendPassiveResults { + my $service = shift; + my $returnCode = shift; + my $pluginOutput = shift; + + my $cmd = sprintf( "%s;%s;%s;%u;%s", "PROCESS_SERVICE_CHECK_RESULT", + $service->{ "host_name"}, $service->{ "service_description"}, + $returnCode, $pluginOutput); + + my $cmdfile = "/usr/local/nagios/var/rw/nagios.cmd"; + open( CMD, ">$cmdfile") || die "Cannot open $cmdfile for writing"; + print CMD sprintf( "[%lu] %s\n", time, $cmd); + close( CMD) || die "Unable to close $cmdfile"; +} + +# Determine the amount of time to discover a service failure above +# the normal check results reaper frequency +sub maxDiscoveryTime { + my $cfg = shift; + my $service = shift; + my $versionMajor = shift; + + my $maxDiscoveryTime = 0; + if( $service->{ "active_checks_enabled"}) { + $maxDiscoveryTime += ( $service->{ "check_interval"} * + $cfg->{ "interval_length"}); + $maxDiscoveryTime += ((( $service->{ "retry_interval"} + + ( $versionMajor < 4 ? + $cfg->{ "check_result_reaper_frequency"} : 0)) * + $cfg->{ "interval_length"}) * + ( $service->{ "max_check_attempts"} - 1)); + } + return $maxDiscoveryTime; +} + +# Return information about a particular service recorded in a .dat file +sub findServiceStatus { + my $datfile = shift; + my $service = shift; + + my $found; + + if( exists( $datfile->{ "servicestatus"})) { + for( my $x = 0; $x < @{ $datfile->{ "servicestatus"}}; $x++) { + if(( $datfile->{ "servicestatus"}->[ $x]->{ "host_name"} eq + $service->{ "host_name"}) && + ( $datfile->{ "servicestatus"}->[ $x]->{ "service_description"} eq + $service->{ "service_description"})) { + return $datfile->{ "servicestatus"}->[ $x]; + } + } + } + + return \$found; +} + +sub findServiceNextCheck { + my $cfg = shift; + my $service = shift; + + my $datfile = readDatFile( $cfg->{ "status_file"}); + my $serviceStatus = findServiceStatus( $datfile, $service); + return $serviceStatus->{ "next_check"}; +} + +# Return information about downtimes for a particular service recorded in a +# .dat file +sub findServiceDowntimes { + my $datfile = shift; + my $service = shift; + + my @found; + + if( exists( $datfile->{ "servicedowntime"})) { + for( my $x = 0; $x < @{ $datfile->{ "servicedowntime"}}; $x++) { + if(( $datfile->{ "servicedowntime"}->[ $x]->{ "host_name"} eq + $service->{ "host_name"}) && + ( $datfile->{ "servicedowntime"}->[ $x]->{ "service_description"} eq + $service->{ "service_description"})) { + push( @found, $datfile->{ "servicedowntime"}->[ $x]); + } + } + } + + return \@found; +} + +# Fine a particular service in a config (.cfg) file or the objects cache. +sub findService { + my $cfgfile = shift; + my $host = shift; + my $service = shift; + + if( exists( $cfgfile->{ "service"})) { + for( my $x = 0; $x < @{ $cfgfile->{ "service"}}; $x++) { + if(( $cfgfile->{ "service"}->[ $x]->{ "host_name"} eq $host) && + ( $cfgfile->{ "service"}->[ $x]->{ "service_description"} eq $service)) { + return $cfgfile->{ "service"}->[ $x]; + } + } + } + + return undef; +} + +# Sleep for a given amount of time displaying a message while sleeping +sub noisySleep { + my $length = shift; + my $message = shift; + + print $message; + print " " if( $USESLEEPTICKS); + for( my $x = 0; $x < $length; $x++) { + if( $USESLEEPTICKS) { + printf( "\b%s", $SLEEPTICKS[ $x % scalar( @SLEEPTICKS)]); + } + else { + print "."; + } + sleep 1; + } + print "\b " if( $USESLEEPTICKS); + print "\n"; +} + +# Sleep until a given time displaying a message while sleeping +sub noisySleepUntilTime { + my $time = shift; + my $message = shift; + + print $message; + print " " if( $USESLEEPTICKS); + while( time < $time) { + if( $USESLEEPTICKS) { + printf( "\b%s", $SLEEPTICKS[ time % scalar( @SLEEPTICKS)]); + } + else { + print "."; + } + sleep 1; + } + print "\b " if( $USESLEEPTICKS); + print "\n"; +} + +# Sleep until a specified file is updated, displaying a message while sleeping +sub noisySleepUntilFileUpdate { + my $file = shift; # File whose mtime should be watched + my $after = shift; # Time after which file must be updated + my $maxtime = shift; # Maximum number of seconds after $after to wait + my $message = shift; # Message to display + + print $message; + print " " if( $USESLEEPTICKS); + while(( ! -f $file) && ( time < ( $after + $maxtime))) { + if( $USESLEEPTICKS) { + printf( "\b%s", $SLEEPTICKS[ time % scalar( @SLEEPTICKS)]); + } + else { + print "."; + } + sleep 1; + } + my ( $dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size, $atime, $mtime, + $ctime, $blksize, $blocks) = stat( $file); + while(( $mtime <= $after) && ( time < ( $after + $maxtime))) { + if( $USESLEEPTICKS) { + printf( "\b%s", $SLEEPTICKS[ time % scalar( @SLEEPTICKS)]); + } + else { + print "."; + } + sleep 1; + ( $dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size, $atime, $mtime, + $ctime, $blksize, $blocks) = stat( $file); + } + print "\b " if( $USESLEEPTICKS); + print "\n"; + + if( time >= ( $after + $maxtime)) { + die "Maximum time exceeded waiting for $file to update\n"; + } +} + +# Verify that a downtime is recorded correctly in a .dat file +sub verifyDowntime { + my $service = shift; + my $cfg = shift; + my $downtimeFixed = shift; + my $downtimeStart = shift; + my $downtimeEnd = shift; + my $downtimeDuration = shift; + + # Grab the status data + print statusString( 2, "Reading status data.\n"); + my $datfile = readDatFile( $cfg->{ "status_file"}); + + # Find the downtimes + print statusString( 2, "Looking for downtimes.\n"); + my $downtimes = findServiceDowntimes( $datfile, $service); + + # Check to see if we found the correct number of downtimes (1) + print statusString( 2, "Verifying the downtime.\n"); + if( scalar( @$downtimes) != 1) { + print STDERR "Incorrect number of downtimes found: " . + scalar( @downtimes) . ".\n"; + return 0; + } + + # Verify that the aspects of the downtime match + if( $downtimes->[ 0]->{ "fixed"} != $downtimeFixed) { + print STDERR sprintf( "Downtime type incorrect: should be %s, is %s.\n", + ( $downtimes->[ 0]->{ "fixed"} ? "Fixed" : "Flexible"), + ( $downtimeFixed ? "Fixed" : "Flexible")); + return 0; + } + if( $downtimes->[ 0]->{ "start_time"} != $downtimeStart) { + print STDERR sprintf( "Downtime start time incorrect: should be %lu, is %lu.\n", + $downtimes->[ 0]->{ "start_time"}, $downtimeStart); + return 0; + } + if( $downtimes->[ 0]->{ "end_time"} != $downtimeEnd) { + print STDERR sprintf( "Downtime end time incorrect: should be %lu, is %lu.\n", + $downtimes->[ 0]->{ "end_time"}, $downtimeEnd); + return 0; + } + if( ! $downtimeFixed && ( $downtimes->[ 0]->{ "duration"} != + $downtimeDuration)) { + print STDERR sprintf( "Downtime duration incorrect: should be %lu, is %lu.\n", + $downtimes->[ 0]->{ "duration"}, $downtimeDuration); + return 0; + } + return 1; +} + +sub recoverService { + my $service = shift; + my $cfg = shift; + my $message = shift; + my $nagiosRunning = shift; + my $versionMajor = shift; + + print statusString( 1, sprintf( "%s\n", $message)); + if( $service->{ "active_checks_enabled"}) { + if(( $service->{ "host_name"} eq "localhost") && + ( $service->{ "service_description"} eq "HTTP")) { + system( "/sbin/service httpd start"); + } + elsif(( $service->{ "host_name"} eq "localhost") && + ( $service->{ "service_description"} eq "SSH")) { + system( "/sbin/service sshd start"); + } + else { + die sprintf( "Don't know how to start service %s:%s", + $service->{ "host_name"}, + $service->{ "service_description"}); + } + } + else { + die "Nagios is not running" unless( $nagiosRunning); + sendPassiveResults( $service, 0, "OK - Everything Okey Dokey"); + } + + # If Nagios is running, sleep so an undetected recovery doesn't + # interfere with future operations + if( $nagiosRunning) { + if( $service->{ "active_checks_enabled"}) { + my $nextCheck = findServiceNextCheck( $cfg, $service); + noisySleepUntilTime( $nextCheck, statusString( 2, + sprintf( "Waiting for next check to run at %s", + humanTime( $nextCheck)))); + } + if( $versionMajor < 4) { + noisySleep( $cfg->{ "check_result_reaper_frequency"} + 2, + statusString( 2, "Waiting for check results reaper to run")); + } + noisySleepUntilFileUpdate( $cfg->{ "status_file"}, time, + $cfg->{ "status_update_interval"} * + $cfg->{ "StatusUpdateIntervalMultiplier"}, + statusString( 2, "Waiting for status to update")); + } + + return 1; +} + +sub failService { + my $service = shift; + my $cfg = shift; + my $schedule = shift; + my $downtimeStart = shift; + my $nagiosRunning = shift; + my $versionMajor = shift; + + # downtimeEndCheckIncrement is how much time we're going to add before the + # DowntimeEndCheck event due to a service check being delayed after the + # service fail command is sent. + my $downtimeEndCheckIncrement = 0; + + print statusString( 1, "Sending service failure.\n"); + if( $service->{ "active_checks_enabled"}) { + if(( $service->{ "host_name"} eq "localhost") && + ( $service->{ "service_description"} eq "HTTP")) { + system( "/sbin/service httpd stop"); + } + elsif(( $service->{ "host_name"} eq "localhost") && + ( $service->{ "service_description"} eq "SSH")) { + system( "/sbin/service sshd stop"); + } + else { + die sprintf( "Don't know how to stop service %s:%s", + $service->{ "host_name"}, + $service->{ "service_description"}); + } + } + else { + die "Nagios is not running" unless( $nagiosRunning); + sendPassiveResults( $service, 2, "CRITICAL - Danger Will Robinson"); + } + if( $nagiosRunning) { + if( $service->{ "active_checks_enabled"}) { + my $nextCheck = findServiceNextCheck( $cfg, $service); + $downtimeEndCheckIncrement = $nextCheck - time - + maxDiscoveryTime( $cfg, $service, $versionMajor); + $downtimeEndCheckIncrement = 0 if( $downtimeEndCheckIncrement < 0); + noisySleepUntilTime( $nextCheck, statusString( 2, + sprintf( "Waiting for next check to run at %s", + humanTime( $nextCheck)))); + } + if( $versionMajor < 4) { + noisySleep( $cfg->{ "check_result_reaper_frequency"} + 2, + statusString( 2, "Waiting for check results reaper to run")); + } + noisySleepUntilFileUpdate( $cfg->{ "status_file"}, time, + $cfg->{ "status_update_interval"} * + $cfg->{ "StatusUpdateIntervalMultiplier"}, + statusString( 2, "Waiting for status to update")); + + if( time < $downtimeStart + $schedule->{ "DowntimeEnd"}) { + # We have not passed the end of the downtime waiting for + # a check that would trigger a downtime + print statusString( 2, + "Verifying that flexible downtime is in effect.\n"); + my $datfile = readDatFile( $cfg->{ "status_file"}); + my $downtimes = findServiceDowntimes( $datfile, $service); + if( scalar( @$downtimes) != 1) { + print STDERR "Incorrect number of downtimes found: " . + scalar( @$downtimes) . "\n"; + return ( -1, undef); + } + if( ! $downtimes->[ 0]->{ "is_in_effect"}) { + print STDERR "Downtime is not in effect\n"; + return ( -1, undef); + } + print statusString( 2, + sprintf( "The flexible downtime was triggered at %s.\n", + humanTime( $downtimes->[ 0]->{ "flex_downtime_start"}))); + return ( $downtimeEndCheckIncrement, $downtimes->[ 0]); + } + else { + return ( $downtimeEndCheckIncrement, undef); + } + } + else { + return ( 0, undef); + } +} + +sub checkStateAfterNagiosRestart { + my $cfg = shift; + my $service = shift; + my $schedule = shift; + my $downtimeStart = shift; + my $downtimeFixed = shift; + my $downtimeAfterServiceFail = shift; + my $downtimesAtNagiosStop = shift; + + # If a flexible downtime was triggered and completed before the + # Nagios restart, we have nothing to do. + my $durationEndBeforeNagiosStop = ( ! $downtimeFixed && + ( $schedule->{ "ServiceFail"} > 0) && + ( $schedule->{ "NagiosStop"} > 0) && + ( ref( $downtimeAfterServiceFail) eq "HASH") && + ( $downtimeAfterServiceFail->{ "flex_downtime_start"} > 0) && + ( $downtimeAfterServiceFail->{ "flex_downtime_start"} + + $schedule->{ "DowntimeDuration"} < $schedule->{ "NagiosStart"} + + $downtimeStart)); + print statusString( 3, + sprintf( "Downtime duration %s before Nagios was restarted\n", + ( $durationEndBeforeNagiosStop ? "ended" : "did not end"))); + return 0 if ( $durationEndBeforeNagiosStop); + + # If the service failed AND recovered while Nagios was down, a flexible + # downtime would never be trigged. + my $serviceCycleWhileNagiosDown = ( ! $downtimeFixed && + ( $schedule->{ "ServiceFail"} > 0) && + ( $schedule->{ "NagiosStop"} > 0) && + ( $schedule->{ "NagiosStop"} < $schedule->{ "ServiceFail"}) && + ( $schedule->{ "ServiceRecover"} < $schedule->{ "NagiosStart"})); + print statusString( 3, sprintf( "Service %s while Nagios was down\n", + ( $serviceCycleWhileNagiosDown ? "cycled" : "did not cycle"))); + return 0 if( $serviceCycleWhileNagiosDown); + + # downtimeEndCheckIncrement is how much time we're going to add before the + # DowntimeEndCheck event due to the downtime not being triggered until + # after a Nagios restart, if that even happens + my $downtimeEndCheckIncrement = 0; + + # Determine whether the Nagios restart occurred after the end of the + # downtime. + my $nagiosRestartAfterDowntimeEnd = ( $schedule->{ "NagiosStart"} > + $schedule->{ "DowntimeEnd"}); + + # Use the above information and the schedule to determine whether a + # flexible downtime should have been triggered or should yet be triggered. + my $downtimeTriggeredBeforeNagiosStop = 0; + my $downtimeTriggeredAfterNagiosStart = 0; + if( ! $downtimeFixed) { + if(( $schedule->{ "ServiceFail"} > 0) && + ( $schedule->{ "ServiceFail"} < $schedule->{ "NagiosStop"})) { + $downtimeTriggeredBeforeNagiosStop = 1; + print statusString( 3, "Downtime should have been triggered " . + "before Nagios stopped\n"); + } + else { + print statusString( 3, "Downtime would not have been triggered " . + "before Nagios stopped\n"); + } + if( ! $nagiosRestartAfterDowntimeEnd && + ( $schedule->{ "ServiceFail"} > 0 ) && + ( $schedule->{ "NagiosStop"} < $schedule->{ "ServiceFail"}) && + ( $schedule->{ "ServiceFail"} < $schedule->{ "NagiosStart"})) { + $downtimeTriggeredAfterNagiosStart = 1; + print statusString( 3, "Downtime should be triggered after " . + "Nagios start\n"); + } + else { + print statusString( 3, "Downtime would not be triggered after " . + "Nagios start\n"); + } + } + + + # If the downtime should have been triggered, but was not detected prior + # to the Nagios stop, wait for it to be detected. + if( $downtimeTriggeredAfterNagiosStart) { + if( $service->{ "active_checks_enabled"}) { + my $nextCheck = findServiceNextCheck( $cfg, $service); + $downtimeEndCheckIncrement = ( $nextCheck - time) + + ( $schedule->{ "NagiosStart"} - + $schedule->{ "ServiceFail"}); + noisySleepUntilTime( $nextCheck, statusString( 1, + sprintf( "Waiting for next check to run at %s", + humanTime( $nextCheck)))); + } + if( time > $downtimeStart + $schedule->{ "DowntimeEnd"}) { + # We passed the end of the downtime waiting for a check that + # would trigger a downtime + print statusString( 2, + "Downtime ended while waiting for next check.\n"); + return 0; + } + } + + # Next determine whether the downtime should still exist + my $downtimeShouldExist = 0; + if( $downtimeFixed) { + if( time < $downtimeStart + $schedule->{ "DowntimeEnd"}) { + # If the downtime is fixed and we have not reached the + # downtime end, it should still exists so check it below + $downtimeShouldExist = 1; + } + } + else { + if( ! $downtimeTriggeredBeforeNagiosStop && + ! $downtimeTriggeredAfterNagiosStart) { + if( time < $downtimeStart + $schedule->{ "DowntimeEnd"}) { + # If the downtime is flexible, it was never triggered + # and we have not reached the downtime end, it should + # still exist so check it below + print statusString( 2, "We have not reached the downtime " . + "end, so it should still exist.\n"); + $downtimeShouldExist = 1; + } + } + else { + # In this case the downtime is flexible and should have been + # triggered. + print statusString( 3, + sprintf( "There were %d downtime(s) when Nagios stopped.\n", + scalar( @$downtimesAtNagiosStop))); + if( scalar( @$downtimesAtNagiosStop) == 1) { + print statusString( 3, + sprintf( "The flex downtime start for the downtime " . + "existing when\nNagios stopped was %s\n", + humanTime( $downtimesAtNagiosStop->[ 0]->{ "flex_downtime_start"}))); + } + if(( scalar( @$downtimesAtNagiosStop) == 1) && + ( $downtimesAtNagiosStop->[ 0]->{ "flex_downtime_start"} > 0)) { + print statusString( 2, + "The downtime was triggered before Nagios stopped.\n"); + if( time < + ( $downtimesAtNagiosStop->[ 0]->{ "flex_downtime_start"} + + $downtimesAtNagiosStop->[ 0]->{ "duration"})) { + # If the trigger was detected before Nagios was stopped and + # we are still in the flexible downtime, it should exist + print statusString( 2, "We have not reached the duration " . + "end; it should still exist.\n"); + $downtimeShouldExist = 1; + } + else { + print statusString( 2, "We have reached the duration " . + "end; it should not exist.\n"); + } + } + elsif( time < ( $downtimeStart + $schedule->{ "NagiosStart"} + + $schedule->{ "DowntimeDuration"})) { + # If the downtime was not triggered until after Nagios restarted + # and we have not reached the duration end, it should still + # exist so check it below + print statusString( 2, "We have not reached the duration " . + "end; it should still exist.\n"); + $downtimeShouldExist = 1; + } + } + } + + + # If the downtime should exist, verify the downtime is back. If it should + # not exist, verification that the downtime is gone happens at the + # DowntimeEndCheck event. + if( $downtimeShouldExist) { + print statusString( 1, "Verifying downtime after Nagios restart.\n"); + if( !verifyDowntime( $service, $cfg, $downtimeFixed, + $downtimeStart, + $downtimeStart + ( $schedule->{ "DowntimeEnd"} - + $schedule->{ "DowntimeStart"}), + $schedule->{ "DowntimeDuration"})) { + return -1; + } + } + else { + print statusString( 1, + "The downtime should have ended; it will be checked later.\n"); + } + + return $downtimeEndCheckIncrement; +} + +# Perform the check of a downtime sequence +sub checkDowntime { + my $testComment = shift; + my $service = shift; + my $cfg = shift; + my $downtimeFixed = shift; + my $schedule = shift; + my $versionMajor = shift; + + my $startTime = time; + my $datfile; + my $nagiosRunning = 1; + my $downtimesAtNagiosStop; + my $downtimeAfterServiceFail; + my $downtimeEndCheckIncrement = 0; + + print "$testComment\n"; + + # Verify parameters + die "No downtime start specified" unless( exists( $schedule->{ "DowntimeStart"})); + die "No downtime end specified" unless( $schedule->{ "DowntimeEnd"} >= 0); + die "No downtime duration specified" unless( $downtimeFixed || + $schedule->{ "DowntimeDuration"} >= 0); + + # Determine the amount of time to discover a service failure above + # the normal check results reaper frequency + my $maxDiscoveryTime = maxDiscoveryTime( $cfg, $service, $versionMajor); + + # Create an events list + my @events; + my $eventTime; + + # Figure out the time for the check at the end of the downtime + if( ! $downtimeFixed && $schedule->{ "ServiceFail"} > 0) { + if( $schedule->{ "NagiosStart"} > $schedule->{ "ServiceFail"} + + $schedule->{ "DowntimeDuration"} + $maxDiscoveryTime) { + $eventTime = $schedule->{ "NagiosStart"} + 1; + } + else { + $eventTime = $schedule->{ "ServiceFail"} + + $schedule->{ "DowntimeDuration"}; + if( $service->{ "active_checks_enabled"}) { + $eventTime += $maxDiscoveryTime; + } + } + } + else { + if( $schedule->{ "NagiosStart"} > ( $schedule->{ "DowntimeEnd"} - + $schedule->{ "DowntimeStart"})) { + $eventTime = $schedule->{ "NagiosStart"} + 1; + } + else { + $eventTime = ( $schedule->{ "DowntimeEnd"} - + $schedule->{ "DowntimeStart"}); + } + } + push( @events, { "time" => $eventTime + $cfg->{ "status_update_interval"}, + "type" => "DowntimeEndCheck"}); + + # Add the Nagios stop and start events if they're in the permutation + if( $schedule->{ "NagiosStop"} > 0) { + push( @events, { "time" => $schedule->{ "NagiosStop"}, + "type" => "NagiosStop"}); + if( $schedule->{ "NagiosStart"} > 0) { + push( @events, { "time" => $schedule->{ "NagiosStart"}, + "type" => "NagiosStart"}); + } + else { + die "No Nagios restart time specified"; + } + } + + # Add the service failure and recover events if they're in the permutation + if( $schedule->{ "ServiceFail"} > 0) { + push( @events, { "time" => $schedule->{ "ServiceFail"}, + "type" => "ServiceFail"}); + if( $schedule->{ "ServiceRecover"} > 0) { + push( @events, { "time" => $schedule->{ "ServiceRecover"}, + "type" => "ServiceRecover"}); + } + else { + die "No service recovery time specified"; + } + } + + # Sort the events in chronological order + my @sortedEvents = sort { $a->{ "time"} <=> $b->{ "time"}} @events; + + # Make sure the service starts in a good state + if( ! recoverService( $service, $cfg, + "Making sure the service is in a good state.", $nagiosRunning, + $versionMajor)) { + return -1; + } + + # Cancel all current downtimes + print statusString( 1, "Deleting current downtimes: "); + $datfile = readDatFile( $cfg->{ "status_file"}); + $downtimes = findServiceDowntimes( $datfile, $service); + for( my $x = 0; $x < @$downtimes; $x++) { + print ", " if( $x > 0); + print $downtimes->[ $x]->{ "downtime_id"}; + deleteDowntime( $downtimes->[ $x]->{ "downtime_id"}, $cfg, $service); + } + print "\n"; + + # Schedule the downtime + my $downtimeStart = time + $schedule->{ "DowntimeStart"}; + if( $downtimeFixed) { + print statusString( 1, + sprintf( "Scheduling fixed downtime\n\t\tfrom %s to %s.\n", + humanTime( $downtimeStart), + humanTime( $downtimeStart + ( $schedule->{ "DowntimeEnd"} - + $schedule->{ "DowntimeStart"})))); + } + else { + print statusString( 1, sprintf( "Scheduling flexible downtime of " . + "%d seconds\n\t\tfrom %s to %s.\n", + $schedule->{ "DowntimeDuration"}, humanTime( $downtimeStart), + humanTime( $downtimeStart + ( $schedule->{ "DowntimeEnd"} - + $schedule->{ "DowntimeStart"})))); + } + scheduleDowntime( $service, $downtimeStart, + $downtimeStart + ( $schedule->{ "DowntimeEnd"} - + $schedule->{ "DowntimeStart"}), $downtimeFixed, + $schedule->{ "DowntimeDuration"}, $testComment); + + # Wait for the status file to update + noisySleepUntilFileUpdate( $cfg->{ "status_file"}, time, + $cfg->{ "status_update_interval"} * + $cfg->{ "StatusUpdateIntervalMultiplier"}, + statusString( 2, "Waiting for status to update")); + + # Verify the downtime + if( !verifyDowntime( $service, $cfg, $downtimeFixed, $downtimeStart, + $downtimeStart + ( $schedule->{ "DowntimeEnd"} - + $schedule->{ "DowntimeStart"}), + $schedule->{ "DowntimeDuration"})) { + return -1; + } + + # Enter the event loop + my $eventIndex = 0; + while( $eventIndex < @sortedEvents) { + + # Sleep until the next event is to to be executed + if( time < ( $downtimeStart + $sortedEvents[ $eventIndex]->{ "time"})) { + my $message = statusString( 1, + sprintf( "Waiting for %s event at %s", + $sortedEvents[ $eventIndex]->{ "type"}, + humanTime( $downtimeStart + + $sortedEvents[ $eventIndex]->{ "time"}))); + noisySleepUntilTime(( $downtimeStart + + $sortedEvents[ $eventIndex]->{ "time"}), $message); + } + + # Verify the downtime is gone at the end of the check + if( $sortedEvents[ $eventIndex]->{ "type"} eq "DowntimeEndCheck") { + noisySleepUntilFileUpdate( $cfg->{ "status_file"}, time, + $cfg->{ "status_update_interval"} * + $cfg->{ "StatusUpdateIntervalMultiplier"}, + statusString( 2, "Waiting for status to update")); + # Grab the status data again + print statusString( 2, "Rereading status data.\n"); + $datfile = readDatFile( $cfg->{ "status_file"}); + + # Find the downtimes + print statusString( 2, "Looking for downtimes again.\n"); + $downtimes = findServiceDowntimes( $datfile, $service); + print statusString( 1, "Verifying the downtime has ended.\n"); + if( scalar( @$downtimes) > 0) { + for( my $y = 0; $y < @$downtimes; $y++) { + if( $downtimes->[ $y]->{ "is_in_effect"}) { + print STDERR "Downtime still exists.\n"; + return -1; + } + } + } + } + + # Restart Nagios + elsif( $sortedEvents[ $eventIndex]->{ "type"} eq "NagiosStart") { + print statusString( 1, "Starting Nagios.\n"); + system( "/sbin/service nagios start"); + system( "/bin/chgrp nagcmd /usr/local/nagios/var/rw/nagios.cmd"); + + # Wait for the status file to update + noisySleepUntilFileUpdate( $cfg->{ "status_file"}, time, + $cfg->{ "status_update_interval"} * + $cfg->{ "StatusUpdateIntervalMultiplier"}, + statusString( 2, "Waiting for status to update")); + + # Check the status of things after the Nagios restart + $downtimeEndCheckIncrement = checkStateAfterNagiosRestart( $cfg, + $service, $schedule, $downtimeStart, $downtimeFixed, + $downtimeAfterServiceFail, $downtimesAtNagiosStop); + if( $downtimeEndCheckIncrement < 0) { + return -1; + } + elsif( $downtimeEndCheckIncrement > 0) { + print statusString( 3, + sprintf( "Extending the DowntimeEndCheck time by %d " . + "seconds\n", $downtimeEndCheckIncrement)); + $sortedEvents[ @sortedEvents - 1]->{ "time"} += + $downtimeEndCheckIncrement; + } + $nagiosRunning = 1; + } + + # Stop Nagios + elsif( $sortedEvents[ $eventIndex]->{ "type"} eq "NagiosStop") { + $datfile = readDatFile( $cfg->{ "status_file"}); + $downtimesAtNagiosStop = findServiceDowntimes( $datfile, $service); + print statusString( 3, sprintf( + "There are %d downtime(s) just before stopping Nagios.\n", + scalar( @$downtimesAtNagiosStop))); + print statusString( 1, "Stopping Nagios.\n"); + system( "/sbin/service nagios stop"); + $nagiosRunning = 0; + } + + # Cause the service to fail + elsif( $sortedEvents[ $eventIndex]->{ "type"} eq "ServiceFail") { + ( $downtimeEndCheckIncrement, $downtimeAfterServiceFail) = + failService( $service, $cfg, $schedule, $downtimeStart, + $nagiosRunning, $versionMajor); + if( $downtimeEndCheckIncrement < 0) { + return -1; + } + elsif( $downtimeEndCheckIncrement > 0) { + print statusString( 3, + sprintf( "Extending the DowntimeEndCheck time by %d " . + "seconds\n", $downtimeEndCheckIncrement)); + $sortedEvents[ @sortedEvents - 1]->{ "time"} += + $downtimeEndCheckIncrement; + } + } + + # Cause the service to recover + elsif( $sortedEvents[ $eventIndex]->{ "type"} eq "ServiceRecover") { + if( !recoverService( $service, $cfg, "Sending service recovery.", + $nagiosRunning, $versionMajor)) { + return -1; + } + } + + # Something is dreadfully wrong + else { + die "Unhandled event type: " . $sortedEvents[ $eventIndex]->{ "type"}; + } + $eventIndex++; + } + + return( time - $startTime); +} + +# Determine whether a event permutation is valid +sub isValidEventPermutation { + my $permutation = shift; + my $activeChecks = shift; + + # Create a hash of the events with the event name as the key and the order + # as the value. + my %permutation; + for( my $x = 0; $x < @$permutation; $x++) { + $permutation{ $permutation->[ $x]} = $x; + } + + # The downtime cannot be created after it ends + if( exists( $permutation{ "DowntimeEnd"}) && + exists( $permutation{ "EntryTime"}) && + ( $permutation{ "DowntimeEnd"} < $permutation{ "EntryTime"})) { + return 0; + } + + # The downtime cannot end before it starts + if( exists( $permutation{ "DowntimeEnd"}) && + exists( $permutation{ "DowntimeStart"}) && + ( $permutation{ "DowntimeEnd"} < $permutation{ "DowntimeStart"})) { + return 0; + } + + # The service cannot recover before it fails + if( exists( $permutation{ "ServiceFail"}) && + exists( $permutation{ "ServiceRecover"}) && + ( $permutation{ "ServiceRecover"} < $permutation{ "ServiceFail"})) { + return 0; + } + + # Nagios cannot be restarted before it is initially stopped + if( exists( $permutation{ "NagiosStop"}) && + exists( $permutation{ "NagiosStart"}) && + ( $permutation{ "NagiosStart"} < $permutation{ "NagiosStop"})) { + return 0; + } + + # It doesn't make sense to test when a service failure occurs after the + # end of the downtime + if( exists( $permutation{ "ServiceFail"}) && + exists( $permutation{ "DowntimeEnd"}) && + ( $permutation{ "ServiceFail"} > $permutation{ "DowntimeEnd"})) { + return 0; + } + + # It doesn't make sense to test when a service failure occurs before the + # downtime is created + if( exists( $permutation{ "ServiceFail"}) && + exists( $permutation{ "EntryTime"}) && + ( $permutation{ "ServiceFail"} < $permutation{ "EntryTime"})) { + return 0; + } + + # It doesn't make sense to test when a service failure occurs before the + # downtime starts + if( exists( $permutation{ "ServiceFail"}) && + exists( $permutation{ "DowntimeStart"}) && + ( $permutation{ "ServiceFail"} < $permutation{ "DowntimeStart"})) { + return 0; + } + + # It doesn't make sense to test when a Nagios shutdown occurs after the + # end of the downtime + if( exists( $permutation{ "NagiosStop"}) && + exists( $permutation{ "DowntimeEnd"}) && + ( $permutation{ "NagiosStop"} > $permutation{ "DowntimeEnd"})) { + return 0; + } + + # A downtime cannot be created when Nagios is shutdown and it doesn't + # make sense to test when Nagios is shutdown and restarted before the + # downtime is created + if( exists( $permutation{ "NagiosStop"}) && + exists( $permutation{ "EntryTime"}) && + ( $permutation{ "NagiosStop"} < $permutation{ "EntryTime"})) { + return 0; + } + + # It doesn't make sense for the duration to be so short it ends before + # any real testing occurs + if( exists( $permutation{ "DurationEnd"}) && + ( $permutation{ "DurationEnd"} < 1)) { + return 0; + } + + # The following only applies to passive checks + unless( $activeChecks) { + # A passive service failure cannot be sent to Nagios when it is not + # running + if( exists( $permutation{ "ServiceFail"}) && + exists( $permutation{ "NagiosStop"}) && + exists( $permutation{ "NagiosStart"}) && + ( $permutation{ "ServiceFail"} > $permutation{ "NagiosStop"}) && + ( $permutation{ "ServiceFail"} < $permutation{ "NagiosStart"})) { + return 0; + } + + # A passive service recovery cannot be sent to Nagios when it is not + # running + if( exists( $permutation{ "ServiceRecover"}) && + exists( $permutation{ "NagiosStop"}) && + exists( $permutation{ "NagiosStart"}) && + ( $permutation{ "ServiceRecover"} > $permutation{ "NagiosStop"}) && + ( $permutation{ "ServiceRecover"} < $permutation{ "NagiosStart"})) { + return 0; + } + } + return 1; +} + +# Display a time in human-readable format +sub humanTime { + my $epoch = shift; + my $longFormat = 0; + $longFormat = shift if( @_); + + my ( $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = + localtime( $epoch); + if( $longFormat) { + return sprintf( "%04d-%02d-%02d %02d:%02d:%02d", $year+1900, $mon+1, + $mday, $hour, $min, $sec); + } + else { + return sprintf( "%02d:%02d:%02d", $hour, $min, $sec); + } +} + +# Display a time duration in human-readable format +sub humanDuration { + my $duration = shift; + my $wordyFormat = 0; + $wordyFormat = shift if( @_); + + my ( $durationLeft, $hours, $minutes, $seconds); + $durationLeft = $duration; + $hours = int( $durationLeft / ( 60 * 60)); + $durationLeft -= $hours * 60 * 60; + $minutes = int( $durationLeft / 60); + $durationLeft -= $minutes * 60; + $seconds = $durationLeft; + + if( $wordyFormat) { + if( $hours > 0) { + return sprintf( "%d hour%s, %d minute%s, %d second%s", + $hours, ( $hours == 1 ? "" : "s"), + $minutes, ( $minutes == 1 ? "" : "s"), + $seconds, ( $seconds == 1 ? "" : "s")); + } + elsif( $minutes > 0) { + return sprintf( "%d minute%s, %d second%s", + $minutes, ( $minutes == 1 ? "" : "s"), + $seconds, ( $seconds == 1 ? "" : "s")); + } + else { + return sprintf( "%d second%s", $duration, + ( $duration == 1 ? "" : "s")); + } + } + else { + return sprintf( "%02d:%02d:%02d (%ds)", $hours, $minutes, $seconds, + $duration); + } +} + +# Schedule a downtime series' event times +sub scheduleDowntimePermutation { + my $service = shift; + my $cfg = shift; + my $permutation = shift; + my $versionMajor = shift; + + # Initialize times + my %schedule; + $schedule{ "DowntimeStart"} = -1; + $schedule{ "DowntimeEnd"} = -1; + $schedule{ "DowntimeDuration"} = -1; + $schedule{ "NagiosStop"} = -1; + $schedule{ "NagiosStart"} = -1; + $schedule{ "ServiceFail"} = -1; + $schedule{ "ServiceRecover"} = -1; + + # Determine the amount of time to discover a service failure above + # the normal check results reaper frequency + my $maxDiscoveryTime = maxDiscoveryTime( $cfg, $service, $versionMajor); + + # Get the current time, to be used for all future times + my $currentTime = time; + + # Last event time + my $lastEventTime; + + if( $permutation->[ 0] eq "EntryTime") { + $schedule{ "DowntimeStart"} = 10; + $lastEventTime = $schedule{ "DowntimeStart"}; + } + elsif( $permutation->[ 0] eq "DowntimeStart") { + $schedule{ "DowntimeStart"} = -10; + $lastEventTime = $schedule{ "DowntimeStart"} + + ( $versionMajor < 4 ? + $cfg->{ "check_result_reaper_frequency"} : 0) + 2 ; + } + else { + die "Unsupported permutation order: " . $permutation->[ 0] . " => " . + $permutation->[ 1]; + } + + print join( " => ", @$permutation) . "\n"; + printf( " Downtime Start: %s\n", $schedule{ "DowntimeStart"}); + # Iterate through the remaining events, determining the time for each + for( my $x = 0; $x < @$permutation; $x++) { + if( $permutation->[ $x] eq "DowntimeEnd") { + $schedule{ "DowntimeEnd"} = $lastEventTime + + ( $cfg->{ "status_update_interval"} * + $cfg->{ "StatusUpdateIntervalMultiplier"}); + $lastEventTime = $schedule{ "DowntimeEnd"}; + printf( " Downtime End: %s\n", $schedule{ "DowntimeEnd"}); + } + elsif( $permutation->[ $x] eq "DowntimeStart") { + ; # Do nothing - Downtime Start was determined earlier + } + elsif( $permutation->[ $x] eq "DurationEnd") { + $schedule{ "DowntimeDuration"} = ( $lastEventTime - + $schedule{ "DowntimeStart"}) + + ( $cfg->{ "status_update_interval"} * + $cfg->{ "StatusUpdateIntervalMultiplier"} + + $maxDiscoveryTime); + $lastEventTime = $schedule{ "DowntimeDuration"} + + $schedule{ "DowntimeStart"}; + printf( " Duration: %d\n", $schedule{ "DowntimeDuration"}); + } + elsif( $permutation->[ $x] eq "EntryTime") { + ; # Do nothing + } + elsif( $permutation->[ $x] eq "NagiosStop") { + $schedule{ "NagiosStop"} = $lastEventTime + + ( $cfg->{ "status_update_interval"} * + $cfg->{ "StatusUpdateIntervalMultiplier"}); + $lastEventTime = $schedule{ "NagiosStop"}; + printf( " Nagios Stop: %s\n", $schedule{ "NagiosStop"}); + } + elsif( $permutation->[ $x] eq "NagiosStart") { + $schedule{ "NagiosStart"} = $lastEventTime + + ( $cfg->{ "status_update_interval"} * + $cfg->{ "StatusUpdateIntervalMultiplier"}); + $lastEventTime = $schedule{ "NagiosStart"}; + printf( " Nagios Start: %s\n", $schedule{ "NagiosStart"}); + } + elsif( $permutation->[ $x] eq "ServiceFail") { + $schedule{ "ServiceFail"} = $lastEventTime + + ( $cfg->{ "status_update_interval"} * + $cfg->{ "StatusUpdateIntervalMultiplier"}); + $lastEventTime = $schedule{ "ServiceFail"} + + ( $versionMajor < 4 ? + $cfg->{ "check_result_reaper_frequency"} : 0) + + $maxDiscoveryTime; + printf( " Service Fail: %s\n", $schedule{ "ServiceFail"}); + } + elsif( $permutation->[ $x] eq "ServiceRecover") { + $schedule{ "ServiceRecover"} = $lastEventTime + + ( $cfg->{ "status_update_interval"} * + $cfg->{ "StatusUpdateIntervalMultiplier"}); + $lastEventTime = $schedule{ "ServiceRecover"} + + ( $versionMajor < 4 ? + $cfg->{ "check_result_reaper_frequency"} : 0) + + $maxDiscoveryTime; + printf( " Service Recover: %s\n", $schedule{ "ServiceRecover"}); + } + else { + die "Unhandled event type: " . $permutation->[ $x]; + } + } + + return \%schedule; +} + +# Generate a list of valid permutations for fixed downtime events +sub fixedDowntimeTestPermutations { + my $service = shift; + + my @allPermutations; + + my @noRestart = ( "EntryTime", "DowntimeStart", "DowntimeEnd"); + my $iteratorNoRestart= Algorithm::Permute->new ( \@noRestart); + while (my @perm1 = $iteratorNoRestart->next) { + if( isValidEventPermutation( \@perm1, + $service->{ "active_checks_enabled"})) { +# print "(@perm1)\n"; + push( @allPermutations, \@perm1); + } + } + + my @withRestart = ( "EntryTime", "DowntimeStart", "NagiosStop", + "NagiosStart", "DowntimeEnd"); + my $iteratorWithRestart = + Algorithm::Permute->new ( \@withRestart); + while (my @perm2 = $iteratorWithRestart->next) { + if( isValidEventPermutation( \@perm2, + $service->{ "active_checks_enabled"})) { +# print "(@perm2)\n"; + push( @allPermutations, \@perm2); + } + } + + return \@allPermutations; + +} + +# Generate a list of valid permutations for flexible downtime events +sub flexibleDowntimeTestPermutations { + my $service = shift; + + my @allPermutations; + + my @noRestartOrTrigger = ( "EntryTime", "DowntimeStart", "DurationEnd", + "DowntimeEnd"); + my $iteratorNoRestartOrTrigger = + Algorithm::Permute->new ( \@noRestartOrTrigger ); + while (my @perm1 = $iteratorNoRestartOrTrigger->next) { + if( isValidEventPermutation( \@perm1, + $service->{ "active_checks_enabled"})) { + push( @allPermutations, \@perm1); + } + } + + my @noRestart = ( "EntryTime", "DowntimeStart", "DurationEnd", + "DowntimeEnd", "ServiceFail", "ServiceRecover"); + my $iteratorNoRestart = Algorithm::Permute->new ( \@noRestart ); + while (my @perm2 = $iteratorNoRestart->next) { + if( isValidEventPermutation( \@perm2, + $service->{ "active_checks_enabled"})) { + push( @allPermutations, \@perm2); + } + } + + my @noTrigger = ( "EntryTime", "DowntimeStart", "DurationEnd", + "DowntimeEnd", "NagiosStop", "NagiosStart"); + my $iteratorNoTrigger = Algorithm::Permute->new ( \@noTrigger ); + while (my @perm3 = $iteratorNoTrigger->next) { + if( isValidEventPermutation( \@perm3, + $service->{ "active_checks_enabled"})) { + push( @allPermutations, \@perm3); + } + } + + my @allEvents = ( "EntryTime", "DowntimeStart", "DurationEnd", + "DowntimeEnd", "NagiosStop", "NagiosStart", "ServiceFail", + "ServiceRecover"); + my $iteratorAllEventns = Algorithm::Permute->new ( \@allEvents ); + while (my @perm4 = $iteratorAllEventns->next) { + if( isValidEventPermutation( \@perm4, + $service->{ "active_checks_enabled"})) { + push( @allPermutations, \@perm4); + } + } + + return \@allPermutations; +} + +# This function verifies the global Nagios configuration +sub verifyConfig { + + my $cfg = shift; + my $versionMajor = shift; + + # Verify the status update interval + if( $cfg->{ "status_update_interval"} < 5) { + print STDERR sprintf( "status_update_interval (%d) is too short\n", + $cfg->{ "status_update_interval"}); + return 0; + } + if( $cfg->{ "status_update_interval"} >= 10) { + print sprintf( "The status_update_interval (%d) is long. " . + "It should optimally be 5 seconds.\n", + $cfg->{ "status_update_interval"}); + print "Press ENTER to continue..."; + ; + } + + if( $versionMajor < 4) { + # Verify the check_result_reaper_frequency + if( $cfg->{ "check_result_reaper_frequency"} < 5) { + print STDERR sprintf( "check_result_reaper_frequency (%d) is too " . + "short\n", $cfg->{ "check_result_reaper_frequency"}); + return 0; + } + if( $cfg->{ "check_result_reaper_frequency"} >= 10) { + print sprintf( "The check_result_reaper_frequency (%d) is long. " . + "It should optimally be 5 seconds.\n", + $cfg->{ "check_result_reaper_frequency"}); + print "Press ENTER to continue..."; + ; + } + } + + return 1; +} + +sub verifyService { + my $cfg = shift; + my $hostName = shift; + my $serviceDescription = shift; + + # Make sure there is an appropriately configured service before we + # start testing. + my $objects = readObjectCache( $cfg->{ "object_cache_file"}); + my $service = findService( $objects, $hostName, $serviceDescription); + if( !defined( $service)) { + print STDERR sprintf( "No service found for host '%s' and " . + "service description '%s'.\n", $hostName, $serviceDescription); + return undef; + } + if( !( $service->{ "active_checks_enabled"} || + $service->{ "passive_checks_enabled"})) { + print STDERR sprintf( "Either active or passive checks must be " . + "enabled for %s:%s\n", $hostName, $serviceDescription); + return undef; + } + if( $service->{ "notifications_enabled"}) { + print STDERR sprintf( "Notifications must not be enabled for %s:%s\n", + $hostName, $serviceDescription); + return undef; + } + if( $service->{ "flap_detection_enabled"}) { + print STDERR sprintf( "Flap detection must not be enabled for %s:%s\n", + $hostName, $serviceDescription); + return undef; + } + if( $service->{ "process_perf_data"}) { + print STDERR sprintf( "Performance data processing must not be " . + "enabled for %s:%s\n", $hostName, $serviceDescription); + return undef; + } + if( $service->{ "active_checks_enabled"}) { + if( $service->{ "max_check_attempts"} > 1) { + print sprintf( "The max_check_attempts (%d) is high. " . + "It should optimally be 1.\n", + $cfg->{ "max_check_attempts"}); + print "Press ENTER to continue..."; + ; + } + if( $service->{ "check_interval"} > 1) { + print sprintf( "The normal_check_interval (%d) is long. " . + "It should optimally be 1 minute.\n", + $cfg->{ "normal_interval"}); + print "Press ENTER to continue..."; + ; + } + if(( $service->{ "max_check_attempts"} > 1) && + ( $service->{ "retry_interval"} > 1)) { + print sprintf( "The retry_check_interval (%d) is long. " . + "It should optimally be 1 minute.\n", + $cfg->{ "retry_interval"}); + print "Press ENTER to continue..."; + ; + } + } + else { + if( $service->{ "check_freshness"}) { + print STDERR sprintf( "check_freshness must not be enabled " . + "for %s:%s\n", $hostName, $serviceDescription); + return undef; + } + if( $service->{ "max_check_attempts"} != 1) { + print STDERR sprintf( "max_check_attempts must be 1 for %s:%s\n", + $hostName, $serviceDescription); + return undef; + } + } + return $service; +} + +sub getVersion { + my $cfg = shift; + + my $status = readDatFile( $cfg->{ "status_file"}); + my @versionparts = split( /\./, $status->{ "info"}->{ "version"}); + my %version; + $version{ "major"} = $versionparts[ 0]; + $version{ "minor"} = $versionparts[ 1]; + $version{ "micro"} = $versionparts[ 2]; + + return \%version; +} + +sub isInArray { + my $string = shift; + my $array = shift; + + for( my $x = 0; $x < @$array; $x++) { + return 1 if( $array->[ $x] eq $string); + } + return 0; +} + +# This is the SIGUSR1 handler - it sets a flag that causes the test to +# pause. +sub pauseTest { + $testPaused = 1; +} + +sub usage { + my $cmd = shift; + + print < --service-description + [--single-run ] [--no-fixed-tests] [--no-flexible-tests] + [--skip-logged ] [--help|-?] + +Where: + --host-name specifies the name of the host whose service + is to be used for the downtime check. + --service-description specifies the name of the service + to be used for the downtime check. + --single-run indicates that the single specified test is + to be run. must be of the form "(Fixed|Flexible) + downtime: " is a comma and space + separated list of the following events: EntryTime, + DowntimeStart, [NagiosStop, NagiosStart,] [ServiceFail, + ServiceRecover,] DurationEnd, DowntimeEnd. The events within + the brackets are optional, but if one of the pair is used, + both must be used. Hint: the format of is the same as + is displayed at the beginning of each downtime check when + --single-run is not specified. + --no-fixed-tests indicates that no fixed tests should be run. + This option is ignored is --single-run is specified. + --no-flexible-tests indicates that no flexible tests should be + run. This option is ignored is --single-run is specified. + --skip-logged indicates that any tests logged in + should be skipped. This is useful for start over + where you left off if the test had been aborted prematurely. + --help|-? displays this help message. +EOU +} + +# Host and service to be used for testing +my $hostName = "localhost"; +my $serviceDescription = "Downtime Test"; +my $singleRun = undef; +my $logFile = undef; +my $noFixedTests = 0; +my $noFlexibleTests = 0; +my $showUsage = 0; + +$result = GetOptions ( "host-name=s" => \$hostName, + "service-description=s" => \$serviceDescription, + "single-run=s" => \$singleRun, + "no-fixed-tests" => \$noFixedTests, + "no-flexible-tests" => \$noFlexibleTests, + "skip-logged=s" => \$logFile, + "help|?" => \$showUsage); + +die "Error processing command line options" unless( $result); + +if( $showUsage) { + usage( $PROGRAM_NAME); + exit( 0); +} + +# Install signal handle to enable test pausing +$SIG{ "USR1"} = "pauseTest"; + +# Make sure we're running as root +if( $EUID != 0) { + print STDERR "This script must be run as root.\n"; + exit 1; +} + +# Make sure Nagios is running +my $status = `/sbin/service nagios status`; +if( $status !~ /nagios \(pid( \d+)+\) is running.../) { + print STDERR "Nagios must be running in order to run this test.\n"; + exit 1; +} + +# Read the Nagios configuration +my $cfg = readCfgFile( "/usr/local/nagios/etc/nagios.cfg"); +exit 1 unless( defined( $cfg)); + +# Get the version +my $version = getVersion( $cfg); +printf( "Nagios version is %d.%d.%d\n", $version->{ "major"}, + $version->{ "minor"}, $version->{ "micro"}); + +# Verify the global configuration +unless( verifyConfig( $cfg, $version->{ "major"}) > 0) { + exit 1; +} +$cfg->{ "StatusUpdateIntervalMultiplier"} = 4; + +# Verify the service configuration +my $service = verifyService( $cfg, $hostName, $serviceDescription); +exit 1 unless( defined( $service)); + +# Enable autoflush on STDOUT so updates occur +my $old_fh = select(STDOUT); +$| = 1; +select($old_fh); + +my $activeChecks = 0; +my $permutationTime = 0; +my $elapsedTime = 0; +my $schedule; +my $comment; + +#my @testPerm = ( "DowntimeStart", "DurationEnd", "EntryTime", "ServiceFail", "NagiosStop", "DowntimeEnd", "NagiosStart", "ServiceRecover"); +#my $testSchedule = scheduleDowntimePermutation( $service, $cfg, \@testPerm, +# $version->{ "major"}); +#my $testComment = join( ", ", @testPerm); +#checkDowntime( "Flexible downtime: $testComment", $service, $cfg, 0, +# $testSchedule, $version->{ "major"}); +#exit( 0); + +if( defined( $singleRun)) { + if( $singleRun =~ /^(Fixed|Flexible) downtime: (.*)/) { + my $downtimeType = $1; + my @singleRunPerm = split( /, /, $2); + my $fixed = (( $singleRun =~ /^Fixed/) ? 1 : 0); + my $testSchedule = scheduleDowntimePermutation( $service, $cfg, + \@singleRunPerm, $version->{ "major"}); + my $testComment = join( ", ", @singleRunPerm); + checkDowntime( "$downtimeType downtime: $testComment", $service, $cfg, + $fixed, $testSchedule, $version->{ "major"}); + exit 0; + } + else { + die "Unrecognized single run format: $singleRun"; + } +} +else { + my @skipTests = (); + if( defined( $logFile)) { + open( LOG, "$logFile") || + die "Unable to open log file $logFile for reading"; + while( ) { + chomp; + push( @skipTests, $_) if( /^(Fixed|Flexible) downtime: /); + } + close( LOG) || die "Unable to close $logFile"; + } + + my $lastTriedPermutation = -1; + unless( $noFixedTests) { + my $fixedDowntimeTests = fixedDowntimeTestPermutations( $service); + for( my $x = 0; $x < @$fixedDowntimeTests; $x++) { + if( $testPaused) { + print "Testing paused as requested.\n"; + print "Press ENTER to continue..."; + ; + $testPaused = 0; + } + $comment = join( ", ", @{ $fixedDowntimeTests->[ $x]}); + unless( isInArray( "Fixed downtime: $comment", \@skipTests)) { + printf( "Fixed Test %d of %d\n", $x + 1, + scalar( @$fixedDowntimeTests)); + $schedule = scheduleDowntimePermutation( $service, $cfg, + $fixedDowntimeTests->[ $x], $version->{ "major"}); + $permutationTime = checkDowntime( "Fixed downtime: $comment", + $service, $cfg, 1, $schedule, $version->{ "major"}); + if( $permutationTime == -1) { + if( $lastTriedPermutation != $x) { + print "Downtime test failed: retrying\n"; + $lastTriedPermutation = $x; + $x--; + } + else { + die "Downtime test failed after retry\n"; + } + } + else { + $lastTriedPermutation = $x; + $elapsedTime += $permutationTime; + printf( "Last test time: %s\n", + humanDuration( $permutationTime)); + printf( "Elapsed time thus far: %s\n", + humanDuration( $elapsedTime)); + } + } + else { + $lastTriedPermutation = $x; + printf( "Skipping fixed downtime: %s\n", $comment); + } + } + } + + $lastTriedPermutation = -1; + unless( $noFlexibleTests) { + my $flexibleDowntimeTests = flexibleDowntimeTestPermutations( $service); + for( my $y = 0; $y < @$flexibleDowntimeTests; $y++) { + if( $testPaused) { + print "Testing paused as requested.\n"; + print "Press ENTER to continue..."; + ; + $testPaused = 0; + } + $comment = join( ", ", @{ $flexibleDowntimeTests->[ $y]}); + unless( isInArray( "Flexible downtime: $comment", \@skipTests)) { + printf( "Flexible Test %d of %d\n", $y + 1, + scalar( @$flexibleDowntimeTests)); + $schedule = scheduleDowntimePermutation( $service, $cfg, + $flexibleDowntimeTests->[ $y], $version->{ "major"}); + $permutationTime = checkDowntime( "Flexible downtime: $comment", + $service, $cfg, 0, $schedule, $version->{ "major"}); + if( $permutationTime == -1) { + if( $lastTriedPermutation != $y) { + print "Downtime test failed: retrying\n"; + $lastTriedPermutation = $y; + $y--; + } + else { + die "Downtime test failed after retry\n"; + } + } + else { + $lastTriedPermutation = $y; + $elapsedTime += $permutationTime; + printf( "Last test time: %s\n", + humanDuration( $permutationTime)); + printf( "Elapsed time thus far: %s\n", + humanDuration( $elapsedTime)); + } + } + else { + $lastTriedPermutation = $y; + printf( "Skipping flexible downtime: %s\n", $comment); + } + } + } +} diff --git a/tools/tinderbox_build b/tools/tinderbox_build deleted file mode 100755 index 01d9a8e..0000000 --- a/tools/tinderbox_build +++ /dev/null @@ -1,291 +0,0 @@ -#!/usr/bin/perl -# tinderbox_build.pl -# This script builds the nagios code and then sends -# logs back to the master tinderbox server -# -# This script is based on mozilla-unix.pl which comes with tinderbox2 -# -# See http://tinderbox.nagios.org for more details - -require 5.000; - -use strict; -use Sys::Hostname; -use Cwd; -use Time::Local; - -my $Version = "1.0"; - -my $myhost = hostname; -chomp($myhost); -my ($host, $junk) = split(/\./, $myhost); - -my $BuildAdministrator = $ENV{TINDERBOX_BUILD_ADMIN} || "$ENV{'USER'}\@$myhost"; -my $TmpDir = $ENV{TMPDIR} || "/tmp"; - -#Default values of cmdline opts -my $ReportStatus = 0; # Do not send results to server - -# Set these to what makes sense for your system - -# Set these proper values for your tinderbox server -# Have the StrictHostKeyChecking=no so that a new host will automatically add hostkey without -# prompting. If host key changes, then will get error, so this should still be secure -my $Tinderbox_user = "tinderbox2"; -my $Tinderbox_server = 'tinderbox.nagios.org'; -my $Tinderbox_ssh_args = "-o StrictHostKeyChecking=no $Tinderbox_user\@$Tinderbox_server"; - -# These shouldn't really need to be changed -my $BuildTree = 'nagios'; -my $BuildName = ''; -my $ConfigureArgs = $ENV{CONFIGURE_ARGS}; - -my $OS = `uname -s`; -my $OSVer = `uname -r`; - -chop($OS, $OSVer); - -if ( $OS eq 'AIX' ) { - $OSVer = `uname -v`; - chop($OSVer); - $OSVer = $OSVer . "." . `uname -r`; - chop($OSVer); -} - -if ( $OS eq 'IRIX64' ) { - $OS = 'IRIX'; -} - -if ( $OS eq 'SCO_SV' ) { - $OS = 'SCOOS'; - $OSVer = '5.0'; -} - -if ( "$host" ne "" ) { - $BuildName = $host . ' '; -} -$BuildName .= $OS . ' ' . $OSVer; -$_ = $BuildName; -s/ /_/g; - -my $logfile = "$_.log"; - -sub BuildIt { - my ($fe, @felist, $EarlyExit, $LastTime); - - my $StartDir = getcwd(); - $LastTime = 0; - - print "Starting dir is : $StartDir\n"; - - my $EarlyExit = 0; - - chdir("$StartDir"); - - my $StartTime = time; - if (-e (my $file = "nagios-plugins.spec")) { - open F, $file; - while () { - if (/^Version: trunk-(\d\d\d\d)(\d\d)(\d\d)(\d\d)(\d\d)$/) { - $StartTime = timegm(0, $5, $4, $3, ($2 - 1), ($1 - 1900)); - last; - } - } - } - - print "Start time is $StartTime",$/; - - my $CurrentDir = getcwd(); - if ( $CurrentDir ne $StartDir ) { - print "startdir: $StartDir, curdir $CurrentDir\n"; - die "curdir != startdir"; - } - - unlink( "$logfile" ); - - print "opening $logfile\n"; - open( LOG, ">$logfile" ) || print "can't open $?\n"; - print LOG "current dir is -- $host:$CurrentDir\n"; - print LOG "Build Administrator is $BuildAdministrator\n"; - &PrintEnv; - - my $BuildStatus; - if (&configure) { - if (&make) { - if (&maketest) { - $BuildStatus = "success"; - } else { - $BuildStatus = "test_failed"; - } - } else { - $BuildStatus = "build_failed"; - } - } else { - $BuildStatus = "busted"; - } - - print LOG "\nBuild Status = $BuildStatus\n"; - - close(LOG); - chdir("$StartDir"); - -# TV: Leaving this in, because process mail program probably has some -# limitation retained - -# this fun line added on 2/5/98. do not remove. Translated to english, -# that's "take any line longer than 1000 characters, and split it into less -# than 1000 char lines. If any of the resulting lines is -# a dot on a line by itself, replace that with a blank line." -# This is to prevent cases where a . occurs in the log file. Sendmail -# interprets that as the end of the mail, and truncates the log before -# it gets to Tinderbox. (terry weismann, chris yeh) -# -# This was replaced by a perl 'port' of the above, writen by -# preed@netscape.com; good things: no need for system() call, and now it's -# all in perl, so we don't have to do OS checking like before. - - open(LOG, "$logfile") || die "Couldn't open logfile: $!\n"; - open(OUTLOG, ">${logfile}.last") || die "Couldn't open logfile: $!\n"; - - print OUTLOG $/; - print OUTLOG "tinderbox: tree: $BuildTree\n"; - print OUTLOG "tinderbox: builddate: $StartTime\n"; - print OUTLOG "tinderbox: status: $BuildStatus\n"; - print OUTLOG "tinderbox: build: $BuildName $fe\n"; - print OUTLOG "tinderbox: errorparser: unix\n"; - print OUTLOG "tinderbox: buildfamily: unix\n"; - print OUTLOG "tinderbox: END\n"; - print OUTLOG $/; - - while () { - my $q = 0; - - for (;;) { - my $val = $q * 1000; - my $Output = substr($_, $val, 1000); - - last if $Output eq undef; - - $Output =~ s/^\.$//g; - $Output =~ s/\n//g; - print OUTLOG "$Output\n"; - $q++; - } #EndFor - - } #EndWhile - - close(LOG); - close(OUTLOG); - - if ($ReportStatus) { - system( "ssh $Tinderbox_ssh_args tinderbox_receive < ${logfile}.last" ) - } else { - print <<"EOF" -Not sending logs to http://$Tinderbox_server -If you have SSH keys setup on the tinderbox server, you can manually send -with 'ssh $Tinderbox_ssh_args tinderbox_receive < ${logfile}.last' -EOF - } - - unlink("$logfile"); - print "Finished building for tinderbox",$/; - -} #EndSub-BuildIt - -sub ParseArgs { - my($i); - - $i = 0; - while( $i < @ARGV ) { - if ($ARGV[$i] eq '--version' || $ARGV[$i] eq '-v') { - die "$0: version $Version\n"; - } elsif ($ARGV[$i] eq '-y') { - $ReportStatus = 1; - } else { - &PrintUsage; - } - - $i++; - } #EndWhile - -} #EndSub-ParseArgs - -sub PrintUsage { - die "usage: $0 [-v | --version ] [-t do not send report to tinderbox server]\n"; -} - -sub PrintEnv { - my ($key); - foreach $key (keys %ENV) { - print LOG "$key = $ENV{$key}\n"; - print "$key = $ENV{$key}\n"; - } - - # Print the NPTest variables - if (-e "/var/tmp/NPTest.cache") { - open F, "/var/tmp/NPTest.cache"; - print LOG "NPTest variables:\n"; - print LOG ; - close F; - } - -} #EndSub-PrintEnv - -sub SetupPath { - my($Path); - $Path = $ENV{PATH}; - print "Path before: $Path\n"; - - # Don't alter path if we're building off a repository tree; - # SunOS make will be used only for snapshots and releases. - if ( $OS eq 'SunOS' && !( -e '.svn' || -e '.git' )) { - $ENV{'PATH'} = '/usr/ccs/bin:' . $ENV{'PATH'}; - } - - $Path = $ENV{PATH}; - print "Path After: $Path\n"; -} #EndSub-SetupPath - -sub configure { - # Configure - print LOG "./configure --enable-libtap $ConfigureArgs 2>&1\n"; - open (CONFIGURE, "./configure --enable-libtap $ConfigureArgs 2>&1 |") || die "../configure: $!\n"; - while () { - print $_; - print LOG $_; - } - close(CONFIGURE); - return ! $?; -} - -sub make { - # Building - print LOG "make nagios && make cgis 2>&1\n"; - open( MAKE, "make nagios && make cgis 2>&1 |"); - while ( ) { - print $_; - print LOG $_; - } - close( MAKE); - return ! $?; -} - -sub maketest { - # Tests - print LOG "LANG=C make test 2>&1\n"; - open( MAKE, "LANG=C make test 2>&1 |"); - while ( ) { - print $_; - print LOG $_; - } - close( MAKE); - my $rc = $?; - return ! $rc; -} - -# Main function -&ParseArgs; -&SetupPath; -&BuildIt; - -1; diff --git a/update-version b/update-version index fb5041d..7b6c379 100755 --- a/update-version +++ b/update-version @@ -3,17 +3,19 @@ # Get date (two formats) if [ -n "$2" ]; then LONGDATE=`date -d "$2" "+%B %d, %Y"` - SHORTDATE=`date -d "$2" "+%m-%d-%Y"` + SHORTDATE=`date -d "$2" "+%Y-%m-%d"` + YEAR=`date -d "$2" "+%Y"` else LONGDATE=`date "+%B %d, %Y"` - SHORTDATE=`date "+%m-%d-%Y"` + SHORTDATE=`date "+%Y-%m-%d"` + YEAR=`date "+%Y"` fi # Current version number -CURRENTVERSION=3.5.1 +CURRENTVERSION=4.3.2 # Last date -LASTDATE=08-30-2013 +LASTDATE=2017-05-09 if [ "x$1" = "x" ] then @@ -42,36 +44,28 @@ then fi # Update version number and release date in main PHP page -perl -i -p -e "s/>Version .*Version $newversion.*<\//releasedate\">$LONGDATE<\//;" html/main.php -perl -i -p -e "s/\?version=.*&product=/\?version=$newversion&product=/;" html/main.php -perl -i -p -e "s/$this_version=\".*\";/$this_version=\"$newversion\";/;" html/main.php +perl -i -p -e "s/this_version = '.*';/this_version = '$newversion';/;" html/main.php +perl -i -p -e "s/this_version = '.*';/this_version = '$newversion';/;" html/side.php # Update version number and release date in common code -perl -i -p -e "s/VERSION \".*\"/VERSION \"$newversion\"/;" include/common.h +perl -i -p -e "s/PROGRAM_VERSION \".*\"/PROGRAM_VERSION \"$newversion\"/;" include/common.h perl -i -p -e "s/MODIFICATION_DATE \".*\"/MODIFICATION_DATE \"$SHORTDATE\"/;" include/common.h -# Update version number and release date in main code -perl -i -p -e "s/Version: .*/Version: $newversion/;" base/nagios.c -perl -i -p -e "s/Last Modified: [0-9].*/Last Modified: $SHORTDATE/;" base/nagios.c -perl -i -p -e "s/Version: [0-9].*/Version: $newversion/;" base/nagiostats.c -perl -i -p -e "s/Last Modified: [0-9].*/Last Modified: $SHORTDATE/;" base/nagiostats.c - # Update version number and release date in configure script and configure.in perl -i -p -e "s/PKG_VERSION=.*/PKG_VERSION=\"$newversion\"/;" configure perl -i -p -e "s/PKG_REL_DATE=.*\"/PKG_REL_DATE=\"$SHORTDATE\"/;" configure -perl -i -p -e "s/PKG_VERSION=.*/PKG_VERSION=\"$newversion\"/;" configure.in -perl -i -p -e "s/PKG_REL_DATE=.*\"/PKG_REL_DATE=\"$SHORTDATE\"/;" configure.in +perl -i -p -e "s/PKG_VERSION=.*/PKG_VERSION=\"$newversion\"/;" configure.ac +perl -i -p -e "s/PKG_REL_DATE=.*\"/PKG_REL_DATE=\"$SHORTDATE\"/;" configure.ac # Update RPM spec file with version number -perl -i -p -e "s/%define version .*/%define version $newversion/;" nagios.spec +perl -i -p -e "s/Version: .*/Version: $newversion/;" nagios.spec -# Update quickstart guides with new version number -#perl -i -p -e "s/nagios-$lastversion/nagios-$newversion/;" html/docs/quickstart-fedora.html -#perl -i -p -e "s/nagios-$lastversion/nagios-$newversion/;" html/docs/quickstart-opensuse.html -#perl -i -p -e "s/nagios-$lastversion/nagios-$newversion/;" html/docs/quickstart-ubuntu.html +# Update the doxygen docs +perl -i -p -e "s/^PROJECT_NUMBER = .*/PROJECT_NUMBER = $newversion/;" doxy.conf # Update this file with version number and last date perl -i -p -e "s/^CURRENTVERSION=.*/CURRENTVERSION=$newversion/;" update-version perl -i -p -e "s/^LASTDATE=.*/LASTDATE=$SHORTDATE/;" update-version - diff --git a/worker/Makefile.in b/worker/Makefile.in new file mode 100644 index 0000000..bc5f9ba --- /dev/null +++ b/worker/Makefile.in @@ -0,0 +1,36 @@ +################################### +# Makefile for NEB examples +# +################################### + + +# Source code directories +SRC_PING_WORKER=./ping + +default: + @echo "Please supply a command line argument (i.e. 'make all'). Other targets are:" + @echo " ping-worker" + @echo " clean distclean" + @echo " install-all install-ping" + +ping-worker: + cd $(SRC_PING_WORKER) && $(MAKE) all + +all: + cd $(SRC_PING_WORKER) && $(MAKE) all + +clean: + cd $(SRC_PING_WORKER) && $(MAKE) $@ + rm -f *~ *.*~ + +distclean: clean + cd $(SRC_PING_WORKER) && $(MAKE) $@ + rm -f Makefile + +devclean: distclean + +install-ping: + cd $(SRC_PING_WORKER) && $(MAKE) install + +install-all: install-ping + diff --git a/worker/ping/.gitignore b/worker/ping/.gitignore new file mode 100644 index 0000000..990aea1 --- /dev/null +++ b/worker/ping/.gitignore @@ -0,0 +1 @@ +worker-ping diff --git a/worker/ping/Makefile.in b/worker/ping/Makefile.in new file mode 100644 index 0000000..e26e4c3 --- /dev/null +++ b/worker/ping/Makefile.in @@ -0,0 +1,55 @@ +################################### +# Makefile for NEB examples +# +################################### + + +# Source code directories +SRC_LIB=@srcdir@/lib +SRC_INCLUDE=@srcdir@/include + +CC=@CC@ +WORKER_CFLAGS=@WORKER_CFLAGS@ +CFLAGS=@CFLAGS@ @DEFS@ +WORKER_LDFLAGS=@WORKER_LDFLAGS@ +LDFLAGS=@LDFLAGS@ +LIBS=@LIBS@ + +prefix=@prefix@ +exec_prefix=@exec_prefix@ +BINDIR=@bindir@ +INSTALL=@INSTALL@ +INSTALL_OPTS=@INSTALL_OPTS@ +COMMAND_OPTS=@COMMAND_OPTS@ +STRIP=@STRIP@ + +CP=@CP@ + +all: worker-ping + +worker-ping: worker-ping.c + $(CC) -I.. $(WORKER_CFLAGS) $(CFLAGS) -o worker-ping worker-ping.c $(WORKER_LDFLAGS) $(LDFLAGS) $(LIBS) + +clean: + rm -f worker-ping worker-ping.o + rm -f core *.o + rm -f *~ *.*~ + +distclean: clean + rm -f Makefile + +devclean: distclean + +install: + $(MAKE) install-basic + $(MAKE) strip-post-install + +install-unstripped: + $(MAKE) install-basic + +install-basic: + $(INSTALL) -m 775 $(INSTALL_OPTS) -d $(DESTDIR)$(BINDIR) + $(INSTALL) -m 774 $(INSTALL_OPTS) worker-ping $(DESTDIR)$(BINDIR) + +strip-post-install: + $(STRIP) $(DESTDIR)$(BINDIR)/worker-ping diff --git a/worker/ping/worker-ping.c b/worker/ping/worker-ping.c new file mode 100644 index 0000000..cbef2f4 --- /dev/null +++ b/worker/ping/worker-ping.c @@ -0,0 +1,466 @@ +/****************************************************************************** + * + * worker-ping.c - Nagios Core 4 worker to handle ping checke + * + * Program: Nagios Core + * License: GPL + * + * First Written: 01-03-2013 (start of development) + * + * Description: + * + * License: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + *****************************************************************************/ + +#include "config.h" +#include "workers.h" + +/* Local macro definitions */ +#define PING_WORKER_VERSION "0.2" +#define PING_WORKER_MODIFICATION_DATE "02-Feb-13" + +#define PW_OK 0 +#define PW_ERROR 1 + +/* Local function declarations */ +int daemon_init( void); +int drop_privileges( char *, char *); +void print_license( void); +void print_usage( char *); +void print_version( void); +void parse_worker_command_line( int, char **, char **, int *, char **, + char **, char **); +static int worker( const char *); + +/* Everything starts here */ +main( int argc, char **argv, char **env) { + int daemon_mode = FALSE; + char *worker_socket; + char *worker_user = ( char *)0; + char *worker_group = ( char *)0; + + if( FALSE == daemon_mode) { + printf( "Greetings from the ping worker.\n"); + } + + parse_worker_command_line( argc, argv, env, &daemon_mode, &worker_socket, + &worker_user, &worker_group); + + if( FALSE == daemon_mode) { + print_version(); + printf( "Worker socket is %s.\n", worker_socket); + } + + /* drop privileges */ + if( drop_privileges( worker_user, worker_group) == PW_ERROR) { + fprintf( stderr, "Failed to drop privileges. Aborting.\n"); + exit( 1); + } + + if( TRUE == daemon_mode) { + if( daemon_init() == ERROR) { + fprintf( stderr, + "Bailing out due to failure to daemonize. (PID=%d)\n", + ( int)getpid()); + exit( 1); + } + } + + /* Enter the worker code */ + if( worker( worker_socket)) { + exit( 1); + } +} + +void parse_worker_command_line( int argc, char **argv, char **env, + int *daemon_mode, char **worker_socket, char **worker_user, + char **worker_group) { + int c = 0; + int display_usage = FALSE; + int display_license = FALSE; + +#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'}, + { "daemon", no_argument, 0, 'd'}, + { "worker", required_argument, 0, 'W'}, + { "user", required_argument, 0, 'u'}, + { "group", required_argument, 0, 'g'}, + { 0, 0, 0, 0} + }; +#define getopt( argc, argv, o) getopt_long( argc, argv, o, long_options, &option_index) +#endif + + /* get all command line arguments */ + while( 1) { + c = getopt( argc, argv, "+:hVdW:u:g:"); + + if( -1 == c || EOF == c) break; + + switch( c) { + + case '?': /* usage */ + case 'h': + display_usage = TRUE; + break; + + case 'V': /* version */ + display_license = TRUE; + break; + + case 'd': /* daemon mode */ + *daemon_mode = TRUE; + break; + + case 'W': + *worker_socket = optarg; + break; + + case 'u': + *worker_user = optarg; + break; + + case 'g': + *worker_group = optarg; + break; + + case ':': + printf( "Missing argument for command line option '%c'.\n\n", + optopt); + print_usage( argv[ 0]); + exit( 1); + break; + + default: + printf( "Unknown command line option '%c'.\n\n", c); + print_usage( argv[ 0]); + exit( 1); + break; + } + } + + if( TRUE == display_license) { + print_version(); + print_license(); + exit( 0); + } + + if( TRUE == display_usage) { + print_usage( argv[ 0]); + exit( 0); + } + +} + +void print_license( void) { + printf( "\nThis 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"); +} + +void print_usage( char *program_name) { + printf( "\nUsage: %s [-?|-h|--help] [-V|--version] [-d]\n", program_name); + printf( " -W /path/to/socket -u user -g group\n"); + printf( "\n"); + printf( "Options:\n"); + printf( "\n"); + printf( " -d, --daemon Starts the ping worker in daemon mode,\n"); + printf( " instead of as a foreground process\n"); + printf( " -W, --worker /path/to/socket Act as a worker for an already running daemon\n"); + printf( " -u, --user user Drop privileges to the specified user\n"); + printf( " -g, --group group Drop privileges to the specified user\n"); + printf( "\n"); + printf( "Visit the Nagios website at https://www.nagios.org/ for bug fixes, new\n"); + printf( "releases, online documentation, FAQs, information on subscribing to\n"); + printf( "the mailing lists, and commercial support options for Nagios.\n"); + printf( "\n"); +} + +void print_version( void) { + printf( "\nNagios Core 4 Ping Worker %s\n", PING_WORKER_VERSION); + printf( "Copyright (c) 2013-present Nagios Core Development Team\n"); + printf( " and Community Contributors\n"); + printf( "Last Modified: %s\n", PING_WORKER_MODIFICATION_DATE); + printf( "License: GPL\n"); + printf( "Website: https://www.nagios.org\n"); +} + +static int worker( const char *path) +{ + int sd, ret; + char response[128]; + + /*set_loadctl_defaults();*/ + + sd = nsock_unix( path, NSOCK_TCP | NSOCK_CONNECT); + if( sd < 0) { + printf( "Failed to connect to query socket '%s': %s: %s\n", + path, nsock_strerror( sd), strerror( errno)); + return 1; + } + + ret = nsock_printf_nul( sd, "@wproc register name=Core Ping Worker %d;pid=%d;plugin=check_ping", getpid(), getpid()); + if( ret < 0) { + printf( "Failed to register as worker.\n"); + return 1; + } + + ret = read( sd, response, 3); + if( ret != 3) { + printf( "Failed to read response from wproc manager\n"); + return 1; + } + if( memcmp( response, "OK", 3)) { + read( sd, response + 3, sizeof(response) - 4); + response[ sizeof( response) - 2] = 0; + printf( "Failed to register with wproc manager: %s\n", response); + return 1; + } + + enter_worker( sd, start_cmd); + return 0; +} + +int drop_privileges( char *user, char *group) { + uid_t uid = -1; + gid_t gid = -1; + struct group *grp = NULL; + struct passwd *pw = NULL; + int result = PW_OK; + + /* only drop privileges if we're running as root, so we don't + interfere with being debugged while running as some random user */ + if( getuid() != 0) { + return PW_OK; + } + + /* set effective group ID */ + if( NULL != group) { + + /* see if this is a group name */ + if( strspn( group, "0123456789") < strlen( group)) { + grp = ( struct group *)getgrnam( group); + if( NULL != grp) { + gid = ( gid_t)(grp->gr_gid); + } + else { + fprintf( stderr, + "Warning: Could not get group entry for '%s'\n", group); + } + } + + /* else we were passed the GID */ + else { + gid = ( gid_t)atoi( group); + } + + /* set effective group ID if other than current EGID */ + if( gid != getegid()) { + if( setgid( gid) == -1) { + fprintf( stderr, "Warning: Could not set effective GID=%d\n", + ( int)gid); + result = PW_ERROR; + } + } + } + + /* set effective user ID */ + if( NULL != user) { + + /* see if this is a user name */ + if( strspn( user, "0123456789") < strlen( user)) { + pw = ( struct passwd *)getpwnam( user); + if( NULL != pw) { + uid = ( uid_t)(pw->pw_uid); + } + else { + fprintf( stderr, + "Warning: Could not get passwd entry for '%s'\n", user); + } + } + + /* else we were passed the UID */ + else { + uid = ( uid_t)atoi( user); + } + +#ifdef HAVE_INITGROUPS + + if( uid != geteuid()) { + + /* initialize supplementary groups */ + if( initgroups( user, gid) == -1) { + if( EPERM == errno) { + fprintf( stderr, "Warning: Unable to change supplementary " + "groups using initgroups() -- I hope you know what " + "you're doing\n"); + } + else { + fprintf( stderr, "Warning: Possibly root user failed " + "dropping privileges with initgroups()\n"); + return PW_ERROR; + } + } + } +#endif + if( setuid( uid) == -1) { + fprintf( stderr, "Warning: Could not set effective UID=%d\n", + ( int)uid); + result = PW_ERROR; + } + } + + return result; +} + +int daemon_init( void) { + pid_t pid = -1; + int pidno = 0; + int lockfile = 0; + int val = 0; + char buf[256]; + struct flock lock; + char *homedir = NULL; + +#ifdef RLIMIT_CORE + struct rlimit limit; +#endif + + /* change working directory. scuttle home if we're dumping core */ + homedir = getenv( "HOME"); +#ifdef DAEMON_DUMPS_CORE + if( NULL != homedir) { + chdir( homedir); + } + else { +#endif + chdir( "/"); +#ifdef DAEMON_DUMPS_CORE + } +#endif + + umask( S_IWGRP | S_IWOTH); + + /* close existing stdin, stdout, stderr */ + close( 0); + close( 1); + close( 2); + + /* THIS HAS TO BE DONE TO AVOID PROBLEMS WITH STDERR BEING REDIRECTED TO SERVICE MESSAGE PIPE! */ + /* re-open stdin, stdout, stderr with known values */ + open( "/dev/null", O_RDONLY); + open( "/dev/null", O_WRONLY); + open( "/dev/null", O_WRONLY); + +#ifdef USE_LOCKFILE + lockfile = open( lock_file, + O_RDWR | O_CREAT, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH); + + if( lockfile < 0) { + logit( NSLOG_RUNTIME_ERROR, TRUE, "Failed to obtain lock on file %s: %s\n", lock_file, strerror(errno)); + logit( NSLOG_PROCESS_INFO | NSLOG_RUNTIME_ERROR, TRUE, "Bailing out due to errors encountered while attempting to daemonize... (PID=%d)", (int)getpid()); + + exit( 1); + } + + /* see if we can read the contents of the lockfile */ + if(( val = read( lockfile, buf, ( size_t)10)) < 0) { + logit(NSLOG_RUNTIME_ERROR, TRUE, "Lockfile exists but cannot be read"); + exit( 1); + } + + /* we read something - check the PID */ + if( val > 0) { + if(( val = sscanf( buf, "%d", &pidno)) < 1) { + logit( NSLOG_RUNTIME_ERROR, TRUE, "Lockfile '%s' does not contain a valid PID (%s)", lock_file, buf); + exit( 1); + } + } + + /* check for SIGHUP */ + if( val == 1 && ( pid = ( pid_t)pidno) == getpid()) { + close( lockfile); + return OK; + } +#endif + + /* exit on errors... */ + if(( pid = fork()) < 0) { + return( PW_ERROR); + } + + /* parent process goes away.. */ + else if((int)pid != 0) { + exit( 0); + } + + /* child continues... */ + + /* child becomes session leader... */ + setsid(); + +#ifdef USE_LOCKFILE + /* place a file lock on the lock file */ + lock.l_type = F_WRLCK; + lock.l_start = 0; + lock.l_whence = SEEK_SET; + lock.l_len = 0; + if( fcntl( lockfile, F_SETLK, &lock) < 0) { + if( EACCES == errno || EAGAIN == errno) { + fcntl( lockfile, F_GETLK, &lock); + logit( NSLOG_RUNTIME_ERROR, TRUE, "Lockfile '%s' looks like its already held by another instance of Nagios (PID %d). Bailing out...", lock_file, (int)lock.l_pid); + } + else { + logit(NSLOG_RUNTIME_ERROR, TRUE, "Cannot lock lockfile '%s': %s. Bailing out...", lock_file, strerror(errno)); + + } + exit( 1); + } +#endif + + /* prevent daemon from dumping a core file... */ +#if defined( RLIMIT_CORE) && defined( DAEMON_DUMPS_CORE) + getrlimit( RLIMIT_CORE, &limit); + limit.rlim_cur = 0; + setrlimit( RLIMIT_CORE, &limit); +#endif + +#ifdef USE_LOCKFILE + /* write PID to lockfile... */ + lseek( lockfile, 0, SEEK_SET); + ftruncate( lockfile, 0); + sprintf( buf, "%d\n", ( int)getpid()); + write( lockfile, buf, strlen( buf)); + + /* make sure lock file stays open while program is executing... */ + val = fcntl( lockfile, F_GETFD, 0); + val |= FD_CLOEXEC; + fcntl( lockfile, F_SETFD, val); +#endif + + return PW_OK; +} diff --git a/xdata/Makefile.in b/xdata/Makefile.in index 22993e8..b4cc14d 100644 --- a/xdata/Makefile.in +++ b/xdata/Makefile.in @@ -1,7 +1,6 @@ ############################ # Makefile for Nagios # -# Last Modified: 04-08-2003 ############################ clean: diff --git a/xdata/xcddefault.c b/xdata/xcddefault.c index 868cd13..803e1ae 100644 --- a/xdata/xcddefault.c +++ b/xdata/xcddefault.c @@ -2,8 +2,6 @@ * * XCDDEFAULT.C - Default external comment data routines for Nagios * - * Copyright (c) 2000-2007 Ethan Galstad (egalstad@nagios.org) - * Last Modified: 09-04-2007 * * License: * @@ -30,38 +28,19 @@ #include "../include/locations.h" #include "../include/comments.h" #include "../include/macros.h" - -#ifdef NSCORE #include "../include/objects.h" #include "../include/nagios.h" -#endif - -#ifdef NSCGI -#include "../include/cgiutils.h" -#endif - - -/**** IMPLEMENTATION SPECIFIC HEADER FILES ****/ #include "xcddefault.h" -#ifdef NSCORE -extern unsigned long next_comment_id; -extern comment *comment_list; -#endif - - - -#ifdef NSCORE - /******************************************************************/ /************ COMMENT INITIALIZATION/CLEANUP FUNCTIONS ************/ /******************************************************************/ /* initialize comment data */ -int xcddefault_initialize_comment_data(char *main_config_file) { - comment *temp_comment = NULL; +int xcddefault_initialize_comment_data(void) { + nagios_comment *temp_comment = NULL; /* find the new starting index for comment id if its missing*/ if(next_comment_id == 0L) { @@ -79,18 +58,6 @@ int xcddefault_initialize_comment_data(char *main_config_file) { } -/* removes invalid and old comments from the comment file */ -int xcddefault_cleanup_comment_data(char *main_config_file) { - - /* nothing to do anymore */ - - return OK; - } - - - - - /******************************************************************/ /***************** DEFAULT DATA OUTPUT FUNCTIONS ******************/ /******************************************************************/ @@ -106,9 +73,6 @@ int xcddefault_add_new_host_comment(int entry_type, char *host_name, time_t entr /* add comment to list in memory */ add_host_comment(entry_type, host_name, entry_time, author_name, comment_data, next_comment_id, persistent, expires, expire_time, source); - /* update comment file */ - xcddefault_save_comment_data(); - /* return the id for the comment we are about to add (this happens in the main code) */ if(comment_id != NULL) *comment_id = next_comment_id; @@ -130,9 +94,6 @@ int xcddefault_add_new_service_comment(int entry_type, char *host_name, char *sv /* add comment to list in memory */ add_service_comment(entry_type, host_name, svc_description, entry_time, author_name, comment_data, next_comment_id, persistent, expires, expire_time, source); - /* update comment file */ - xcddefault_save_comment_data(); - /* return the id for the comment we are about to add (this happens in the main code) */ if(comment_id != NULL) *comment_id = next_comment_id; @@ -142,45 +103,3 @@ int xcddefault_add_new_service_comment(int entry_type, char *host_name, char *sv return OK; } - - - -/******************************************************************/ -/**************** COMMENT DELETION FUNCTIONS **********************/ -/******************************************************************/ - - -/* deletes a host comment */ -int xcddefault_delete_host_comment(unsigned long comment_id) { - - /* update comment file */ - xcddefault_save_comment_data(); - - return OK; - } - - -/* deletes a service comment */ -int xcddefault_delete_service_comment(unsigned long comment_id) { - - /* update comment file */ - xcddefault_save_comment_data(); - - return OK; - } - - - -/******************************************************************/ -/****************** COMMENT OUTPUT FUNCTIONS **********************/ -/******************************************************************/ - -/* writes comment data to file */ -int xcddefault_save_comment_data(void) { - - /* don't update the status file now (too inefficent), let aggregated status updates do it */ - return OK; - } - -#endif - diff --git a/xdata/xcddefault.h b/xdata/xcddefault.h index cf6d72b..addd6cd 100644 --- a/xdata/xcddefault.h +++ b/xdata/xcddefault.h @@ -2,8 +2,6 @@ * * XCDDEFAULT.H - Header file for default comment data routines * - * Copyright (c) 2000-2006 Ethan Galstad (egalstad@nagios.org) - * Last Modified: 12-26-2006 * * License: * @@ -22,17 +20,9 @@ * *****************************************************************************/ -#ifndef _XCDDEFAULT_H -#define _XCDDEFAULT_H - -#ifdef NSCORE -int xcddefault_initialize_comment_data(char *); -int xcddefault_cleanup_comment_data(char *); -int xcddefault_save_comment_data(void); +#ifndef NAGIOS_XCDDEFAULT_H_INCLUDED +#define NAGIOS_XCDDEFAULT_H_INCLUDED +int xcddefault_initialize_comment_data(void); int xcddefault_add_new_host_comment(int, char *, time_t, char *, char *, int, int, int, time_t, unsigned long *); int xcddefault_add_new_service_comment(int, char *, char *, time_t, char *, char *, int, int, int, time_t, unsigned long *); -int xcddefault_delete_host_comment(unsigned long); -int xcddefault_delete_service_comment(unsigned long); -#endif - #endif diff --git a/xdata/xdddefault.c b/xdata/xdddefault.c deleted file mode 100644 index e6dc6c6..0000000 --- a/xdata/xdddefault.c +++ /dev/null @@ -1,294 +0,0 @@ -/***************************************************************************** - * - * XDDDEFAULT.C - Default scheduled downtime data routines for Nagios - * - * Copyright (c) 2001-2007 Ethan Galstad (egalstad@nagios.org) - * Last Modified: 09-04-2007 - * - * License: - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - *****************************************************************************/ - - -/*********** COMMON HEADER FILES ***********/ - -#include "../include/config.h" -#include "../include/common.h" -#include "../include/locations.h" -#include "../include/downtime.h" -#include "../include/macros.h" - -#ifdef NSCORE -#include "../include/objects.h" -#include "../include/nagios.h" -#endif - -#ifdef NSCGI -#include "../include/cgiutils.h" -#endif - - -/**** IMPLEMENTATION SPECIFIC HEADER FILES ****/ -#include "xdddefault.h" - - - -#ifdef NSCORE -extern unsigned long next_downtime_id; -extern scheduled_downtime *scheduled_downtime_list; -#endif - - - - -#ifdef NSCORE - - -/******************************************************************/ -/*********** DOWNTIME INITIALIZATION/CLEANUP FUNCTIONS ************/ -/******************************************************************/ - - -/* initialize downtime data */ -int xdddefault_initialize_downtime_data(char *main_config_file) { - scheduled_downtime *temp_downtime = NULL; - - /* clean up the old downtime data */ - xdddefault_validate_downtime_data(); - - /* find the new starting index for downtime id if its missing*/ - if(next_downtime_id == 0L) { - for(temp_downtime = scheduled_downtime_list; temp_downtime != NULL; temp_downtime = temp_downtime->next) { - if(temp_downtime->downtime_id >= next_downtime_id) - next_downtime_id = temp_downtime->downtime_id + 1; - } - } - - /* initialize next downtime id if necessary */ - if(next_downtime_id == 0L) - next_downtime_id = 1; - - return OK; - } - - - -/* removes invalid and old downtime entries from the downtime file */ -int xdddefault_validate_downtime_data(void) { - scheduled_downtime *temp_downtime; - scheduled_downtime *next_downtime; - int update_file = FALSE; - int save = TRUE; - - /* remove stale downtimes */ - for(temp_downtime = scheduled_downtime_list; temp_downtime != NULL; temp_downtime = next_downtime) { - - next_downtime = temp_downtime->next; - save = TRUE; - - /* delete downtimes with invalid host names */ - if(find_host(temp_downtime->host_name) == NULL) { - log_debug_info(DEBUGL_DOWNTIME, 1, - "Deleting downtime with invalid host name: %s\n", - temp_downtime->host_name); - save = FALSE; - } - - /* delete downtimes with invalid service descriptions */ - if(temp_downtime->type == SERVICE_DOWNTIME && find_service(temp_downtime->host_name, temp_downtime->service_description) == NULL) { - log_debug_info(DEBUGL_DOWNTIME, 1, - "Deleting downtime with invalid service description: %s\n", - temp_downtime->service_description); - save = FALSE; - } - - /* delete fixed downtimes that have expired */ - if((TRUE == temp_downtime->fixed) && - (temp_downtime->end_time < time(NULL))) { - log_debug_info(DEBUGL_DOWNTIME, 1, - "Deleting fixed downtime that expired at: %lu\n", - temp_downtime->end_time); - save = FALSE; - } - - /* delete flexible downtimes that never started and have expired */ - if((FALSE == temp_downtime->fixed) && - (0 == temp_downtime->flex_downtime_start) && - (temp_downtime->end_time < time(NULL))) { - log_debug_info(DEBUGL_DOWNTIME, 1, - "Deleting flexible downtime that expired at: %lu\n", - temp_downtime->end_time); - save = FALSE; - } - - /* delete flexible downtimes that started but whose duration - has completed */ - if((FALSE == temp_downtime->fixed) && - (0 != temp_downtime->flex_downtime_start) && - ((temp_downtime->flex_downtime_start + temp_downtime->duration) - < time(NULL))) { - log_debug_info(DEBUGL_DOWNTIME, 1, - "Deleting flexible downtime whose duration ended at: %lu\n", - temp_downtime->flex_downtime_start + temp_downtime->duration); - save = FALSE; - } - - /* delete the downtime */ - if(save == FALSE) { - update_file = TRUE; - delete_downtime(temp_downtime->type, temp_downtime->downtime_id); - } - } - - /* remove triggered downtimes without valid parents */ - for(temp_downtime = scheduled_downtime_list; temp_downtime != NULL; temp_downtime = next_downtime) { - - next_downtime = temp_downtime->next; - save = TRUE; - - if(temp_downtime->triggered_by == 0) - continue; - - if(find_host_downtime(temp_downtime->triggered_by) == NULL && find_service_downtime(temp_downtime->triggered_by) == NULL) - save = FALSE; - - /* delete the downtime */ - if(save == FALSE) { - update_file = TRUE; - delete_downtime(temp_downtime->type, temp_downtime->downtime_id); - } - } - - /* update downtime file */ - if(update_file == TRUE) - xdddefault_save_downtime_data(); - - return OK; - } - - - -/* removes invalid and old downtime entries from the downtime file */ -int xdddefault_cleanup_downtime_data(char *main_config_file) { - - /* we don't need to do any cleanup... */ - return OK; - } - - - -/******************************************************************/ -/************************ SAVE FUNCTIONS **************************/ -/******************************************************************/ - -/* adds a new scheduled host downtime entry */ -int xdddefault_add_new_host_downtime(char *host_name, time_t entry_time, char *author, char *comment, time_t start_time, time_t end_time, int fixed, unsigned long triggered_by, unsigned long duration, unsigned long *downtime_id, int is_in_effect, int start_notification_sent) { - - /* find the next valid downtime id */ - while(find_host_downtime(next_downtime_id) != NULL) - next_downtime_id++; - - /* add downtime to list in memory */ - add_host_downtime(host_name, entry_time, author, comment, start_time, (time_t)0, end_time, fixed, triggered_by, duration, next_downtime_id, is_in_effect, start_notification_sent); - - /* update downtime file */ - xdddefault_save_downtime_data(); - - /* return the id for the downtime we are about to add (this happens in the main code) */ - if(downtime_id != NULL) - *downtime_id = next_downtime_id; - - /* increment the downtime id */ - next_downtime_id++; - - return OK; - } - - - -/* adds a new scheduled service downtime entry */ -int xdddefault_add_new_service_downtime(char *host_name, char *service_description, time_t entry_time, char *author, char *comment, time_t start_time, time_t end_time, int fixed, unsigned long triggered_by, unsigned long duration, unsigned long *downtime_id, int is_in_effect, int start_notification_sent) { - - /* find the next valid downtime id */ - while(find_service_downtime(next_downtime_id) != NULL) - next_downtime_id++; - - /* add downtime to list in memory */ - add_service_downtime(host_name, service_description, entry_time, author, comment, start_time, (time_t)0, end_time, fixed, triggered_by, duration, next_downtime_id, is_in_effect, start_notification_sent); - - /* update downtime file */ - xdddefault_save_downtime_data(); - - /* return the id for the downtime we are about to add (this happens in the main code) */ - if(downtime_id != NULL) - *downtime_id = next_downtime_id; - - /* increment the downtime id */ - next_downtime_id++; - - return OK; - } - - -/******************************************************************/ -/********************** DELETION FUNCTIONS ************************/ -/******************************************************************/ - -/* deletes a scheduled host downtime entry */ -int xdddefault_delete_host_downtime(unsigned long downtime_id) { - int result; - - result = xdddefault_delete_downtime(HOST_DOWNTIME, downtime_id); - - return result; - } - - -/* deletes a scheduled service downtime entry */ -int xdddefault_delete_service_downtime(unsigned long downtime_id) { - int result; - - result = xdddefault_delete_downtime(SERVICE_DOWNTIME, downtime_id); - - return result; - } - - -/* deletes a scheduled host or service downtime entry */ -int xdddefault_delete_downtime(int type, unsigned long downtime_id) { - - /* rewrite the downtime file (downtime was already removed from memory) */ - xdddefault_save_downtime_data(); - - return OK; - } - - - -/******************************************************************/ -/****************** DOWNTIME OUTPUT FUNCTIONS *********************/ -/******************************************************************/ - -/* writes downtime data to file */ -int xdddefault_save_downtime_data(void) { - - /* don't update the status file now (too inefficent), let aggregated status updates do it */ - return OK; - } - -#endif - - diff --git a/xdata/xdddefault.h b/xdata/xdddefault.h deleted file mode 100644 index fa5e708..0000000 --- a/xdata/xdddefault.h +++ /dev/null @@ -1,47 +0,0 @@ -/***************************************************************************** - * - * XDDDEFAULT.H - Header file for default scheduled downtime data routines - * - * Copyright (c) 2001-2006 Ethan Galstad (egalstad@nagios.org) - * Last Modified: 03-01-2006 - * - * License: - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - *****************************************************************************/ - -#ifndef _XDDDEFAULT_H -#define _XDDDEFAULT_H - -#define XDDDEFAULT_NO_DATA 0 -#define XDDDEFAULT_INFO_DATA 1 -#define XDDDEFAULT_HOST_DATA 2 -#define XDDDEFAULT_SERVICE_DATA 3 - -#ifdef NSCORE -int xdddefault_initialize_downtime_data(char *); -int xdddefault_validate_downtime_data(void); -int xdddefault_cleanup_downtime_data(char *); - -int xdddefault_save_downtime_data(void); -int xdddefault_add_new_host_downtime(char *, time_t, char *, char *, time_t, time_t, int, unsigned long, unsigned long, unsigned long *, int, int); -int xdddefault_add_new_service_downtime(char *, char *, time_t, char *, char *, time_t, time_t, int, unsigned long, unsigned long, unsigned long *, int, int); - -int xdddefault_delete_host_downtime(unsigned long); -int xdddefault_delete_service_downtime(unsigned long); -int xdddefault_delete_downtime(int, unsigned long); -#endif - -#endif diff --git a/xdata/xodtemplate.c b/xdata/xodtemplate.c index 58eac00..66a683b 100644 --- a/xdata/xodtemplate.c +++ b/xdata/xodtemplate.c @@ -2,8 +2,6 @@ * * XODTEMPLATE.C - Template-based object configuration data input routines * - * Copyright (c) 2001-2009 Ethan Galstad (egalstad@nagios.org) - * Last Modified: 01-01-2009 * * Description: * @@ -52,7 +50,6 @@ #include "../include/objects.h" #include "../include/locations.h" #include "../include/macros.h" -#include "../include/skiplist.h" /**** CORE OR CGI SPECIFIC HEADER FILES ****/ @@ -68,14 +65,10 @@ #include "xodtemplate.h" - -#ifdef NSCORE -extern int use_regexp_matches; -extern int use_true_regexp_matching; -extern int verify_config; -extern int test_scheduling; -extern int use_precached_objects; -#endif +#define XOD_NEW 0 /* not seen */ +#define XOD_SEEN 1 /* seen, but not yet loopy */ +#define XOD_LOOPY 2 /* loopy */ +#define XOD_OK 3 /* not loopy */ xodtemplate_timeperiod *xodtemplate_timeperiod_list = NULL; xodtemplate_command *xodtemplate_command_list = NULL; @@ -118,32 +111,58 @@ int xodtemplate_current_object_type = XODTEMPLATE_NONE; int xodtemplate_current_config_file = 0; char **xodtemplate_config_files = NULL; -char *xodtemplate_cache_file = NULL; -char *xodtemplate_precache_file = NULL; - int presorted_objects = FALSE; -extern int allow_empty_hostgroup_assignment; +/* xodtemplate id / object counter */ +static struct object_count xodcount; + +/* reusable bitmaps for expanding objects */ +static bitmap *host_map = NULL, *contact_map = NULL; +static bitmap *service_map = NULL, *parent_map = NULL; + +/* These variables are defined in base/utils.c, but as CGIs do not need these + we just fake the values for this file */ +#ifdef NSCGI +#define use_precached_objects TRUE +#define use_regexp_matches FALSE +#define use_true_regexp_matching FALSE +#define test_scheduling FALSE +#endif /* - * Macro magic used to determine if a service is assigned - * via hostgroup_name or host_name. Those assigned via host_name - * take precedence. + * simple inheritance macros. o = object, t = template, v = variable + * Note that these can be used for inter-object inheritance as well, + * so long as the variable names are identical. */ -#define X_SERVICE_IS_FROM_HOSTGROUP (1 << 1) /* flag to know if service come from a hostgroup def, apply on srv->have_initial_state */ -#define xodtemplate_set_service_is_from_hostgroup(srv) \ - srv->have_initial_state |= X_SERVICE_IS_FROM_HOSTGROUP -#define xodtemplate_unset_service_is_from_hostgroup(srv) \ - srv->have_initial_state &= ~X_SERVICE_IS_FROM_HOSTGROUP -#define xodtemplate_is_service_is_from_hostgroup(srv) \ - ((srv->have_initial_state & X_SERVICE_IS_FROM_HOSTGROUP) != 0) +#define xod_inherit(o, t, v) \ + do { \ + if(o->have_##v == FALSE && t->have_##v == TRUE) { \ + o->v = t->v; \ + o->have_##v = TRUE; \ + } \ + } while(0) + +#define xod_inherit_str_nohave(o, t, v) \ + do { \ + if(o->v == NULL && t->v != NULL) { \ + o->v = (char *)strdup(t->v); \ + } \ + } while(0) + +#define xod_inherit_str(o, t, v) \ + do { \ + if(o->have_##v == FALSE && t->have_##v == TRUE) { \ + xod_inherit_str_nohave(o, t, v); \ + o->have_##v = TRUE; \ + } \ + } while(0) /* returns the name of a numbered config file */ -static char *xodtemplate_config_file_name(int config_file) { - if(config_file <= xodtemplate_current_config_file) - return xodtemplate_config_files[config_file - 1]; +static const char *xodtemplate_config_file_name(int cfgfile) { + if(cfgfile <= xodtemplate_current_config_file) + return xodtemplate_config_files[cfgfile - 1]; return "?"; } @@ -154,18 +173,28 @@ static char *xodtemplate_config_file_name(int config_file) { /************* TOP-LEVEL CONFIG DATA INPUT FUNCTION ***************/ /******************************************************************/ +#ifndef NSCGI +static void xodtemplate_free_template_skiplists(void) { + int x = 0; + + for(x = 0; x < NUM_XOBJECT_SKIPLISTS; x++) { + skiplist_free(&xobject_template_skiplists[x]); + } + } +#endif + /* process all config files - both core and CGIs pass in name of main config file */ -int xodtemplate_read_config_data(char *main_config_file, int options, int cache, int precache) { +int xodtemplate_read_config_data(const char *main_config_file, int options) { #ifdef NSCORE - char *config_file = NULL; + char *cfgfile = NULL; char *config_base_dir = NULL; char *input = NULL; char *var = NULL; char *val = NULL; - struct timeval tv[14]; - double runtime[14]; + double runtime[11]; mmapfile *thefile = NULL; #endif + struct timeval tv[12]; int result = OK; @@ -176,8 +205,7 @@ int xodtemplate_read_config_data(char *main_config_file, int options, int cache, return ERROR; } - /* get variables from main config file */ - xodtemplate_grab_config_info(main_config_file); + timing_point("Reading config data from '%s'\n", main_config_file); /* initialize variables */ xodtemplate_timeperiod_list = NULL; @@ -203,7 +231,7 @@ int xodtemplate_read_config_data(char *main_config_file, int options, int cache, /* allocate memory for 256 config files (increased dynamically) */ xodtemplate_current_config_file = 0; - xodtemplate_config_files = (char **)malloc(256 * sizeof(char **)); + xodtemplate_config_files = (char **)malloc(256 * sizeof(char *)); if(xodtemplate_config_files == NULL) { #ifdef NSCORE printf("Unable to allocate memory!\n"); @@ -223,29 +251,24 @@ int xodtemplate_read_config_data(char *main_config_file, int options, int cache, /* only process the precached object file as long as we're not regenerating it and we're not verifying the config */ if(use_precached_objects == TRUE) - result = xodtemplate_process_config_file(xodtemplate_precache_file, options); + result = xodtemplate_process_config_file(object_precache_file, options); /* process object config files normally... */ else { - /* determine the directory of the main config file */ - if((config_file = (char *)strdup(main_config_file)) == NULL) { + if((cfgfile = (char *)strdup(main_config_file)) == NULL) { my_free(xodtemplate_config_files); -#ifdef NSCORE printf("Unable to allocate memory!\n"); -#endif return ERROR; } - config_base_dir = (char *)strdup(dirname(config_file)); - my_free(config_file); + config_base_dir = (char *)strdup(dirname(cfgfile)); + my_free(cfgfile); /* open the main config file for reading (we need to find all the config files to read) */ if((thefile = mmap_fopen(main_config_file)) == NULL) { my_free(config_base_dir); my_free(xodtemplate_config_files); -#ifdef NSCORE printf("Unable to open main config file '%s'\n", main_config_file); -#endif return ERROR; } @@ -277,15 +300,15 @@ int xodtemplate_read_config_data(char *main_config_file, int options, int cache, if(!strcmp(var, "xodtemplate_config_file") || !strcmp(var, "cfg_file")) { if(config_base_dir != NULL && val[0] != '/') { - asprintf(&config_file, "%s/%s", config_base_dir, val); + asprintf(&cfgfile, "%s/%s", config_base_dir, val); } else - config_file = strdup(val); + cfgfile = strdup(val); /* process the config file... */ - result = xodtemplate_process_config_file(config_file, options); + result = xodtemplate_process_config_file(cfgfile, options); - my_free(config_file); + my_free(cfgfile); /* if there was an error processing the config file, break out of loop */ if(result == ERROR) @@ -296,19 +319,19 @@ int xodtemplate_read_config_data(char *main_config_file, int options, int cache, else if(!strcmp(var, "xodtemplate_config_dir") || !strcmp(var, "cfg_dir")) { if(config_base_dir != NULL && val[0] != '/') { - asprintf(&config_file, "%s/%s", config_base_dir, val); + asprintf(&cfgfile, "%s/%s", config_base_dir, val); } else - config_file = strdup(val); + cfgfile = strdup(val); /* strip trailing / if necessary */ - if(config_file != NULL && config_file[strlen(config_file) - 1] == '/') - config_file[strlen(config_file) - 1] = '\x0'; + if(cfgfile != NULL && cfgfile[strlen(cfgfile) - 1] == '/') + cfgfile[strlen(cfgfile) - 1] = '\x0'; /* process the config directory... */ - result = xodtemplate_process_config_dir(config_file, options); + result = xodtemplate_process_config_dir(cfgfile, options); - my_free(config_file); + my_free(cfgfile); /* if there was an error processing the config file, break out of loop */ if(result == ERROR) @@ -328,8 +351,9 @@ int xodtemplate_read_config_data(char *main_config_file, int options, int cache, #ifdef NSCGI /* CGIs process only one file - the cached objects file */ - result = xodtemplate_process_config_file(xodtemplate_cache_file, options); + result = xodtemplate_process_config_file(object_cache_file, options); #endif + timing_point("Done parsing config files\n"); #ifdef NSCORE @@ -339,33 +363,64 @@ int xodtemplate_read_config_data(char *main_config_file, int options, int cache, /* resolve objects definitions */ if(result == OK) result = xodtemplate_resolve_objects(); + timing_point("Done resolving objects\n"); + + /* these are no longer needed */ + xodtemplate_free_template_skiplists(); + if(test_scheduling == TRUE) gettimeofday(&tv[2], NULL); /* cleanup some additive inheritance stuff... */ xodtemplate_clean_additive_strings(); + } +#endif - /* do the meat and potatoes stuff... */ - if(result == OK) - result = xodtemplate_recombobulate_contactgroups(); - if(test_scheduling == TRUE) - gettimeofday(&tv[3], NULL); + /* do the meat and potatoes stuff... */ + host_map = bitmap_create(xodcount.hosts); + contact_map = bitmap_create(xodcount.contacts); + if(!host_map || !contact_map) { + logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Failed to create bitmaps for resolving objects\n"); + return ERROR; + } - if(result == OK) - result = xodtemplate_recombobulate_hostgroups(); - if(test_scheduling == TRUE) - gettimeofday(&tv[4], NULL); + if(result == OK) + result = xodtemplate_recombobulate_contactgroups(); + if(test_scheduling == TRUE) + gettimeofday(&tv[3], NULL); + timing_point("Done recombobulating contactgroups\n"); + if(result == OK) + result = xodtemplate_recombobulate_hostgroups(); + if(test_scheduling == TRUE) + gettimeofday(&tv[4], NULL); + timing_point("Done recombobulating hostgroups\n"); + +#ifndef NSCGI + if(use_precached_objects == FALSE) { if(result == OK) result = xodtemplate_duplicate_services(); if(test_scheduling == TRUE) gettimeofday(&tv[5], NULL); + timing_point("Created %u services (dupes possible)\n", xodcount.services); + } +#endif - if(result == OK) - result = xodtemplate_recombobulate_servicegroups(); - if(test_scheduling == TRUE) - gettimeofday(&tv[6], NULL); + /* now we have an accurate service count */ + service_map = bitmap_create(xodcount.services); + if(!service_map) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Failed to create service map\n"); + return ERROR; + } + if(result == OK) + result = xodtemplate_recombobulate_servicegroups(); + if(test_scheduling == TRUE) + gettimeofday(&tv[6], NULL); + timing_point("Done recombobulating servicegroups\n"); + +#ifndef NSCGI + if(use_precached_objects == FALSE) { if(result == OK) result = xodtemplate_duplicate_objects(); if(test_scheduling == TRUE) @@ -374,62 +429,31 @@ int xodtemplate_read_config_data(char *main_config_file, int options, int cache, /* NOTE: some missing defaults (notification options, etc.) are also applied here */ if(result == OK) result = xodtemplate_inherit_object_properties(); + timing_point("Done propagating inherited object properties\n"); if(test_scheduling == TRUE) gettimeofday(&tv[8], NULL); - - if(result == OK) - result = xodtemplate_recombobulate_object_contacts(); - if(test_scheduling == TRUE) - gettimeofday(&tv[9], NULL); - - /* sort objects */ - if(result == OK) - result = xodtemplate_sort_objects(); - if(test_scheduling == TRUE) - gettimeofday(&tv[10], NULL); - } - - if(result == OK) { - - /* merge host/service extinfo definitions with host/service definitions */ - /* this will be removed in Nagios 4.x */ - xodtemplate_merge_extinfo_ojects(); - - /* cache object definitions for the CGIs and external apps */ - if(cache == TRUE) - xodtemplate_cache_objects(xodtemplate_cache_file); - - /* precache object definitions for future runs */ - if(precache == TRUE) - xodtemplate_cache_objects(xodtemplate_precache_file); } +#endif if(test_scheduling == TRUE) - gettimeofday(&tv[11], NULL); + gettimeofday(&tv[9], NULL); -#endif /* register objects */ - if(result == OK) - result = xodtemplate_register_objects(); -#ifdef NSCORE + +/* Commented out because functions above (xodtemplate_duplicate_objects + in this particular case) return an error without printing any error + messages, so nothing will say what was wrong. */ +/* if(result == OK) */ + result |= xodtemplate_register_objects(); if(test_scheduling == TRUE) - gettimeofday(&tv[12], NULL); -#endif + gettimeofday(&tv[10], NULL); /* cleanup */ xodtemplate_free_memory(); -#ifdef NSCORE - if(test_scheduling == TRUE) - gettimeofday(&tv[13], NULL); -#endif - - /* free memory */ - my_free(xodtemplate_cache_file); - my_free(xodtemplate_precache_file); - #ifdef NSCORE if(test_scheduling == TRUE) { + gettimeofday(&tv[11], NULL); runtime[0] = (double)((double)(tv[1].tv_sec - tv[0].tv_sec) + (double)((tv[1].tv_usec - tv[0].tv_usec) / 1000.0) / 1000.0); if(use_precached_objects == FALSE) { @@ -440,10 +464,7 @@ int xodtemplate_read_config_data(char *main_config_file, int options, int cache, runtime[5] = (double)((double)(tv[6].tv_sec - tv[5].tv_sec) + (double)((tv[6].tv_usec - tv[5].tv_usec) / 1000.0) / 1000.0); runtime[6] = (double)((double)(tv[7].tv_sec - tv[6].tv_sec) + (double)((tv[7].tv_usec - tv[6].tv_usec) / 1000.0) / 1000.0); runtime[7] = (double)((double)(tv[8].tv_sec - tv[7].tv_sec) + (double)((tv[8].tv_usec - tv[7].tv_usec) / 1000.0) / 1000.0); - runtime[8] = (double)((double)(tv[9].tv_sec - tv[8].tv_sec) + (double)((tv[9].tv_usec - tv[8].tv_usec) / 1000.0) / 1000.0); - runtime[9] = (double)((double)(tv[10].tv_sec - tv[9].tv_sec) + (double)((tv[10].tv_usec - tv[9].tv_usec) / 1000.0) / 1000.0); - runtime[10] = (double)((double)(tv[11].tv_sec - tv[10].tv_sec) + (double)((tv[11].tv_usec - tv[10].tv_usec) / 1000.0) / 1000.0); - runtime[11] = (double)((double)(tv[12].tv_sec - tv[11].tv_sec) + (double)((tv[12].tv_usec - tv[11].tv_usec) / 1000.0) / 1000.0); + runtime[8] = (double)((double)(tv[10].tv_sec - tv[9].tv_sec) + (double)((tv[10].tv_usec - tv[9].tv_usec) / 1000.0) / 1000.0); } else { runtime[1] = 0.0; @@ -453,13 +474,10 @@ int xodtemplate_read_config_data(char *main_config_file, int options, int cache, runtime[5] = 0.0; runtime[6] = 0.0; runtime[7] = 0.0; - runtime[8] = 0.0; - runtime[9] = 0.0; - runtime[10] = 0.0; - runtime[11] = (double)((double)(tv[12].tv_sec - tv[1].tv_sec) + (double)((tv[12].tv_usec - tv[1].tv_usec) / 1000.0) / 1000.0); + runtime[8] = (double)((double)(tv[10].tv_sec - tv[1].tv_sec) + (double)((tv[10].tv_usec - tv[1].tv_usec) / 1000.0) / 1000.0); } - runtime[12] = (double)((double)(tv[13].tv_sec - tv[12].tv_sec) + (double)((tv[13].tv_usec - tv[12].tv_usec) / 1000.0) / 1000.0); - runtime[13] = (double)((double)(tv[13].tv_sec - tv[0].tv_sec) + (double)((tv[13].tv_usec - tv[0].tv_usec) / 1000.0) / 1000.0); + runtime[9] = (double)((double)(tv[11].tv_sec - tv[10].tv_sec) + (double)((tv[11].tv_usec - tv[10].tv_usec) / 1000.0) / 1000.0); + runtime[10] = (double)((double)(tv[11].tv_sec - tv[0].tv_sec) + (double)((tv[11].tv_usec - tv[0].tv_usec) / 1000.0) / 1000.0); printf("Timing information on object configuration processing is listed\n"); printf("below. You can use this information to see if precaching your\n"); @@ -477,97 +495,25 @@ int xodtemplate_read_config_data(char *main_config_file, int options, int cache, printf("Recomb Servicegroups: %.6lf sec *\n", runtime[5]); printf("Duplicate: %.6lf sec *\n", runtime[6]); printf("Inherit: %.6lf sec *\n", runtime[7]); - printf("Recomb Contacts: %.6lf sec *\n", runtime[8]); - printf("Sort: %.6lf sec *\n", runtime[9]); - /* printf("Cache: %.6lf sec\n",runtime[10]);*/ - printf("Register: %.6lf sec\n", runtime[11]); - printf("Free: %.6lf sec\n", runtime[12]); + printf("Register: %.6lf sec\n", runtime[8]); + printf("Free: %.6lf sec\n", runtime[9]); printf(" ============\n"); - printf("TOTAL: %.6lf sec ", runtime[13]); + printf("TOTAL: %.6lf sec ", runtime[10]); if(use_precached_objects == FALSE) - printf("* = %.6lf sec (%.2f%%) estimated savings", runtime[13] - runtime[12] - runtime[11] - runtime[0], ((runtime[13] - runtime[12] - runtime[11] - runtime[0]) / runtime[13]) * 100.0); + printf("* = %.6lf sec (%.2f%%) estimated savings", (runtime[10] - runtime[9] - runtime[8] - runtime[0]) / 4, ((runtime[10] - runtime[9] - runtime[8] - runtime[0]) / runtime[10]) * 25.0); printf("\n"); printf("\n\n"); } #endif + bitmap_destroy(contact_map); + bitmap_destroy(host_map); + bitmap_destroy(service_map); + return result; } - -/* grab config variable from main config file */ -int xodtemplate_grab_config_info(char *main_config_file) { - char *input = NULL; - char *var = NULL; - char *val = NULL; - mmapfile *thefile = NULL; -#ifdef NSCORE - nagios_macros *mac; -#endif - - /* open the main config file for reading */ - if((thefile = mmap_fopen(main_config_file)) == NULL) - return ERROR; - - /* read in all lines from the main config file */ - while(1) { - - /* free memory */ - my_free(input); - - /* read the next line */ - if((input = mmap_fgets_multiline(thefile)) == NULL) - break; - - /* strip input */ - strip(input); - - /* skip blank lines and comments */ - if(input[0] == '#' || input[0] == ';' || input[0] == '\x0') - continue; - - if((var = strtok(input, "=")) == NULL) - continue; - - if((val = strtok(NULL, "\n")) == NULL) - continue; - - /* cached object file definition (overrides default location) */ - if(!strcmp(var, "object_cache_file")) - xodtemplate_cache_file = (char *)strdup(val); - - /* pre-cached object file definition */ - if(!strcmp(var, "precached_object_file")) - xodtemplate_precache_file = (char *)strdup(val); - } - - /* close the file */ - mmap_fclose(thefile); - - /* default locations */ - if(xodtemplate_cache_file == NULL) - xodtemplate_cache_file = (char *)strdup(DEFAULT_OBJECT_CACHE_FILE); - if(xodtemplate_precache_file == NULL) - xodtemplate_precache_file = (char *)strdup(DEFAULT_PRECACHED_OBJECT_FILE); - - /* make sure we have what we need */ - if(xodtemplate_cache_file == NULL || xodtemplate_precache_file == NULL) - return ERROR; - -#ifdef NSCORE - mac = get_global_macros(); - /* save the object cache file macro */ - my_free(mac->x[MACRO_OBJECTCACHEFILE]); - if((mac->x[MACRO_OBJECTCACHEFILE] = (char *)strdup(xodtemplate_cache_file))) - strip(mac->x[MACRO_OBJECTCACHEFILE]); -#endif - - return OK; - } - - - /* process all files in a specific config directory */ int xodtemplate_process_config_dir(char *dirname, int options) { char file[MAX_FILENAME_LENGTH]; @@ -578,7 +524,7 @@ int xodtemplate_process_config_dir(char *dirname, int options) { struct stat stat_buf; #ifdef NSCORE - if(verify_config == TRUE) + if(verify_config >= 2) printf("Processing object config directory '%s'...\n", dirname); #endif @@ -660,7 +606,7 @@ int xodtemplate_process_config_file(char *filename, int options) { #ifdef NSCORE - if(verify_config == TRUE) + if(verify_config >= 2) printf("Processing object config file '%s'...\n", filename); #endif @@ -669,7 +615,7 @@ int xodtemplate_process_config_file(char *filename, int options) { /* reallocate memory for config files */ if(!(xodtemplate_current_config_file % 256)) { - xodtemplate_config_files = (char **)realloc(xodtemplate_config_files, (xodtemplate_current_config_file + 256) * sizeof(char **)); + xodtemplate_config_files = (char **)realloc(xodtemplate_config_files, (xodtemplate_current_config_file + 256) * sizeof(char *)); if(xodtemplate_config_files == NULL) return ERROR; } @@ -733,10 +679,13 @@ int xodtemplate_process_config_file(char *filename, int options) { } /* check validity of object type */ - if(strcmp(input, "timeperiod") && strcmp(input, "command") && strcmp(input, "contact") && strcmp(input, "contactgroup") && strcmp(input, "host") && strcmp(input, "hostgroup") && strcmp(input, "servicegroup") && strcmp(input, "service") && strcmp(input, "servicedependency") && strcmp(input, "serviceescalation") && strcmp(input, "hostgroupescalation") && strcmp(input, "hostdependency") && strcmp(input, "hostescalation") && strcmp(input, "hostextinfo") && strcmp(input, "serviceextinfo")) { - logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Invalid object definition type '%s' in file '%s' on line %d.\n", input, filename, current_line); - result = ERROR; - break; + if(strcmp(input, "timeperiod") && strcmp(input, "command") && strcmp(input, "contact") && strcmp(input, "contactgroup") && strcmp(input, "host") && strcmp(input, "hostgroup") && strcmp(input, "servicegroup") && strcmp(input, "service") && strcmp(input, "servicedependency") && strcmp(input, "serviceescalation") && strcmp(input, "hostgroupescalation") && strcmp(input, "hostdependency") && strcmp(input, "hostescalation")) { + if(strcmp(input, "hostextinfo") && strcmp(input, "serviceextinfo")) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Invalid object definition type '%s' in file '%s' on line %d.\n", input, filename, current_line); + result = ERROR; + break; + } + logit(NSLOG_CONFIG_WARNING, TRUE, "WARNING: Extinfo objects are deprecated and will be removed in future versions\n"); } /* we're already in an object definition... */ @@ -766,7 +715,7 @@ int xodtemplate_process_config_file(char *filename, int options) { /* close out current definition */ if(xodtemplate_end_object_definition(options) == ERROR) { - logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not complete object definition in file '%s' on line %d.\n", filename, current_line); + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not complete object definition in file '%s' on line %d. Have you named all your objects?\n", filename, current_line); result = ERROR; break; } @@ -849,7 +798,7 @@ int xodtemplate_process_config_file(char *filename, int options) { if (new_##type == NULL) \ return ERROR; \ new_##type->register_object=TRUE; \ - new_##type->_config_file=config_file; \ + new_##type->_config_file=cfgfile; \ new_##type->_start_line=start_line; \ \ /* precached object files are already sorted, so add to tail */ \ @@ -876,7 +825,7 @@ int xodtemplate_process_config_file(char *filename, int options) { } while (0) /* starts a new object definition */ -int xodtemplate_begin_object_definition(char *input, int options, int config_file, int start_line) { +int xodtemplate_begin_object_definition(char *input, int options, int cfgfile, int start_line) { int result = OK; xodtemplate_timeperiod *new_timeperiod = NULL; xodtemplate_command *new_command = NULL; @@ -1026,6 +975,7 @@ int xodtemplate_begin_object_definition(char *input, int options, int config_fil case XODTEMPLATE_CONTACT: xod_begin_def(contact); + new_contact->minimum_value = 0; new_contact->host_notifications_enabled = TRUE; new_contact->service_notifications_enabled = TRUE; new_contact->can_submit_commands = TRUE; @@ -1035,21 +985,20 @@ int xodtemplate_begin_object_definition(char *input, int options, int config_fil case XODTEMPLATE_HOST: xod_begin_def(host); + + new_host->hourly_value = 0; new_host->check_interval = 5.0; new_host->retry_interval = 1.0; new_host->active_checks_enabled = TRUE; new_host->passive_checks_enabled = TRUE; - new_host->obsess_over_host = TRUE; + new_host->obsess = TRUE; new_host->max_check_attempts = -2; new_host->event_handler_enabled = TRUE; new_host->flap_detection_enabled = TRUE; - new_host->flap_detection_on_up = TRUE; - new_host->flap_detection_on_down = TRUE; - new_host->flap_detection_on_unreachable = TRUE; + new_host->flap_detection_options = OPT_ALL; new_host->notifications_enabled = TRUE; new_host->notification_interval = 30.0; new_host->process_perf_data = TRUE; - new_host->failure_prediction_enabled = TRUE; new_host->x_2d = -1; new_host->y_2d = -1; new_host->retain_status_information = TRUE; @@ -1059,6 +1008,7 @@ int xodtemplate_begin_object_definition(char *input, int options, int config_fil case XODTEMPLATE_SERVICE: xod_begin_def(service); + new_service->hourly_value = 0; new_service->initial_state = STATE_OK; new_service->max_check_attempts = -2; new_service->check_interval = 5.0; @@ -1066,22 +1016,18 @@ int xodtemplate_begin_object_definition(char *input, int options, int config_fil new_service->active_checks_enabled = TRUE; new_service->passive_checks_enabled = TRUE; new_service->parallelize_check = TRUE; - new_service->obsess_over_service = TRUE; + new_service->obsess = TRUE; new_service->event_handler_enabled = TRUE; new_service->flap_detection_enabled = TRUE; - new_service->flap_detection_on_ok = TRUE; - new_service->flap_detection_on_warning = TRUE; - new_service->flap_detection_on_unknown = TRUE; - new_service->flap_detection_on_critical = TRUE; + new_service->flap_detection_options = OPT_ALL; new_service->notifications_enabled = TRUE; new_service->notification_interval = 30.0; new_service->process_perf_data = TRUE; - new_service->failure_prediction_enabled = TRUE; new_service->retain_status_information = TRUE; new_service->retain_nonstatus_information = TRUE; - /* true service, so is not from host group, must be set AFTER have_initial_state*/ - xodtemplate_unset_service_is_from_hostgroup(new_service); + /* true service, so is not from host group */ + new_service->is_from_hostgroup = 0; break; case XODTEMPLATE_HOSTDEPENDENCY: @@ -1114,6 +1060,24 @@ int xodtemplate_begin_object_definition(char *input, int options, int config_fil } #undef xod_begin_def /* we don't need this anymore */ +static const char *xodtemplate_type_name(unsigned int id) { + static const char *otype_name[] = { + "NONE", "timeperiod", "command", "contact", "contactgroup", + "host", "hostgroup", "service", "servicedependency", + "serviceescalation", "hostescalation", "hostdependency", + "hostextinfo", "serviceextinfo", "servicegroup" + }; + if (id > ARRAY_SIZE(otype_name)) + return otype_name[0]; + return otype_name[id]; + + } + +static void xodtemplate_obsoleted(const char *var, int start_line) { + logit(NSLOG_CONFIG_WARNING, TRUE, "Warning: %s is obsoleted and no longer has any effect in %s type objects (config file '%s', starting at line %d)\n", + var, xodtemplate_type_name(xodtemplate_current_object_type), + xodtemplate_config_file_name(xodtemplate_current_config_file), start_line); + } /* adds a property to an object definition */ int xodtemplate_add_object_property(char *input, int options) { @@ -1137,9 +1101,7 @@ int xodtemplate_add_object_property(char *input, int options) { xodtemplate_hostescalation *temp_hostescalation = NULL; xodtemplate_hostextinfo *temp_hostextinfo = NULL; xodtemplate_serviceextinfo *temp_serviceextinfo = NULL; - register int x = 0; - register int y = 0; - int force_skiplists = FALSE; + int x, lth, force_skiplists = FALSE; /* should some object definitions be added to skiplists immediately? */ @@ -1214,24 +1176,26 @@ int xodtemplate_add_object_property(char *input, int options) { } /* get variable name */ - if((variable = (char *)strdup(input)) == NULL) - return ERROR; - /* trim at first whitespace occurance */ - for(x = 0, y = 0; variable[x] != '\x0'; x++) { - if(variable[x] == ' ' || variable[x] == '\t') + variable = input; + lth = strlen(variable); + /* trim at first whitespace occurrence */ + for(x = 0; variable[x] != '\x0'; x++) { + if(variable[x] == ' ' || variable[x] == '\t') { + variable[x] = 0; break; - y++; + } } - variable[y] = '\x0'; /* get variable value */ - if((value = (char *)strdup(input + x)) == NULL) { - my_free(variable); - return ERROR; - } + if (x == lth) + value = ""; + else + value = input + x + 1; + while (*value == ' ' || *value == '\t') + value++; + /* now strip trailing spaces */ strip(value); - switch(xodtemplate_current_object_type) { case XODTEMPLATE_TIMEPERIOD: @@ -1249,7 +1213,7 @@ int xodtemplate_add_object_property(char *input, int options) { if(result == OK) { /* add timeperiod to template skiplist for fast searches */ - result = skiplist_insert(xobject_template_skiplists[X_TIMEPERIOD_SKIPLIST], (void *)temp_timeperiod); + result = skiplist_insert(xobject_template_skiplists[TIMEPERIOD_SKIPLIST], (void *)temp_timeperiod); switch(result) { case SKIPLIST_ERROR_DUPLICATE: logit(NSLOG_CONFIG_WARNING, TRUE, "Warning: Duplicate definition found for timeperiod '%s' (config file '%s', starting on line %d)\n", value, xodtemplate_config_file_name(temp_timeperiod->_config_file), temp_timeperiod->_start_line); @@ -1270,7 +1234,7 @@ int xodtemplate_add_object_property(char *input, int options) { if(result == OK) { /* add timeperiod to template skiplist for fast searches */ - result = skiplist_insert(xobject_skiplists[X_TIMEPERIOD_SKIPLIST], (void *)temp_timeperiod); + result = skiplist_insert(xobject_skiplists[TIMEPERIOD_SKIPLIST], (void *)temp_timeperiod); switch(result) { case SKIPLIST_ERROR_DUPLICATE: logit(NSLOG_CONFIG_WARNING, TRUE, "Warning: Duplicate definition found for timeperiod '%s' (config file '%s', starting on line %d)\n", value, xodtemplate_config_file_name(temp_timeperiod->_config_file), temp_timeperiod->_start_line); @@ -1314,13 +1278,12 @@ int xodtemplate_add_object_property(char *input, int options) { result = ERROR; } else if(!strcmp(variable, "name")) { - if((temp_command->name = (char *)strdup(value)) == NULL) result = ERROR; if(result == OK) { /* add command to template skiplist for fast searches */ - result = skiplist_insert(xobject_template_skiplists[X_COMMAND_SKIPLIST], (void *)temp_command); + result = skiplist_insert(xobject_template_skiplists[COMMAND_SKIPLIST], (void *)temp_command); switch(result) { case SKIPLIST_ERROR_DUPLICATE: logit(NSLOG_CONFIG_WARNING, TRUE, "Warning: Duplicate definition found for command '%s' (config file '%s', starting on line %d)\n", value, xodtemplate_config_file_name(temp_command->_config_file), temp_command->_start_line); @@ -1341,7 +1304,7 @@ int xodtemplate_add_object_property(char *input, int options) { if(result == OK) { /* add command to template skiplist for fast searches */ - result = skiplist_insert(xobject_skiplists[X_COMMAND_SKIPLIST], (void *)temp_command); + result = skiplist_insert(xobject_skiplists[COMMAND_SKIPLIST], (void *)temp_command); switch(result) { case SKIPLIST_ERROR_DUPLICATE: logit(NSLOG_CONFIG_WARNING, TRUE, "Warning: Duplicate definition found for command '%s' (config file '%s', starting on line %d)\n", value, xodtemplate_config_file_name(temp_command->_config_file), temp_command->_start_line); @@ -1384,7 +1347,7 @@ int xodtemplate_add_object_property(char *input, int options) { if(result == OK) { /* add contactgroup to template skiplist for fast searches */ - result = skiplist_insert(xobject_template_skiplists[X_CONTACTGROUP_SKIPLIST], (void *)temp_contactgroup); + result = skiplist_insert(xobject_template_skiplists[CONTACTGROUP_SKIPLIST], (void *)temp_contactgroup); switch(result) { case SKIPLIST_ERROR_DUPLICATE: logit(NSLOG_CONFIG_WARNING, TRUE, "Warning: Duplicate definition found for contactgroup '%s' (config file '%s', starting on line %d)\n", value, xodtemplate_config_file_name(temp_contactgroup->_config_file), temp_contactgroup->_start_line); @@ -1405,7 +1368,7 @@ int xodtemplate_add_object_property(char *input, int options) { if(result == OK) { /* add contactgroup to template skiplist for fast searches */ - result = skiplist_insert(xobject_skiplists[X_CONTACTGROUP_SKIPLIST], (void *)temp_contactgroup); + result = skiplist_insert(xobject_skiplists[CONTACTGROUP_SKIPLIST], (void *)temp_contactgroup); switch(result) { case SKIPLIST_ERROR_DUPLICATE: logit(NSLOG_CONFIG_WARNING, TRUE, "Warning: Duplicate definition found for contactgroup '%s' (config file '%s', starting on line %d)\n", value, xodtemplate_config_file_name(temp_contactgroup->_config_file), temp_contactgroup->_start_line); @@ -1480,7 +1443,7 @@ int xodtemplate_add_object_property(char *input, int options) { if(result == OK) { /* add hostgroup to template skiplist for fast searches */ - result = skiplist_insert(xobject_template_skiplists[X_HOSTGROUP_SKIPLIST], (void *)temp_hostgroup); + result = skiplist_insert(xobject_template_skiplists[HOSTGROUP_SKIPLIST], (void *)temp_hostgroup); switch(result) { case SKIPLIST_ERROR_DUPLICATE: logit(NSLOG_CONFIG_WARNING, TRUE, "Warning: Duplicate definition found for hostgroup '%s' (config file '%s', starting on line %d)\n", value, xodtemplate_config_file_name(temp_hostgroup->_config_file), temp_hostgroup->_start_line); @@ -1501,7 +1464,7 @@ int xodtemplate_add_object_property(char *input, int options) { if(result == OK) { /* add hostgroup to template skiplist for fast searches */ - result = skiplist_insert(xobject_skiplists[X_HOSTGROUP_SKIPLIST], (void *)temp_hostgroup); + result = skiplist_insert(xobject_skiplists[HOSTGROUP_SKIPLIST], (void *)temp_hostgroup); switch(result) { case SKIPLIST_ERROR_DUPLICATE: logit(NSLOG_CONFIG_WARNING, TRUE, "Warning: Duplicate definition found for hostgroup '%s' (config file '%s', starting on line %d)\n", value, xodtemplate_config_file_name(temp_hostgroup->_config_file), temp_hostgroup->_start_line); @@ -1598,7 +1561,7 @@ int xodtemplate_add_object_property(char *input, int options) { if(result == OK) { /* add servicegroup to template skiplist for fast searches */ - result = skiplist_insert(xobject_template_skiplists[X_SERVICEGROUP_SKIPLIST], (void *)temp_servicegroup); + result = skiplist_insert(xobject_template_skiplists[SERVICEGROUP_SKIPLIST], (void *)temp_servicegroup); switch(result) { case SKIPLIST_ERROR_DUPLICATE: logit(NSLOG_CONFIG_WARNING, TRUE, "Warning: Duplicate definition found for servicegroup '%s' (config file '%s', starting on line %d)\n", value, xodtemplate_config_file_name(temp_servicegroup->_config_file), temp_servicegroup->_start_line); @@ -1619,7 +1582,7 @@ int xodtemplate_add_object_property(char *input, int options) { if(result == OK) { /* add servicegroup to template skiplist for fast searches */ - result = skiplist_insert(xobject_skiplists[X_SERVICEGROUP_SKIPLIST], (void *)temp_servicegroup); + result = skiplist_insert(xobject_skiplists[SERVICEGROUP_SKIPLIST], (void *)temp_servicegroup); switch(result) { case SKIPLIST_ERROR_DUPLICATE: logit(NSLOG_CONFIG_WARNING, TRUE, "Warning: Duplicate definition found for servicegroup '%s' (config file '%s', starting on line %d)\n", value, xodtemplate_config_file_name(temp_servicegroup->_config_file), temp_servicegroup->_start_line); @@ -1716,7 +1679,7 @@ int xodtemplate_add_object_property(char *input, int options) { if(result == OK) { /* add dependency to template skiplist for fast searches */ - result = skiplist_insert(xobject_template_skiplists[X_SERVICEDEPENDENCY_SKIPLIST], (void *)temp_servicedependency); + result = skiplist_insert(xobject_template_skiplists[SERVICEDEPENDENCY_SKIPLIST], (void *)temp_servicedependency); switch(result) { case SKIPLIST_ERROR_DUPLICATE: logit(NSLOG_CONFIG_WARNING, TRUE, "Warning: Duplicate definition found for service dependency '%s' (config file '%s', starting on line %d)\n", value, xodtemplate_config_file_name(temp_servicedependency->_config_file), temp_servicedependency->_start_line); @@ -1779,20 +1742,6 @@ int xodtemplate_add_object_property(char *input, int options) { result = ERROR; } temp_servicedependency->have_dependent_host_name = TRUE; - - /* NOTE: dependencies are added to the skiplist in xodtemplate_duplicate_objects(), except if daemon is using precached config */ - if(result == OK && force_skiplists == TRUE && temp_servicedependency->dependent_host_name != NULL && temp_servicedependency->dependent_service_description != NULL) { - /* add servicedependency to template skiplist for fast searches */ - result = skiplist_insert(xobject_skiplists[X_SERVICEDEPENDENCY_SKIPLIST], (void *)temp_servicedependency); - switch(result) { - case SKIPLIST_OK: - result = OK; - break; - default: - result = ERROR; - break; - } - } } else if(!strcmp(variable, "dependent_description") || !strcmp(variable, "dependent_service_description")) { if(strcmp(value, XODTEMPLATE_NULL)) { @@ -1800,20 +1749,6 @@ int xodtemplate_add_object_property(char *input, int options) { result = ERROR; } temp_servicedependency->have_dependent_service_description = TRUE; - - /* NOTE: dependencies are added to the skiplist in xodtemplate_duplicate_objects(), except if daemon is using precached config */ - if(result == OK && force_skiplists == TRUE && temp_servicedependency->dependent_host_name != NULL && temp_servicedependency->dependent_service_description != NULL) { - /* add servicedependency to template skiplist for fast searches */ - result = skiplist_insert(xobject_skiplists[X_SERVICEDEPENDENCY_SKIPLIST], (void *)temp_servicedependency); - switch(result) { - case SKIPLIST_OK: - result = OK; - break; - default: - result = ERROR; - break; - } - } } else if(!strcmp(variable, "dependency_period")) { if(strcmp(value, XODTEMPLATE_NULL)) { @@ -1827,68 +1762,56 @@ int xodtemplate_add_object_property(char *input, int options) { temp_servicedependency->have_inherits_parent = TRUE; } else if(!strcmp(variable, "execution_failure_options") || !strcmp(variable, "execution_failure_criteria")) { + temp_servicedependency->have_execution_failure_options = TRUE; for(temp_ptr = strtok(value, ", "); temp_ptr; temp_ptr = strtok(NULL, ", ")) { if(!strcmp(temp_ptr, "o") || !strcmp(temp_ptr, "ok")) - temp_servicedependency->fail_execute_on_ok = TRUE; + flag_set(temp_servicedependency->execution_failure_options, OPT_OK); else if(!strcmp(temp_ptr, "u") || !strcmp(temp_ptr, "unknown")) - temp_servicedependency->fail_execute_on_unknown = TRUE; + flag_set(temp_servicedependency->execution_failure_options, OPT_UNKNOWN); else if(!strcmp(temp_ptr, "w") || !strcmp(temp_ptr, "warning")) - temp_servicedependency->fail_execute_on_warning = TRUE; + flag_set(temp_servicedependency->execution_failure_options, OPT_WARNING); else if(!strcmp(temp_ptr, "c") || !strcmp(temp_ptr, "critical")) - temp_servicedependency->fail_execute_on_critical = TRUE; + flag_set(temp_servicedependency->execution_failure_options, OPT_CRITICAL); else if(!strcmp(temp_ptr, "p") || !strcmp(temp_ptr, "pending")) - temp_servicedependency->fail_execute_on_pending = TRUE; + flag_set(temp_servicedependency->execution_failure_options, OPT_PENDING); else if(!strcmp(temp_ptr, "n") || !strcmp(temp_ptr, "none")) { - temp_servicedependency->fail_execute_on_ok = FALSE; - temp_servicedependency->fail_execute_on_unknown = FALSE; - temp_servicedependency->fail_execute_on_warning = FALSE; - temp_servicedependency->fail_execute_on_critical = FALSE; + temp_servicedependency->execution_failure_options = OPT_NOTHING; + temp_servicedependency->have_execution_failure_options = FALSE; } else if(!strcmp(temp_ptr, "a") || !strcmp(temp_ptr, "all")) { - temp_servicedependency->fail_execute_on_ok = TRUE; - temp_servicedependency->fail_execute_on_unknown = TRUE; - temp_servicedependency->fail_execute_on_warning = TRUE; - temp_servicedependency->fail_execute_on_critical = TRUE; + temp_servicedependency->execution_failure_options = OPT_ALL; } else { logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Invalid execution dependency option '%s' in servicedependency definition.\n", temp_ptr); return ERROR; } } - temp_servicedependency->have_execution_dependency_options = TRUE; } else if(!strcmp(variable, "notification_failure_options") || !strcmp(variable, "notification_failure_criteria")) { + temp_servicedependency->have_notification_failure_options = TRUE; for(temp_ptr = strtok(value, ", "); temp_ptr; temp_ptr = strtok(NULL, ", ")) { if(!strcmp(temp_ptr, "o") || !strcmp(temp_ptr, "ok")) - temp_servicedependency->fail_notify_on_ok = TRUE; + flag_set(temp_servicedependency->notification_failure_options, OPT_OK); else if(!strcmp(temp_ptr, "u") || !strcmp(temp_ptr, "unknown")) - temp_servicedependency->fail_notify_on_unknown = TRUE; + flag_set(temp_servicedependency->notification_failure_options, OPT_UNKNOWN); else if(!strcmp(temp_ptr, "w") || !strcmp(temp_ptr, "warning")) - temp_servicedependency->fail_notify_on_warning = TRUE; + flag_set(temp_servicedependency->notification_failure_options, OPT_WARNING); else if(!strcmp(temp_ptr, "c") || !strcmp(temp_ptr, "critical")) - temp_servicedependency->fail_notify_on_critical = TRUE; + flag_set(temp_servicedependency->notification_failure_options, OPT_CRITICAL); else if(!strcmp(temp_ptr, "p") || !strcmp(temp_ptr, "pending")) - temp_servicedependency->fail_notify_on_pending = TRUE; + flag_set(temp_servicedependency->notification_failure_options, OPT_PENDING); else if(!strcmp(temp_ptr, "n") || !strcmp(temp_ptr, "none")) { - temp_servicedependency->fail_notify_on_ok = FALSE; - temp_servicedependency->fail_notify_on_unknown = FALSE; - temp_servicedependency->fail_notify_on_warning = FALSE; - temp_servicedependency->fail_notify_on_critical = FALSE; - temp_servicedependency->fail_notify_on_pending = FALSE; + temp_servicedependency->notification_failure_options = OPT_NOTHING; + temp_servicedependency->have_notification_failure_options = FALSE; } else if(!strcmp(temp_ptr, "a") || !strcmp(temp_ptr, "all")) { - temp_servicedependency->fail_notify_on_ok = TRUE; - temp_servicedependency->fail_notify_on_unknown = TRUE; - temp_servicedependency->fail_notify_on_warning = TRUE; - temp_servicedependency->fail_notify_on_critical = TRUE; - temp_servicedependency->fail_notify_on_pending = TRUE; + temp_servicedependency->notification_failure_options = OPT_ALL; } else { logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Invalid notification dependency option '%s' in servicedependency definition.\n", temp_ptr); return ERROR; } } - temp_servicedependency->have_notification_dependency_options = TRUE; } else if(!strcmp(variable, "register")) temp_servicedependency->register_object = (atoi(value) > 0) ? TRUE : FALSE; @@ -1915,7 +1838,7 @@ int xodtemplate_add_object_property(char *input, int options) { if(result == OK) { /* add escalation to template skiplist for fast searches */ - result = skiplist_insert(xobject_template_skiplists[X_SERVICEESCALATION_SKIPLIST], (void *)temp_serviceescalation); + result = skiplist_insert(xobject_template_skiplists[SERVICEESCALATION_SKIPLIST], (void *)temp_serviceescalation); switch(result) { case SKIPLIST_ERROR_DUPLICATE: logit(NSLOG_CONFIG_WARNING, TRUE, "Warning: Duplicate definition found for service escalation '%s' (config file '%s', starting on line %d)\n", value, xodtemplate_config_file_name(temp_serviceescalation->_config_file), temp_serviceescalation->_start_line); @@ -1937,20 +1860,6 @@ int xodtemplate_add_object_property(char *input, int options) { result = ERROR; } temp_serviceescalation->have_host_name = TRUE; - - /* NOTE: escalations are added to the skiplist in xodtemplate_duplicate_objects(), except if daemon is using precached config */ - if(result == OK && force_skiplists == TRUE && temp_serviceescalation->host_name != NULL && temp_serviceescalation->service_description != NULL) { - /* add serviceescalation to template skiplist for fast searches */ - result = skiplist_insert(xobject_skiplists[X_SERVICEESCALATION_SKIPLIST], (void *)temp_serviceescalation); - switch(result) { - case SKIPLIST_OK: - result = OK; - break; - default: - result = ERROR; - break; - } - } } else if(!strcmp(variable, "description") || !strcmp(variable, "service_description")) { if(strcmp(value, XODTEMPLATE_NULL)) { @@ -1958,20 +1867,6 @@ int xodtemplate_add_object_property(char *input, int options) { result = ERROR; } temp_serviceescalation->have_service_description = TRUE; - - /* NOTE: escalations are added to the skiplist in xodtemplate_duplicate_objects(), except if daemon is using precached config */ - if(result == OK && force_skiplists == TRUE && temp_serviceescalation->host_name != NULL && temp_serviceescalation->service_description != NULL) { - /* add serviceescalation to template skiplist for fast searches */ - result = skiplist_insert(xobject_skiplists[X_SERVICEESCALATION_SKIPLIST], (void *)temp_serviceescalation); - switch(result) { - case SKIPLIST_OK: - result = OK; - break; - default: - result = ERROR; - break; - } - } } else if(!strcmp(variable, "servicegroup") || !strcmp(variable, "servicegroups") || !strcmp(variable, "servicegroup_name")) { if(strcmp(value, XODTEMPLATE_NULL)) { @@ -1988,6 +1883,11 @@ int xodtemplate_add_object_property(char *input, int options) { temp_serviceescalation->have_hostgroup_name = TRUE; } else if(!strcmp(variable, "contact_groups")) { + if (*value == '\0') { + logit(NSLOG_CONFIG_WARNING, TRUE, "Error: Empty value for contact_groups (config file '%s', starting on line %d)\n", xodtemplate_config_file_name(temp_serviceescalation->_config_file), temp_serviceescalation->_start_line); + result = ERROR; + break; + } if(strcmp(value, XODTEMPLATE_NULL)) { if((temp_serviceescalation->contact_groups = (char *)strdup(value)) == NULL) result = ERROR; @@ -1995,6 +1895,11 @@ int xodtemplate_add_object_property(char *input, int options) { temp_serviceescalation->have_contact_groups = TRUE; } else if(!strcmp(variable, "contacts")) { + if (*value == '\0') { + logit(NSLOG_CONFIG_WARNING, TRUE, "Error: Empty value for contacts (config file '%s', starting on line %d)\n", xodtemplate_config_file_name(temp_serviceescalation->_config_file), temp_serviceescalation->_start_line); + result = ERROR; + break; + } if(strcmp(value, XODTEMPLATE_NULL)) { if((temp_serviceescalation->contacts = (char *)strdup(value)) == NULL) result = ERROR; @@ -2023,24 +1928,18 @@ int xodtemplate_add_object_property(char *input, int options) { else if(!strcmp(variable, "escalation_options")) { for(temp_ptr = strtok(value, ", "); temp_ptr; temp_ptr = strtok(NULL, ", ")) { if(!strcmp(temp_ptr, "w") || !strcmp(temp_ptr, "warning")) - temp_serviceescalation->escalate_on_warning = TRUE; + flag_set(temp_serviceescalation->escalation_options, OPT_WARNING); else if(!strcmp(temp_ptr, "u") || !strcmp(temp_ptr, "unknown")) - temp_serviceescalation->escalate_on_unknown = TRUE; + flag_set(temp_serviceescalation->escalation_options, OPT_UNKNOWN); else if(!strcmp(temp_ptr, "c") || !strcmp(temp_ptr, "critical")) - temp_serviceescalation->escalate_on_critical = TRUE; + flag_set(temp_serviceescalation->escalation_options, OPT_CRITICAL); else if(!strcmp(temp_ptr, "r") || !strcmp(temp_ptr, "recovery")) - temp_serviceescalation->escalate_on_recovery = TRUE; + flag_set(temp_serviceescalation->escalation_options, OPT_RECOVERY); else if(!strcmp(temp_ptr, "n") || !strcmp(temp_ptr, "none")) { - temp_serviceescalation->escalate_on_warning = FALSE; - temp_serviceescalation->escalate_on_unknown = FALSE; - temp_serviceescalation->escalate_on_critical = FALSE; - temp_serviceescalation->escalate_on_recovery = FALSE; + temp_serviceescalation->escalation_options = OPT_NOTHING; } else if(!strcmp(temp_ptr, "a") || !strcmp(temp_ptr, "all")) { - temp_serviceescalation->escalate_on_warning = TRUE; - temp_serviceescalation->escalate_on_unknown = TRUE; - temp_serviceescalation->escalate_on_critical = TRUE; - temp_serviceescalation->escalate_on_recovery = TRUE; + temp_serviceescalation->escalation_options = OPT_ALL; } else { logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Invalid escalation option '%s' in serviceescalation definition.\n", temp_ptr); @@ -2074,7 +1973,7 @@ int xodtemplate_add_object_property(char *input, int options) { if(result == OK) { /* add contact to template skiplist for fast searches */ - result = skiplist_insert(xobject_template_skiplists[X_CONTACT_SKIPLIST], (void *)temp_contact); + result = skiplist_insert(xobject_template_skiplists[CONTACT_SKIPLIST], (void *)temp_contact); switch(result) { case SKIPLIST_ERROR_DUPLICATE: logit(NSLOG_CONFIG_WARNING, TRUE, "Warning: Duplicate definition found for contact '%s' (config file '%s', starting on line %d)\n", value, xodtemplate_config_file_name(temp_contact->_config_file), temp_contact->_start_line); @@ -2095,7 +1994,7 @@ int xodtemplate_add_object_property(char *input, int options) { if(result == OK) { /* add contact to template skiplist for fast searches */ - result = skiplist_insert(xobject_skiplists[X_CONTACT_SKIPLIST], (void *)temp_contact); + result = skiplist_insert(xobject_skiplists[CONTACT_SKIPLIST], (void *)temp_contact); switch(result) { case SKIPLIST_ERROR_DUPLICATE: logit(NSLOG_CONFIG_WARNING, TRUE, "Warning: Duplicate definition found for contact '%s' (config file '%s', starting on line %d)\n", value, xodtemplate_config_file_name(temp_contact->_config_file), temp_contact->_start_line); @@ -2109,6 +2008,7 @@ int xodtemplate_add_object_property(char *input, int options) { break; } } + temp_contact->id = xodcount.contacts++; } else if(!strcmp(variable, "alias")) { if((temp_contact->alias = (char *)strdup(value)) == NULL) @@ -2177,28 +2077,20 @@ int xodtemplate_add_object_property(char *input, int options) { else if(!strcmp(variable, "host_notification_options")) { for(temp_ptr = strtok(value, ", "); temp_ptr; temp_ptr = strtok(NULL, ", ")) { if(!strcmp(temp_ptr, "d") || !strcmp(temp_ptr, "down")) - temp_contact->notify_on_host_down = TRUE; + flag_set(temp_contact->host_notification_options, OPT_DOWN); else if(!strcmp(temp_ptr, "u") || !strcmp(temp_ptr, "unreachable")) - temp_contact->notify_on_host_unreachable = TRUE; + flag_set(temp_contact->host_notification_options, OPT_UNREACHABLE); else if(!strcmp(temp_ptr, "r") || !strcmp(temp_ptr, "recovery")) - temp_contact->notify_on_host_recovery = TRUE; + flag_set(temp_contact->host_notification_options, OPT_RECOVERY); else if(!strcmp(temp_ptr, "f") || !strcmp(temp_ptr, "flapping")) - temp_contact->notify_on_host_flapping = TRUE; + flag_set(temp_contact->host_notification_options, OPT_FLAPPING); else if(!strcmp(temp_ptr, "s") || !strcmp(temp_ptr, "downtime")) - temp_contact->notify_on_host_downtime = TRUE; + flag_set(temp_contact->host_notification_options, OPT_DOWNTIME); else if(!strcmp(temp_ptr, "n") || !strcmp(temp_ptr, "none")) { - temp_contact->notify_on_host_down = FALSE; - temp_contact->notify_on_host_unreachable = FALSE; - temp_contact->notify_on_host_recovery = FALSE; - temp_contact->notify_on_host_flapping = FALSE; - temp_contact->notify_on_host_downtime = FALSE; + temp_contact->host_notification_options = OPT_NOTHING; } else if(!strcmp(temp_ptr, "a") || !strcmp(temp_ptr, "all")) { - temp_contact->notify_on_host_down = TRUE; - temp_contact->notify_on_host_unreachable = TRUE; - temp_contact->notify_on_host_recovery = TRUE; - temp_contact->notify_on_host_flapping = TRUE; - temp_contact->notify_on_host_downtime = TRUE; + temp_contact->host_notification_options = OPT_ALL; } else { logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Invalid host notification option '%s' in contact definition.\n", temp_ptr); @@ -2210,32 +2102,22 @@ int xodtemplate_add_object_property(char *input, int options) { else if(!strcmp(variable, "service_notification_options")) { for(temp_ptr = strtok(value, ", "); temp_ptr; temp_ptr = strtok(NULL, ", ")) { if(!strcmp(temp_ptr, "u") || !strcmp(temp_ptr, "unknown")) - temp_contact->notify_on_service_unknown = TRUE; + flag_set(temp_contact->service_notification_options, OPT_UNKNOWN); else if(!strcmp(temp_ptr, "w") || !strcmp(temp_ptr, "warning")) - temp_contact->notify_on_service_warning = TRUE; + flag_set(temp_contact->service_notification_options, OPT_WARNING); else if(!strcmp(temp_ptr, "c") || !strcmp(temp_ptr, "critical")) - temp_contact->notify_on_service_critical = TRUE; + flag_set(temp_contact->service_notification_options, OPT_CRITICAL); else if(!strcmp(temp_ptr, "r") || !strcmp(temp_ptr, "recovery")) - temp_contact->notify_on_service_recovery = TRUE; + flag_set(temp_contact->service_notification_options, OPT_RECOVERY); else if(!strcmp(temp_ptr, "f") || !strcmp(temp_ptr, "flapping")) - temp_contact->notify_on_service_flapping = TRUE; + flag_set(temp_contact->service_notification_options, OPT_FLAPPING); else if(!strcmp(temp_ptr, "s") || !strcmp(temp_ptr, "downtime")) - temp_contact->notify_on_service_downtime = TRUE; + flag_set(temp_contact->service_notification_options, OPT_DOWNTIME); else if(!strcmp(temp_ptr, "n") || !strcmp(temp_ptr, "none")) { - temp_contact->notify_on_service_unknown = FALSE; - temp_contact->notify_on_service_warning = FALSE; - temp_contact->notify_on_service_critical = FALSE; - temp_contact->notify_on_service_recovery = FALSE; - temp_contact->notify_on_service_flapping = FALSE; - temp_contact->notify_on_service_downtime = FALSE; + temp_contact->service_notification_options = OPT_NOTHING; } else if(!strcmp(temp_ptr, "a") || !strcmp(temp_ptr, "all")) { - temp_contact->notify_on_service_unknown = TRUE; - temp_contact->notify_on_service_warning = TRUE; - temp_contact->notify_on_service_critical = TRUE; - temp_contact->notify_on_service_recovery = TRUE; - temp_contact->notify_on_service_flapping = TRUE; - temp_contact->notify_on_service_downtime = TRUE; + temp_contact->service_notification_options = OPT_ALL; } else { logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Invalid service notification option '%s' in contact definition.\n", temp_ptr); @@ -2264,6 +2146,14 @@ int xodtemplate_add_object_property(char *input, int options) { temp_contact->retain_nonstatus_information = (atoi(value) > 0) ? TRUE : FALSE; temp_contact->have_retain_nonstatus_information = TRUE; } + else if(!strcmp(variable, "minimum_importance") || + !strcmp(variable, "minimum_value")) { + if(!strcmp(variable, "minimum_value")) { + logit(NSLOG_CONFIG_WARNING, TRUE, "WARNING: The minimum_value attribute is deprecated and will be removed in future versions. Please use minimum_importance instead.\n"); + } + temp_contact->minimum_value = strtoul(value, NULL, 10); + temp_contact->have_minimum_value = TRUE; + } else if(!strcmp(variable, "register")) temp_contact->register_object = (atoi(value) > 0) ? TRUE : FALSE; else if(variable[0] == '_') { @@ -2279,7 +2169,7 @@ int xodtemplate_add_object_property(char *input, int options) { } /* get the variable value */ - if(strcmp(value, XODTEMPLATE_NULL)) + if(*value && strcmp(value, XODTEMPLATE_NULL)) customvarvalue = (char *)strdup(value); else customvarvalue = NULL; @@ -2318,7 +2208,7 @@ int xodtemplate_add_object_property(char *input, int options) { if(result == OK) { /* add host to template skiplist for fast searches */ - result = skiplist_insert(xobject_template_skiplists[X_HOST_SKIPLIST], (void *)temp_host); + result = skiplist_insert(xobject_template_skiplists[HOST_SKIPLIST], (void *)temp_host); switch(result) { case SKIPLIST_ERROR_DUPLICATE: logit(NSLOG_CONFIG_WARNING, TRUE, "Warning: Duplicate definition found for host '%s' (config file '%s', starting on line %d)\n", value, xodtemplate_config_file_name(temp_host->_config_file), temp_host->_start_line); @@ -2339,7 +2229,7 @@ int xodtemplate_add_object_property(char *input, int options) { if(result == OK) { /* add host to template skiplist for fast searches */ - result = skiplist_insert(xobject_skiplists[X_HOST_SKIPLIST], (void *)temp_host); + result = skiplist_insert(xobject_skiplists[HOST_SKIPLIST], (void *)temp_host); switch(result) { case SKIPLIST_ERROR_DUPLICATE: logit(NSLOG_CONFIG_WARNING, TRUE, "Warning: Duplicate definition found for host '%s' (config file '%s', starting on line %d)\n", value, xodtemplate_config_file_name(temp_host->_config_file), temp_host->_start_line); @@ -2353,6 +2243,7 @@ int xodtemplate_add_object_property(char *input, int options) { break; } } + temp_host->id = xodcount.hosts++; } else if(!strcmp(variable, "display_name")) { if(strcmp(value, XODTEMPLATE_NULL)) { @@ -2384,6 +2275,11 @@ int xodtemplate_add_object_property(char *input, int options) { temp_host->have_host_groups = TRUE; } else if(!strcmp(variable, "contact_groups")) { + if (*value == '\0') { + logit(NSLOG_CONFIG_WARNING, TRUE, "Error: Empty value for contact_groups (config file '%s', starting on line %d)\n", xodtemplate_config_file_name(temp_host->_config_file), temp_host->_start_line); + result = ERROR; + break; + } if(strcmp(value, XODTEMPLATE_NULL)) { if((temp_host->contact_groups = (char *)strdup(value)) == NULL) result = ERROR; @@ -2391,6 +2287,11 @@ int xodtemplate_add_object_property(char *input, int options) { temp_host->have_contact_groups = TRUE; } else if(!strcmp(variable, "contacts")) { + if (*value == '\0') { + logit(NSLOG_CONFIG_WARNING, TRUE, "Error: Empty value for contacts (config file '%s', starting on line %d)\n", xodtemplate_config_file_name(temp_host->_config_file), temp_host->_start_line); + result = ERROR; + break; + } if(strcmp(value, XODTEMPLATE_NULL)) { if((temp_host->contacts = (char *)strdup(value)) == NULL) result = ERROR; @@ -2426,11 +2327,7 @@ int xodtemplate_add_object_property(char *input, int options) { temp_host->have_event_handler = TRUE; } else if(!strcmp(variable, "failure_prediction_options")) { - if(strcmp(value, XODTEMPLATE_NULL)) { - if((temp_host->failure_prediction_options = (char *)strdup(value)) == NULL) - result = ERROR; - } - temp_host->have_failure_prediction_options = TRUE; + xodtemplate_obsoleted(variable, temp_host->_start_line); } else if(!strcmp(variable, "notes")) { if(strcmp(value, XODTEMPLATE_NULL)) { @@ -2495,13 +2392,25 @@ int xodtemplate_add_object_property(char *input, int options) { temp_host->have_initial_state = TRUE; } else if(!strcmp(variable, "check_interval") || !strcmp(variable, "normal_check_interval")) { + if(!strcmp(variable, "normal_check_interval")) + logit(NSLOG_CONFIG_WARNING, TRUE, "WARNING: The normal_check_interval attribute is deprecated and will be removed in future versions. Please use check_interval instead.\n"); temp_host->check_interval = strtod(value, NULL); temp_host->have_check_interval = TRUE; } else if(!strcmp(variable, "retry_interval") || !strcmp(variable, "retry_check_interval")) { + if(!strcmp(variable, "retry_check_interval")) + logit(NSLOG_CONFIG_WARNING, TRUE, "WARNING: The normal_retry_interval attribute is deprecated and will be removed in future versions. Please use retry_interval instead.\n"); temp_host->retry_interval = strtod(value, NULL); temp_host->have_retry_interval = TRUE; } + else if(!strcmp(variable, "importance") || + !strcmp(variable, "hourly_value")) { + if(!strcmp(variable, "hourly_value")) { + logit(NSLOG_CONFIG_WARNING, TRUE, "WARNING: The hourly_value attribute is deprecated and will be removed in future versions. Please use importance instead.\n"); + } + temp_host->hourly_value = (unsigned int)strtoul(value, NULL, 10); + temp_host->have_hourly_value = 1; + } else if(!strcmp(variable, "max_check_attempts")) { temp_host->max_check_attempts = atoi(value); temp_host->have_max_check_attempts = TRUE; @@ -2541,26 +2450,20 @@ int xodtemplate_add_object_property(char *input, int options) { else if(!strcmp(variable, "flap_detection_options")) { /* user is specifying something, so discard defaults... */ - temp_host->flap_detection_on_up = FALSE; - temp_host->flap_detection_on_down = FALSE; - temp_host->flap_detection_on_unreachable = FALSE; + temp_host->flap_detection_options = OPT_NOTHING; for(temp_ptr = strtok(value, ", "); temp_ptr; temp_ptr = strtok(NULL, ", ")) { if(!strcmp(temp_ptr, "o") || !strcmp(temp_ptr, "up")) - temp_host->flap_detection_on_up = TRUE; + flag_set(temp_host->flap_detection_options, OPT_UP); else if(!strcmp(temp_ptr, "d") || !strcmp(temp_ptr, "down")) - temp_host->flap_detection_on_down = TRUE; + flag_set(temp_host->flap_detection_options, OPT_DOWN); else if(!strcmp(temp_ptr, "u") || !strcmp(temp_ptr, "unreachable")) - temp_host->flap_detection_on_unreachable = TRUE; + flag_set(temp_host->flap_detection_options, OPT_UNREACHABLE); else if(!strcmp(temp_ptr, "n") || !strcmp(temp_ptr, "none")) { - temp_host->flap_detection_on_up = FALSE; - temp_host->flap_detection_on_down = FALSE; - temp_host->flap_detection_on_unreachable = FALSE; + temp_host->flap_detection_options = OPT_NOTHING; } else if(!strcmp(temp_ptr, "a") || !strcmp(temp_ptr, "all")) { - temp_host->flap_detection_on_up = TRUE; - temp_host->flap_detection_on_down = TRUE; - temp_host->flap_detection_on_unreachable = TRUE; + temp_host->flap_detection_options = OPT_ALL; } else { logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Invalid flap detection option '%s' in host definition.\n", temp_ptr); @@ -2572,28 +2475,20 @@ int xodtemplate_add_object_property(char *input, int options) { else if(!strcmp(variable, "notification_options")) { for(temp_ptr = strtok(value, ", "); temp_ptr; temp_ptr = strtok(NULL, ", ")) { if(!strcmp(temp_ptr, "d") || !strcmp(temp_ptr, "down")) - temp_host->notify_on_down = TRUE; + flag_set(temp_host->notification_options, OPT_DOWN); else if(!strcmp(temp_ptr, "u") || !strcmp(temp_ptr, "unreachable")) - temp_host->notify_on_unreachable = TRUE; + flag_set(temp_host->notification_options, OPT_UNREACHABLE); else if(!strcmp(temp_ptr, "r") || !strcmp(temp_ptr, "recovery")) - temp_host->notify_on_recovery = TRUE; + flag_set(temp_host->notification_options, OPT_RECOVERY); else if(!strcmp(temp_ptr, "f") || !strcmp(temp_ptr, "flapping")) - temp_host->notify_on_flapping = TRUE; + flag_set(temp_host->notification_options, OPT_FLAPPING); else if(!strcmp(temp_ptr, "s") || !strcmp(temp_ptr, "downtime")) - temp_host->notify_on_downtime = TRUE; + flag_set(temp_host->notification_options, OPT_DOWNTIME); else if(!strcmp(temp_ptr, "n") || !strcmp(temp_ptr, "none")) { - temp_host->notify_on_down = FALSE; - temp_host->notify_on_unreachable = FALSE; - temp_host->notify_on_recovery = FALSE; - temp_host->notify_on_flapping = FALSE; - temp_host->notify_on_downtime = FALSE; + temp_host->notification_options = OPT_NOTHING; } else if(!strcmp(temp_ptr, "a") || !strcmp(temp_ptr, "all")) { - temp_host->notify_on_down = TRUE; - temp_host->notify_on_unreachable = TRUE; - temp_host->notify_on_recovery = TRUE; - temp_host->notify_on_flapping = TRUE; - temp_host->notify_on_downtime = TRUE; + temp_host->notification_options = OPT_ALL; } else { logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Invalid notification option '%s' in host definition.\n", temp_ptr); @@ -2617,20 +2512,16 @@ int xodtemplate_add_object_property(char *input, int options) { else if(!strcmp(variable, "stalking_options")) { for(temp_ptr = strtok(value, ", "); temp_ptr; temp_ptr = strtok(NULL, ", ")) { if(!strcmp(temp_ptr, "o") || !strcmp(temp_ptr, "up")) - temp_host->stalk_on_up = TRUE; + flag_set(temp_host->stalking_options, OPT_UP); else if(!strcmp(temp_ptr, "d") || !strcmp(temp_ptr, "down")) - temp_host->stalk_on_down = TRUE; + flag_set(temp_host->stalking_options, OPT_DOWN); else if(!strcmp(temp_ptr, "u") || !strcmp(temp_ptr, "unreachable")) - temp_host->stalk_on_unreachable = TRUE; + flag_set(temp_host->stalking_options, OPT_UNREACHABLE); else if(!strcmp(temp_ptr, "n") || !strcmp(temp_ptr, "none")) { - temp_host->stalk_on_up = FALSE; - temp_host->stalk_on_down = FALSE; - temp_host->stalk_on_unreachable = FALSE; + temp_host->stalking_options = OPT_NOTHING; } else if(!strcmp(temp_ptr, "a") || !strcmp(temp_ptr, "all")) { - temp_host->stalk_on_up = TRUE; - temp_host->stalk_on_down = TRUE; - temp_host->stalk_on_unreachable = TRUE; + temp_host->stalking_options = OPT_ALL; } else { logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Invalid stalking option '%s' in host definition.\n", temp_ptr); @@ -2644,8 +2535,7 @@ int xodtemplate_add_object_property(char *input, int options) { temp_host->have_process_perf_data = TRUE; } else if(!strcmp(variable, "failure_prediction_enabled")) { - temp_host->failure_prediction_enabled = (atoi(value) > 0) ? TRUE : FALSE; - temp_host->have_failure_prediction_enabled = TRUE; + xodtemplate_obsoleted(variable, temp_host->_start_line); } else if(!strcmp(variable, "2d_coords")) { if((temp_ptr = strtok(value, ", ")) == NULL) { @@ -2678,9 +2568,9 @@ int xodtemplate_add_object_property(char *input, int options) { temp_host->z_3d = strtod(temp_ptr, NULL); temp_host->have_3d_coords = TRUE; } - else if(!strcmp(variable, "obsess_over_host")) { - temp_host->obsess_over_host = (atoi(value) > 0) ? TRUE : FALSE; - temp_host->have_obsess_over_host = TRUE; + else if(!strcmp(variable, "obsess_over_host") || !strcmp(variable, "obsess")) { + temp_host->obsess = (atoi(value) > 0) ? TRUE : FALSE; + temp_host->have_obsess = TRUE; } else if(!strcmp(variable, "retain_status_information")) { temp_host->retain_status_information = (atoi(value) > 0) ? TRUE : FALSE; @@ -2706,7 +2596,7 @@ int xodtemplate_add_object_property(char *input, int options) { /* get the variable value */ customvarvalue = NULL; - if(strcmp(value, XODTEMPLATE_NULL)) + if(*value && strcmp(value, XODTEMPLATE_NULL)) customvarvalue = (char *)strdup(value); /* add the custom variable */ @@ -2742,7 +2632,7 @@ int xodtemplate_add_object_property(char *input, int options) { if(result == OK) { /* add service to template skiplist for fast searches */ - result = skiplist_insert(xobject_template_skiplists[X_SERVICE_SKIPLIST], (void *)temp_service); + result = skiplist_insert(xobject_template_skiplists[SERVICE_SKIPLIST], (void *)temp_service); switch(result) { case SKIPLIST_ERROR_DUPLICATE: logit(NSLOG_CONFIG_WARNING, TRUE, "Warning: Duplicate definition found for service '%s' (config file '%s', starting on line %d)\n", value, xodtemplate_config_file_name(temp_service->_config_file), temp_service->_start_line); @@ -2767,7 +2657,7 @@ int xodtemplate_add_object_property(char *input, int options) { /* NOTE: services are added to the skiplist in xodtemplate_duplicate_services(), except if daemon is using precached config */ if(result == OK && force_skiplists == TRUE && temp_service->host_name != NULL && temp_service->service_description != NULL) { /* add service to template skiplist for fast searches */ - result = skiplist_insert(xobject_skiplists[X_SERVICE_SKIPLIST], (void *)temp_service); + result = skiplist_insert(xobject_skiplists[SERVICE_SKIPLIST], (void *)temp_service); switch(result) { case SKIPLIST_ERROR_DUPLICATE: logit(NSLOG_CONFIG_WARNING, TRUE, "Warning: Duplicate definition found for service '%s' (config file '%s', starting on line %d)\n", value, xodtemplate_config_file_name(temp_service->_config_file), temp_service->_start_line); @@ -2775,6 +2665,7 @@ int xodtemplate_add_object_property(char *input, int options) { break; case SKIPLIST_OK: result = OK; + temp_service->id = xodcount.services++; break; default: result = ERROR; @@ -2792,7 +2683,7 @@ int xodtemplate_add_object_property(char *input, int options) { /* NOTE: services are added to the skiplist in xodtemplate_duplicate_services(), except if daemon is using precached config */ if(result == OK && force_skiplists == TRUE && temp_service->host_name != NULL && temp_service->service_description != NULL) { /* add service to template skiplist for fast searches */ - result = skiplist_insert(xobject_skiplists[X_SERVICE_SKIPLIST], (void *)temp_service); + result = skiplist_insert(xobject_skiplists[SERVICE_SKIPLIST], (void *)temp_service); switch(result) { case SKIPLIST_ERROR_DUPLICATE: logit(NSLOG_CONFIG_WARNING, TRUE, "Warning: Duplicate definition found for service '%s' (config file '%s', starting on line %d)\n", value, xodtemplate_config_file_name(temp_service->_config_file), temp_service->_start_line); @@ -2800,6 +2691,7 @@ int xodtemplate_add_object_property(char *input, int options) { break; case SKIPLIST_OK: result = OK; + temp_service->id = xodcount.services++; break; default: result = ERROR; @@ -2814,6 +2706,13 @@ int xodtemplate_add_object_property(char *input, int options) { } temp_service->have_display_name = TRUE; } + else if(!strcmp(variable, "parents")) { + if(strcmp(value, XODTEMPLATE_NULL)) { + if((temp_service->parents = (char *)strdup(value)) == NULL) + result = ERROR; + } + temp_service->have_parents = TRUE; + } else if(!strcmp(variable, "hostgroup") || !strcmp(variable, "hostgroups") || !strcmp(variable, "hostgroup_name")) { if(strcmp(value, XODTEMPLATE_NULL)) { if((temp_service->hostgroup_name = (char *)strdup(value)) == NULL) @@ -2863,6 +2762,11 @@ int xodtemplate_add_object_property(char *input, int options) { temp_service->have_notification_period = TRUE; } else if(!strcmp(variable, "contact_groups")) { + if (*value == '\0') { + logit(NSLOG_CONFIG_WARNING, TRUE, "Error: Empty value for contact_groups (config file '%s', starting on line %d)\n", xodtemplate_config_file_name(temp_service->_config_file), temp_service->_start_line); + result = ERROR; + break; + } if(strcmp(value, XODTEMPLATE_NULL)) { if((temp_service->contact_groups = (char *)strdup(value)) == NULL) result = ERROR; @@ -2870,6 +2774,11 @@ int xodtemplate_add_object_property(char *input, int options) { temp_service->have_contact_groups = TRUE; } else if(!strcmp(variable, "contacts")) { + if (*value == '\0') { + logit(NSLOG_CONFIG_WARNING, TRUE, "Error: Empty value for contacts (config file '%s', starting on line %d)\n", xodtemplate_config_file_name(temp_service->_config_file), temp_service->_start_line); + result = ERROR; + break; + } if(strcmp(value, XODTEMPLATE_NULL)) { if((temp_service->contacts = (char *)strdup(value)) == NULL) result = ERROR; @@ -2877,11 +2786,7 @@ int xodtemplate_add_object_property(char *input, int options) { temp_service->have_contacts = TRUE; } else if(!strcmp(variable, "failure_prediction_options")) { - if(strcmp(value, XODTEMPLATE_NULL)) { - if((temp_service->failure_prediction_options = (char *)strdup(value)) == NULL) - result = ERROR; - } - temp_service->have_failure_prediction_options = TRUE; + xodtemplate_obsoleted(variable, temp_service->_start_line); } else if(!strcmp(variable, "notes")) { if(strcmp(value, XODTEMPLATE_NULL)) { @@ -2933,15 +2838,27 @@ int xodtemplate_add_object_property(char *input, int options) { } temp_service->have_initial_state = TRUE; } + else if(!strcmp(variable, "importance") || + !strcmp(variable, "hourly_value")) { + if(!strcmp(variable, "hourly_value")) { + logit(NSLOG_CONFIG_WARNING, TRUE, "WARNING: The hourly_value attribute is deprecated and will be removed in future versions. Please use importance instead.\n"); + } + temp_service->hourly_value = (unsigned int)strtoul(value, NULL, 10); + temp_service->have_hourly_value = 1; + } else if(!strcmp(variable, "max_check_attempts")) { temp_service->max_check_attempts = atoi(value); temp_service->have_max_check_attempts = TRUE; } else if(!strcmp(variable, "check_interval") || !strcmp(variable, "normal_check_interval")) { + if(!strcmp(variable, "normal_check_interval")) + logit(NSLOG_CONFIG_WARNING, TRUE, "WARNING: The normal_check_interval attribute is deprecated and will be removed in future versions. Please use check_interval instead.\n"); temp_service->check_interval = strtod(value, NULL); temp_service->have_check_interval = TRUE; } else if(!strcmp(variable, "retry_interval") || !strcmp(variable, "retry_check_interval")) { + if(!strcmp(variable, "retry_check_interval")) + logit(NSLOG_CONFIG_WARNING, TRUE, "WARNING: The normal_retry_interval attribute is deprecated and will be removed in future versions. Please use retry_interval instead.\n"); temp_service->retry_interval = strtod(value, NULL); temp_service->have_retry_interval = TRUE; } @@ -2961,9 +2878,9 @@ int xodtemplate_add_object_property(char *input, int options) { temp_service->is_volatile = (atoi(value) > 0) ? TRUE : FALSE; temp_service->have_is_volatile = TRUE; } - else if(!strcmp(variable, "obsess_over_service")) { - temp_service->obsess_over_service = (atoi(value) > 0) ? TRUE : FALSE; - temp_service->have_obsess_over_service = TRUE; + else if(!strcmp(variable, "obsess_over_service") || !strcmp(variable, "obsess")) { + temp_service->obsess = (atoi(value) > 0) ? TRUE : FALSE; + temp_service->have_obsess = TRUE; } else if(!strcmp(variable, "event_handler_enabled")) { temp_service->event_handler_enabled = (atoi(value) > 0) ? TRUE : FALSE; @@ -2992,31 +2909,22 @@ int xodtemplate_add_object_property(char *input, int options) { else if(!strcmp(variable, "flap_detection_options")) { /* user is specifying something, so discard defaults... */ - temp_service->flap_detection_on_ok = FALSE; - temp_service->flap_detection_on_warning = FALSE; - temp_service->flap_detection_on_unknown = FALSE; - temp_service->flap_detection_on_critical = FALSE; + temp_service->flap_detection_options = OPT_NOTHING; for(temp_ptr = strtok(value, ", "); temp_ptr; temp_ptr = strtok(NULL, ", ")) { if(!strcmp(temp_ptr, "o") || !strcmp(temp_ptr, "ok")) - temp_service->flap_detection_on_ok = TRUE; + flag_set(temp_service->flap_detection_options, OPT_OK); else if(!strcmp(temp_ptr, "w") || !strcmp(temp_ptr, "warning")) - temp_service->flap_detection_on_warning = TRUE; + flag_set(temp_service->flap_detection_options, OPT_WARNING); else if(!strcmp(temp_ptr, "u") || !strcmp(temp_ptr, "unknown")) - temp_service->flap_detection_on_unknown = TRUE; + flag_set(temp_service->flap_detection_options, OPT_UNKNOWN); else if(!strcmp(temp_ptr, "c") || !strcmp(temp_ptr, "critical")) - temp_service->flap_detection_on_critical = TRUE; + flag_set(temp_service->flap_detection_options, OPT_CRITICAL); else if(!strcmp(temp_ptr, "n") || !strcmp(temp_ptr, "none")) { - temp_service->flap_detection_on_ok = FALSE; - temp_service->flap_detection_on_warning = FALSE; - temp_service->flap_detection_on_unknown = FALSE; - temp_service->flap_detection_on_critical = FALSE; + temp_service->flap_detection_options = OPT_NOTHING; } else if(!strcmp(temp_ptr, "a") || !strcmp(temp_ptr, "all")) { - temp_service->flap_detection_on_ok = TRUE; - temp_service->flap_detection_on_warning = TRUE; - temp_service->flap_detection_on_unknown = TRUE; - temp_service->flap_detection_on_critical = TRUE; + temp_service->flap_detection_options = OPT_ALL; } else { logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Invalid flap detection option '%s' in service definition.\n", temp_ptr); @@ -3028,32 +2936,22 @@ int xodtemplate_add_object_property(char *input, int options) { else if(!strcmp(variable, "notification_options")) { for(temp_ptr = strtok(value, ", "); temp_ptr; temp_ptr = strtok(NULL, ", ")) { if(!strcmp(temp_ptr, "u") || !strcmp(temp_ptr, "unknown")) - temp_service->notify_on_unknown = TRUE; + flag_set(temp_service->notification_options, OPT_UNKNOWN); else if(!strcmp(temp_ptr, "w") || !strcmp(temp_ptr, "warning")) - temp_service->notify_on_warning = TRUE; + flag_set(temp_service->notification_options, OPT_WARNING); else if(!strcmp(temp_ptr, "c") || !strcmp(temp_ptr, "critical")) - temp_service->notify_on_critical = TRUE; + flag_set(temp_service->notification_options, OPT_CRITICAL); else if(!strcmp(temp_ptr, "r") || !strcmp(temp_ptr, "recovery")) - temp_service->notify_on_recovery = TRUE; + flag_set(temp_service->notification_options, OPT_RECOVERY); else if(!strcmp(temp_ptr, "f") || !strcmp(temp_ptr, "flapping")) - temp_service->notify_on_flapping = TRUE; + flag_set(temp_service->notification_options, OPT_FLAPPING); else if(!strcmp(temp_ptr, "s") || !strcmp(temp_ptr, "downtime")) - temp_service->notify_on_downtime = TRUE; + flag_set(temp_service->notification_options, OPT_DOWNTIME); else if(!strcmp(temp_ptr, "n") || !strcmp(temp_ptr, "none")) { - temp_service->notify_on_unknown = FALSE; - temp_service->notify_on_warning = FALSE; - temp_service->notify_on_critical = FALSE; - temp_service->notify_on_recovery = FALSE; - temp_service->notify_on_flapping = FALSE; - temp_service->notify_on_downtime = FALSE; + temp_service->notification_options = OPT_NOTHING; } else if(!strcmp(temp_ptr, "a") || !strcmp(temp_ptr, "all")) { - temp_service->notify_on_unknown = TRUE; - temp_service->notify_on_warning = TRUE; - temp_service->notify_on_critical = TRUE; - temp_service->notify_on_recovery = TRUE; - temp_service->notify_on_flapping = TRUE; - temp_service->notify_on_downtime = TRUE; + temp_service->notification_options = OPT_ALL; } else { logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Invalid notification option '%s' in service definition.\n", temp_ptr); @@ -3077,24 +2975,18 @@ int xodtemplate_add_object_property(char *input, int options) { else if(!strcmp(variable, "stalking_options")) { for(temp_ptr = strtok(value, ", "); temp_ptr; temp_ptr = strtok(NULL, ", ")) { if(!strcmp(temp_ptr, "o") || !strcmp(temp_ptr, "ok")) - temp_service->stalk_on_ok = TRUE; + flag_set(temp_service->stalking_options, OPT_OK); else if(!strcmp(temp_ptr, "w") || !strcmp(temp_ptr, "warning")) - temp_service->stalk_on_warning = TRUE; + flag_set(temp_service->stalking_options, OPT_WARNING); else if(!strcmp(temp_ptr, "u") || !strcmp(temp_ptr, "unknown")) - temp_service->stalk_on_unknown = TRUE; + flag_set(temp_service->stalking_options, OPT_UNKNOWN); else if(!strcmp(temp_ptr, "c") || !strcmp(temp_ptr, "critical")) - temp_service->stalk_on_critical = TRUE; + flag_set(temp_service->stalking_options, OPT_CRITICAL); else if(!strcmp(temp_ptr, "n") || !strcmp(temp_ptr, "none")) { - temp_service->stalk_on_ok = FALSE; - temp_service->stalk_on_warning = FALSE; - temp_service->stalk_on_unknown = FALSE; - temp_service->stalk_on_critical = FALSE; + temp_service->stalking_options = OPT_NOTHING; } else if(!strcmp(temp_ptr, "a") || !strcmp(temp_ptr, "all")) { - temp_service->stalk_on_ok = TRUE; - temp_service->stalk_on_warning = TRUE; - temp_service->stalk_on_unknown = TRUE; - temp_service->stalk_on_critical = TRUE; + temp_service->stalking_options = OPT_ALL; } else { logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Invalid stalking option '%s' in service definition.\n", temp_ptr); @@ -3108,8 +3000,7 @@ int xodtemplate_add_object_property(char *input, int options) { temp_service->have_process_perf_data = TRUE; } else if(!strcmp(variable, "failure_prediction_enabled")) { - temp_service->failure_prediction_enabled = (atoi(value) > 0) ? TRUE : FALSE; - temp_service->have_failure_prediction_enabled = TRUE; + xodtemplate_obsoleted(variable, temp_service->_start_line); } else if(!strcmp(variable, "retain_status_information")) { temp_service->retain_status_information = (atoi(value) > 0) ? TRUE : FALSE; @@ -3134,7 +3025,7 @@ int xodtemplate_add_object_property(char *input, int options) { } /* get the variable value */ - if(strcmp(value, XODTEMPLATE_NULL)) + if(*value && strcmp(value, XODTEMPLATE_NULL)) customvarvalue = (char *)strdup(value); else customvarvalue = NULL; @@ -3172,7 +3063,7 @@ int xodtemplate_add_object_property(char *input, int options) { if(result == OK) { /* add dependency to template skiplist for fast searches */ - result = skiplist_insert(xobject_template_skiplists[X_HOSTDEPENDENCY_SKIPLIST], (void *)temp_hostdependency); + result = skiplist_insert(xobject_template_skiplists[HOSTDEPENDENCY_SKIPLIST], (void *)temp_hostdependency); switch(result) { case SKIPLIST_ERROR_DUPLICATE: logit(NSLOG_CONFIG_WARNING, TRUE, "Warning: Duplicate definition found for host dependency '%s' (config file '%s', starting on line %d)\n", value, xodtemplate_config_file_name(temp_hostdependency->_config_file), temp_hostdependency->_start_line); @@ -3214,20 +3105,6 @@ int xodtemplate_add_object_property(char *input, int options) { result = ERROR; } temp_hostdependency->have_dependent_host_name = TRUE; - - /* NOTE: dependencies are added to the skiplist in xodtemplate_duplicate_objects(), except if daemon is using precached config */ - if(result == OK && force_skiplists == TRUE) { - /* add hostdependency to template skiplist for fast searches */ - result = skiplist_insert(xobject_skiplists[X_HOSTDEPENDENCY_SKIPLIST], (void *)temp_hostdependency); - switch(result) { - case SKIPLIST_OK: - result = OK; - break; - default: - result = ERROR; - break; - } - } } else if(!strcmp(variable, "dependency_period")) { if(strcmp(value, XODTEMPLATE_NULL)) { @@ -3241,62 +3118,51 @@ int xodtemplate_add_object_property(char *input, int options) { temp_hostdependency->have_inherits_parent = TRUE; } else if(!strcmp(variable, "notification_failure_options") || !strcmp(variable, "notification_failure_criteria")) { + temp_hostdependency->have_notification_failure_options = TRUE; for(temp_ptr = strtok(value, ", "); temp_ptr; temp_ptr = strtok(NULL, ", ")) { if(!strcmp(temp_ptr, "o") || !strcmp(temp_ptr, "up")) - temp_hostdependency->fail_notify_on_up = TRUE; + flag_set(temp_hostdependency->notification_failure_options, OPT_UP); else if(!strcmp(temp_ptr, "d") || !strcmp(temp_ptr, "down")) - temp_hostdependency->fail_notify_on_down = TRUE; + flag_set(temp_hostdependency->notification_failure_options, OPT_DOWN); else if(!strcmp(temp_ptr, "u") || !strcmp(temp_ptr, "unreachable")) - temp_hostdependency->fail_notify_on_unreachable = TRUE; + flag_set(temp_hostdependency->notification_failure_options, OPT_UNREACHABLE); else if(!strcmp(temp_ptr, "p") || !strcmp(temp_ptr, "pending")) - temp_hostdependency->fail_notify_on_pending = TRUE; + flag_set(temp_hostdependency->notification_failure_options, OPT_PENDING); else if(!strcmp(temp_ptr, "n") || !strcmp(temp_ptr, "none")) { - temp_hostdependency->fail_notify_on_up = FALSE; - temp_hostdependency->fail_notify_on_down = FALSE; - temp_hostdependency->fail_notify_on_unreachable = FALSE; - temp_hostdependency->fail_notify_on_pending = FALSE; + temp_hostdependency->notification_failure_options = OPT_NOTHING; + temp_hostdependency->have_notification_failure_options = FALSE; } else if(!strcmp(temp_ptr, "a") || !strcmp(temp_ptr, "all")) { - temp_hostdependency->fail_notify_on_up = TRUE; - temp_hostdependency->fail_notify_on_down = TRUE; - temp_hostdependency->fail_notify_on_unreachable = TRUE; - temp_hostdependency->fail_notify_on_pending = TRUE; + temp_hostdependency->notification_failure_options = OPT_ALL; } else { logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Invalid notification dependency option '%s' in hostdependency definition.\n", temp_ptr); return ERROR; } } - temp_hostdependency->have_notification_dependency_options = TRUE; } else if(!strcmp(variable, "execution_failure_options") || !strcmp(variable, "execution_failure_criteria")) { for(temp_ptr = strtok(value, ", "); temp_ptr; temp_ptr = strtok(NULL, ", ")) { if(!strcmp(temp_ptr, "o") || !strcmp(temp_ptr, "up")) - temp_hostdependency->fail_execute_on_up = TRUE; + flag_set(temp_hostdependency->execution_failure_options, OPT_UP); else if(!strcmp(temp_ptr, "d") || !strcmp(temp_ptr, "down")) - temp_hostdependency->fail_execute_on_down = TRUE; + flag_set(temp_hostdependency->execution_failure_options, OPT_DOWN); else if(!strcmp(temp_ptr, "u") || !strcmp(temp_ptr, "unreachable")) - temp_hostdependency->fail_execute_on_unreachable = TRUE; + flag_set(temp_hostdependency->execution_failure_options, OPT_UNREACHABLE); else if(!strcmp(temp_ptr, "p") || !strcmp(temp_ptr, "pending")) - temp_hostdependency->fail_execute_on_pending = TRUE; + flag_set(temp_hostdependency->execution_failure_options, OPT_PENDING); else if(!strcmp(temp_ptr, "n") || !strcmp(temp_ptr, "none")) { - temp_hostdependency->fail_execute_on_up = FALSE; - temp_hostdependency->fail_execute_on_down = FALSE; - temp_hostdependency->fail_execute_on_unreachable = FALSE; - temp_hostdependency->fail_execute_on_pending = FALSE; + temp_hostdependency->execution_failure_options = OPT_NOTHING; } else if(!strcmp(temp_ptr, "a") || !strcmp(temp_ptr, "all")) { - temp_hostdependency->fail_execute_on_up = TRUE; - temp_hostdependency->fail_execute_on_down = TRUE; - temp_hostdependency->fail_execute_on_unreachable = TRUE; - temp_hostdependency->fail_execute_on_pending = TRUE; + temp_hostdependency->execution_failure_options = OPT_ALL; } else { logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Invalid execution dependency option '%s' in hostdependency definition.\n", temp_ptr); return ERROR; } } - temp_hostdependency->have_execution_dependency_options = TRUE; + temp_hostdependency->have_execution_failure_options = TRUE; } else if(!strcmp(variable, "register")) temp_hostdependency->register_object = (atoi(value) > 0) ? TRUE : FALSE; @@ -3323,7 +3189,7 @@ int xodtemplate_add_object_property(char *input, int options) { if(result == OK) { /* add escalation to template skiplist for fast searches */ - result = skiplist_insert(xobject_template_skiplists[X_HOSTESCALATION_SKIPLIST], (void *)temp_hostescalation); + result = skiplist_insert(xobject_template_skiplists[HOSTESCALATION_SKIPLIST], (void *)temp_hostescalation); switch(result) { case SKIPLIST_ERROR_DUPLICATE: logit(NSLOG_CONFIG_WARNING, TRUE, "Warning: Duplicate definition found for host escalation '%s' (config file '%s', starting on line %d)\n", value, xodtemplate_config_file_name(temp_hostescalation->_config_file), temp_hostescalation->_start_line); @@ -3351,22 +3217,13 @@ int xodtemplate_add_object_property(char *input, int options) { result = ERROR; } temp_hostescalation->have_host_name = TRUE; - - /* NOTE: escalations are added to the skiplist in xodtemplate_duplicate_objects(), except if daemon is using precached config */ - if(result == OK && force_skiplists == TRUE) { - /* add hostescalation to template skiplist for fast searches */ - result = skiplist_insert(xobject_skiplists[X_HOSTESCALATION_SKIPLIST], (void *)temp_hostescalation); - switch(result) { - case SKIPLIST_OK: - result = OK; - break; - default: - result = ERROR; - break; - } - } } else if(!strcmp(variable, "contact_groups")) { + if (*value == '\0') { + logit(NSLOG_CONFIG_WARNING, TRUE, "Error: Empty value for contact_groups (config file '%s', starting on line %d)\n", xodtemplate_config_file_name(temp_hostescalation->_config_file), temp_hostescalation->_start_line); + result = ERROR; + break; + } if(strcmp(value, XODTEMPLATE_NULL)) { if((temp_hostescalation->contact_groups = (char *)strdup(value)) == NULL) result = ERROR; @@ -3374,6 +3231,11 @@ int xodtemplate_add_object_property(char *input, int options) { temp_hostescalation->have_contact_groups = TRUE; } else if(!strcmp(variable, "contacts")) { + if (*value == '\0') { + logit(NSLOG_CONFIG_WARNING, TRUE, "Error: Empty value for contacts (config file '%s', starting on line %d)\n", xodtemplate_config_file_name(temp_hostescalation->_config_file), temp_hostescalation->_start_line); + result = ERROR; + break; + } if(strcmp(value, XODTEMPLATE_NULL)) { if((temp_hostescalation->contacts = (char *)strdup(value)) == NULL) result = ERROR; @@ -3402,20 +3264,16 @@ int xodtemplate_add_object_property(char *input, int options) { else if(!strcmp(variable, "escalation_options")) { for(temp_ptr = strtok(value, ", "); temp_ptr; temp_ptr = strtok(NULL, ", ")) { if(!strcmp(temp_ptr, "d") || !strcmp(temp_ptr, "down")) - temp_hostescalation->escalate_on_down = TRUE; + flag_set(temp_hostescalation->escalation_options, OPT_DOWN); else if(!strcmp(temp_ptr, "u") || !strcmp(temp_ptr, "unreachable")) - temp_hostescalation->escalate_on_unreachable = TRUE; + flag_set(temp_hostescalation->escalation_options, OPT_UNREACHABLE); else if(!strcmp(temp_ptr, "r") || !strcmp(temp_ptr, "recovery")) - temp_hostescalation->escalate_on_recovery = TRUE; + flag_set(temp_hostescalation->escalation_options, OPT_RECOVERY); else if(!strcmp(temp_ptr, "n") || !strcmp(temp_ptr, "none")) { - temp_hostescalation->escalate_on_down = FALSE; - temp_hostescalation->escalate_on_unreachable = FALSE; - temp_hostescalation->escalate_on_recovery = FALSE; + temp_hostescalation->escalation_options = OPT_NOTHING; } else if(!strcmp(temp_ptr, "a") || !strcmp(temp_ptr, "all")) { - temp_hostescalation->escalate_on_down = TRUE; - temp_hostescalation->escalate_on_unreachable = TRUE; - temp_hostescalation->escalate_on_recovery = TRUE; + temp_hostescalation->escalation_options = OPT_ALL; } else { logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Invalid escalation option '%s' in hostescalation definition.\n", temp_ptr); @@ -3448,7 +3306,7 @@ int xodtemplate_add_object_property(char *input, int options) { if(result == OK) { /* add to template skiplist for fast searches */ - result = skiplist_insert(xobject_template_skiplists[X_HOSTEXTINFO_SKIPLIST], (void *)temp_hostextinfo); + result = skiplist_insert(xobject_template_skiplists[HOSTEXTINFO_SKIPLIST], (void *)temp_hostextinfo); switch(result) { case SKIPLIST_ERROR_DUPLICATE: logit(NSLOG_CONFIG_WARNING, TRUE, "Warning: Duplicate definition found for extended host info '%s' (config file '%s', starting on line %d)\n", value, xodtemplate_config_file_name(temp_hostextinfo->_config_file), temp_hostextinfo->_start_line); @@ -3586,7 +3444,7 @@ int xodtemplate_add_object_property(char *input, int options) { if(result == OK) { /* add to template skiplist for fast searches */ - result = skiplist_insert(xobject_template_skiplists[X_SERVICEEXTINFO_SKIPLIST], (void *)temp_serviceextinfo); + result = skiplist_insert(xobject_template_skiplists[SERVICEEXTINFO_SKIPLIST], (void *)temp_serviceextinfo); switch(result) { case SKIPLIST_ERROR_DUPLICATE: logit(NSLOG_CONFIG_WARNING, TRUE, "Warning: Duplicate definition found for extended service info '%s' (config file '%s', starting on line %d)\n", value, xodtemplate_config_file_name(temp_serviceextinfo->_config_file), temp_serviceextinfo->_start_line); @@ -3671,19 +3529,52 @@ int xodtemplate_add_object_property(char *input, int options) { break; } - /* free memory */ - my_free(variable); - my_free(value); - return result; } +#define xod_check_complete(otype) \ + do { \ + xodtemplate_##otype *o = (xodtemplate_##otype *)xodtemplate_current_object; \ + if (o->register_object && !o->otype##_name && !o->name) { \ + return ERROR; \ + } \ + } while(0) /* completes an object definition */ int xodtemplate_end_object_definition(int options) { int result = OK; + switch(xodtemplate_current_object_type) { + case XODTEMPLATE_HOSTESCALATION: + xodcount.hostescalations += !!use_precached_objects; + break; + case XODTEMPLATE_SERVICEESCALATION: + xodcount.serviceescalations += !!use_precached_objects; + break; + case XODTEMPLATE_TIMEPERIOD: + xod_check_complete(timeperiod); + break; + case XODTEMPLATE_COMMAND: + xod_check_complete(command); + break; + case XODTEMPLATE_CONTACT: + xod_check_complete(contact); + break; + case XODTEMPLATE_CONTACTGROUP: + xod_check_complete(contactgroup); + break; + case XODTEMPLATE_HOST: + xod_check_complete(host); + break; + case XODTEMPLATE_HOSTGROUP: + xod_check_complete(hostgroup); + break; + case XODTEMPLATE_SERVICEGROUP: + xod_check_complete(servicegroup); + break; + } + xodtemplate_current_object = NULL; xodtemplate_current_object_type = XODTEMPLATE_NONE; @@ -3736,7 +3627,7 @@ xodtemplate_customvariablesmember *xodtemplate_add_custom_variable_to_object(xod my_free(new_customvariablesmember); return NULL; } - if(varvalue) { + if(varvalue && *varvalue) { if((new_customvariablesmember->variable_value = (char *)strdup(varvalue)) == NULL) { my_free(new_customvariablesmember->variable_name); my_free(new_customvariablesmember); @@ -3759,7 +3650,7 @@ xodtemplate_customvariablesmember *xodtemplate_add_custom_variable_to_object(xod -/* parses a timeperod directive... :-) */ +/* parses a timeperiod directive... :-) */ int xodtemplate_parse_timeperiod_directive(xodtemplate_timeperiod *tperiod, char *var, char *val) { char *input = NULL; char temp_buffer[5][MAX_INPUT_BUFFER] = {"", "", "", "", ""}; @@ -4061,7 +3952,7 @@ xodtemplate_daterange *xodtemplate_add_exception_to_timeperiod(xodtemplate_timep int xodtemplate_get_month_from_string(char *str, int *month) { - char *months[12] = {"january", "february", "march", "april", "may", "june", "july", "august", "september", "october", "november", "december"}; + const char *months[12] = {"january", "february", "march", "april", "may", "june", "july", "august", "september", "october", "november", "december"}; int x = 0; if(str == NULL || month == NULL) @@ -4081,7 +3972,7 @@ int xodtemplate_get_month_from_string(char *str, int *month) { int xodtemplate_get_weekday_from_string(char *str, int *weekday) { - char *days[7] = {"sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"}; + const char *days[7] = {"sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"}; int x = 0; if(str == NULL || weekday == NULL) @@ -4109,83 +4000,105 @@ int xodtemplate_get_weekday_from_string(char *str, int *weekday) { int xodtemplate_duplicate_services(void) { int result = OK; xodtemplate_service *temp_service = NULL; - xodtemplate_memberlist *temp_memberlist = NULL; - xodtemplate_memberlist *temp_rejectlist = NULL; - xodtemplate_memberlist *this_memberlist = NULL; - char *host_name = NULL; - int first_item = FALSE; - + xodcount.services = 0; /****** DUPLICATE SERVICE DEFINITIONS WITH ONE OR MORE HOSTGROUP AND/OR HOST NAMES ******/ for(temp_service = xodtemplate_service_list; temp_service != NULL; temp_service = temp_service->next) { + objectlist *hlist = NULL, *list = NULL, *glist = NULL, *next; + xodtemplate_hostgroup fake_hg; - /* skip service definitions without enough data */ - if(temp_service->hostgroup_name == NULL && temp_service->host_name == NULL) - continue; - - /* If hostgroup is not null and hostgroup has no members, check to see if */ - /* allow_empty_hostgroup_assignment is set to 1 - if it is, continue without error */ - if(temp_service->hostgroup_name != NULL) { - if(xodtemplate_expand_hostgroups(&temp_memberlist, &temp_rejectlist, temp_service->hostgroup_name, temp_service->_config_file, temp_service->_start_line) == ERROR) { - return ERROR; - } - else { - xodtemplate_free_memberlist(&temp_rejectlist); - if(temp_memberlist != NULL) { - xodtemplate_free_memberlist(&temp_memberlist); - } - else { - /* User is ok with hostgroup -> service mappings with no hosts */ - if(allow_empty_hostgroup_assignment == 1) { - continue; - } - } - } - } + /* clear for each round */ + bitmap_clear(host_map); /* skip services that shouldn't be registered */ if(temp_service->register_object == FALSE) continue; - /* get list of hosts */ - temp_memberlist = xodtemplate_expand_hostgroups_and_hosts(temp_service->hostgroup_name, temp_service->host_name, temp_service->_config_file, temp_service->_start_line); - if(temp_memberlist == NULL) { - logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not expand hostgroups and/or hosts specified in service (config file '%s', starting on line %d)\n", xodtemplate_config_file_name(temp_service->_config_file), temp_service->_start_line); + /* bail out on service definitions without enough data */ + if((temp_service->hostgroup_name == NULL && temp_service->host_name == NULL) || temp_service->service_description == NULL) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Service has no hosts and/or service_description (config file '%s', starting on line %d)\n", xodtemplate_config_file_name(temp_service->_config_file), temp_service->_start_line); return ERROR; } - /* add a copy of the service for every host in the hostgroup/host name list */ - first_item = TRUE; - for(this_memberlist = temp_memberlist; this_memberlist != NULL; this_memberlist = this_memberlist->next) { + if(temp_service->hostgroup_name != NULL) { + if(xodtemplate_expand_hostgroups(&glist, host_map, temp_service->hostgroup_name, temp_service->_config_file, temp_service->_start_line) == ERROR) { + return ERROR; + } + /* no longer needed */ + my_free(temp_service->hostgroup_name); - /* if this is the first duplication, use the existing entry */ - if(first_item == TRUE) { - - my_free(temp_service->host_name); - temp_service->host_name = (char *)strdup(this_memberlist->name1); - if(temp_service->host_name == NULL) { - xodtemplate_free_memberlist(&temp_memberlist); + /* empty result is only bad if allow_empty_hostgroup_assignment is off */ + if(!glist && !bitmap_count_set_bits(host_map)) { + if(!allow_empty_hostgroup_assignment) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not expand hostgroups and/or hosts specified in service (config file '%s', starting on line %d)\n", xodtemplate_config_file_name(temp_service->_config_file), temp_service->_start_line); return ERROR; } - - first_item = FALSE; - continue; - } - - /* duplicate service definition */ - result = xodtemplate_duplicate_service(temp_service, this_memberlist->name1); - - /* exit on error */ - if(result == ERROR) { - my_free(host_name); - return ERROR; + else if (allow_empty_hostgroup_assignment == 2) { + logit(NSLOG_CONFIG_WARNING, TRUE, "Warning: Could not expand hostgroups and/or hosts specified in service (config file '%s', starting on line %d)\n", xodtemplate_config_file_name(temp_service->_config_file), temp_service->_start_line); + } } } - /* free memory we used for host list */ - xodtemplate_free_memberlist(&temp_memberlist); + /* now find direct hosts */ + if(temp_service->host_name) { + if (xodtemplate_expand_hosts(&hlist, host_map, temp_service->host_name, temp_service->_config_file, temp_service->_start_line) != OK) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Failed to expand host list '%s' for service '%s' (%s:%d)\n", + temp_service->host_name, temp_service->service_description, + xodtemplate_config_file_name(temp_service->_config_file), + temp_service->_start_line); + return ERROR; + } + /* we don't need this anymore now that we have the hlist */ + my_free(temp_service->host_name); } + /* + * host_map now contains all rejected hosts + * group_map contains all rejected hostgroups + * hlist contains all hosts we're directly assigned to. + * glist contains all hostgroups we're assigned to. + * We ignore hostgroups we're assigned to that are also rejected. + * We do a dirty trick here and prepend a fake hostgroup + * to the hostgroup list so we can use the same loop for + * the rest of the code. + */ + fake_hg.hostgroup_name = "!!FAKE HOSTGROUP"; + fake_hg.member_list = hlist; + prepend_object_to_objectlist(&glist, &fake_hg); + for(list = glist; list; list = next) { + xodtemplate_hostgroup *hg = (xodtemplate_hostgroup *)list->object_ptr; + next = list->next; + free(list); + + /* we don't free this list */ + for(hlist = hg->member_list; hlist; hlist = hlist->next) { + xodtemplate_host *h = (xodtemplate_host *)hlist->object_ptr; + + /* ignore this host if it's rejected */ + if(bitmap_isset(host_map, h->id)) + continue; + + /* + * reject more copies of this host. This happens + * if the service is assigned to multiple hostgroups + * where the same host is part of more than one of + * them + */ + bitmap_set(host_map, h->id); + + /* if this is the last duplication, use the existing entry */ + if(!next && !hlist->next) { + temp_service->id = xodcount.services++; + temp_service->host_name = h->host_name; + } + else { + /* duplicate service definition */ + result = xodtemplate_duplicate_service(temp_service, h->host_name, hg != &fake_hg); + } + } + free_objectlist(&fake_hg.member_list); + } + } /***************************************/ /* SKIPLIST STUFF FOR FAST SORT/SEARCH */ @@ -4193,7 +4106,6 @@ int xodtemplate_duplicate_services(void) { /* First loop for single host service definition*/ for(temp_service = xodtemplate_service_list; temp_service != NULL; temp_service = temp_service->next) { - /* skip services that shouldn't be registered */ if(temp_service->register_object == FALSE) continue; @@ -4202,12 +4114,12 @@ int xodtemplate_duplicate_services(void) { if(temp_service->host_name == NULL || temp_service->service_description == NULL) continue; - if(xodtemplate_is_service_is_from_hostgroup(temp_service)) { + if(temp_service->is_from_hostgroup) { continue; } - result = skiplist_insert(xobject_skiplists[X_SERVICE_SKIPLIST], (void *)temp_service); + result = skiplist_insert(xobject_skiplists[SERVICE_SKIPLIST], (void *)temp_service); switch(result) { case SKIPLIST_ERROR_DUPLICATE: logit(NSLOG_CONFIG_WARNING, TRUE, "Warning: Duplicate definition found for service '%s' on host '%s' (config file '%s', starting on line %d)\n", temp_service->service_description, temp_service->host_name, xodtemplate_config_file_name(temp_service->_config_file), temp_service->_start_line); @@ -4235,13 +4147,13 @@ int xodtemplate_duplicate_services(void) { if(temp_service->host_name == NULL || temp_service->service_description == NULL) continue; - if(!xodtemplate_is_service_is_from_hostgroup(temp_service)) { + if(!temp_service->is_from_hostgroup) { continue; } - /*The flag X_SERVICE_IS_FROM_HOSTGROUP is set, unset it*/ - xodtemplate_unset_service_is_from_hostgroup(temp_service); - result = skiplist_insert(xobject_skiplists[X_SERVICE_SKIPLIST], (void *)temp_service); + temp_service->is_from_hostgroup = 0; + + result = skiplist_insert(xobject_skiplists[SERVICE_SKIPLIST], (void *)temp_service); switch(result) { case SKIPLIST_ERROR_DUPLICATE: logit(NSLOG_CONFIG_WARNING, TRUE, "Warning: Duplicate definition found for service '%s' on host '%s' (config file '%s', starting on line %d)\n", temp_service->service_description, temp_service->host_name, xodtemplate_config_file_name(temp_service->_config_file), temp_service->_start_line); @@ -4260,25 +4172,143 @@ int xodtemplate_duplicate_services(void) { } +/** + * Create an objectlist of services from whatever someone put into a + * servicedescription. Rules go like this: + * NOT servicegroup: + * If we have host_name and service_description, we do a simple + * lookup. + * If we have host_name and/or hostgroup_name and service_description, + * we do multiple lookups and concatenate the results. + * If we have host_name/hostgroup_name and service_description, we do multiple + * simple lookups and concatenate the results. + */ +static int xodtemplate_create_service_list(objectlist **ret, bitmap *reject_map, char *host_name, char *hostgroup_name, char *servicegroup_name, char *service_description, int _config_file, int _start_line) +{ + objectlist *hlist = NULL, *hglist = NULL, *slist = NULL, *sglist = NULL; + objectlist *glist, *gnext, *list, *next; /* iterators */ + xodtemplate_hostgroup fake_hg; + bitmap *in; + + /* + * if we have a service_description, we need host_name + * or host_group name + */ + if(service_description && !host_name && !hostgroup_name) + return ERROR; + /* + * if we have host_name or a hostgroup_name we also need + * service_description + */ + if((host_name || hostgroup_name) && !service_description) + return ERROR; + + /* we'll need these */ + bitmap_clear(host_map); + if (!(in = bitmap_create(xodcount.services))) + return ERROR; + + /* + * all services in the accepted servicegroups can be added, except + * if they're also in service_map, in which case they're also + * in rejected servicegroups and must NOT be added + */ + if(servicegroup_name && xodtemplate_expand_servicegroups(&sglist, reject_map, servicegroup_name, _config_file, _start_line) != OK) + return ERROR; + for(glist = sglist; glist; glist = gnext) { + xodtemplate_servicegroup *sg = (xodtemplate_servicegroup *)glist->object_ptr; + gnext = glist->next; + free(glist); /* free it as we go along */ + for(list = sg->member_list; list; list = list->next) { + xodtemplate_service *s = (xodtemplate_service *)list->object_ptr; + + /* rejected or already added */ + if(bitmap_isset(in, s->id) || bitmap_isset(reject_map, s->id)) + continue; + bitmap_set(in, s->id); + if(prepend_object_to_objectlist(ret, s) != OK) { + free_objectlist(&gnext); + return ERROR; + } + } + } + + /* + * get the lists we'll need, with reject markers included. + * We have to get both hostlist and hostgroup list at once + * to get the full reject markers. + */ + if(host_name && xodtemplate_expand_hosts(&hlist, host_map, host_name, _config_file, _start_line) != OK) + return ERROR; + if(hostgroup_name && xodtemplate_expand_hostgroups(&hglist, host_map, hostgroup_name, _config_file, _start_line) != OK) { + free_objectlist(&hlist); + return ERROR; + } + + /* + * if hlist isn't NULL, we add a fake hostgroup to the mix so we + * can get away with a single loop, but we must always set its + * memberlist so we can safely call free_objectlist() on it. + */ + fake_hg.member_list = hlist; + if(hlist) { + if(prepend_object_to_objectlist(&hglist, &fake_hg) != OK) { + free_objectlist(&hlist); + free_objectlist(&hglist); + bitmap_destroy(in); + return ERROR; + } + } + + for(glist = hglist; glist; glist = gnext) { + xodtemplate_hostgroup *hg = (xodtemplate_hostgroup *)glist->object_ptr; + gnext = glist->next; + free(glist); + + for(hlist = hg->member_list; hlist; hlist = hlist->next) { + xodtemplate_host *h = (xodtemplate_host *)hlist->object_ptr; + if(bitmap_isset(host_map, h->id)) + continue; + + /* expand services and add them all, unless they're rejected */ + slist = NULL; + if(xodtemplate_expand_services(&slist, reject_map, h->host_name, service_description, _config_file, _start_line) != OK) { + free_objectlist(&gnext); + bitmap_destroy(in); + return ERROR; + } + for(list = slist; list; list = next) { + xodtemplate_service *s = (xodtemplate_service *)list->object_ptr; + next = list->next; + free(list); + if(bitmap_isset(in, s->id) || bitmap_isset(reject_map, s->id)) + continue; + bitmap_set(in, s->id); + if(prepend_object_to_objectlist(ret, s) != OK) { + free_objectlist(&next); + free_objectlist(&gnext); + free_objectlist(&fake_hg.member_list); + bitmap_destroy(in); + return ERROR; + } + } + } + } + + bitmap_destroy(in); + free_objectlist(&fake_hg.member_list); + return OK; +} /* duplicates object definitions */ int xodtemplate_duplicate_objects(void) { int result = OK; xodtemplate_hostescalation *temp_hostescalation = NULL; xodtemplate_serviceescalation *temp_serviceescalation = NULL; - xodtemplate_hostdependency *temp_hostdependency = NULL; - xodtemplate_servicedependency *temp_servicedependency = NULL; - xodtemplate_hostextinfo *temp_hostextinfo = NULL; - xodtemplate_serviceextinfo *temp_serviceextinfo = NULL; - - xodtemplate_memberlist *master_hostlist = NULL, *dependent_hostlist = NULL; - xodtemplate_memberlist *master_servicelist = NULL, *dependent_servicelist = NULL; - xodtemplate_memberlist *temp_masterhost = NULL, *temp_dependenthost = NULL; - xodtemplate_memberlist *temp_masterservice = NULL, *temp_dependentservice = NULL; - - char *service_descriptions = NULL; - int first_item = FALSE; - int same_host_servicedependency = FALSE; + xodtemplate_hostextinfo *next_he = NULL, *temp_hostextinfo = NULL; + xodtemplate_serviceextinfo *next_se = NULL, *temp_serviceextinfo = NULL; + objectlist *master_hostlist, *master_servicelist; + objectlist *list, *next; /*************************************/ @@ -4286,7 +4316,7 @@ int xodtemplate_duplicate_objects(void) { /*************************************/ - /****** DUPLICATE HOST ESCALATION DEFINITIONS WITH ONE OR MORE HOSTGROUP AND/OR HOST NAMES ******/ + /* duplicate host escalations */ for(temp_hostescalation = xodtemplate_hostescalation_list; temp_hostescalation != NULL; temp_hostescalation = temp_hostescalation->next) { /* skip host escalation definitions without enough data */ @@ -4301,606 +4331,93 @@ int xodtemplate_duplicate_objects(void) { } /* add a copy of the hostescalation for every host in the hostgroup/host name list */ - first_item = TRUE; - for(temp_masterhost = master_hostlist; temp_masterhost != NULL; temp_masterhost = temp_masterhost->next) { + for(list = master_hostlist; list; list = next) { + xodtemplate_host *h = (xodtemplate_host *)list->object_ptr; + next = list->next; + free(list); - /* if this is the first duplication, use the existing entry */ - if(first_item == TRUE) { + xodcount.hostescalations++; + /* if this is the last duplication, use the existing entry */ + if(!next) { + my_free(temp_hostescalation->name); + my_free(temp_hostescalation->template); my_free(temp_hostescalation->host_name); - temp_hostescalation->host_name = (char *)strdup(temp_masterhost->name1); - if(temp_hostescalation->host_name == NULL) { - xodtemplate_free_memberlist(&master_hostlist); - return ERROR; - } - - first_item = FALSE; + my_free(temp_hostescalation->hostgroup_name); + temp_hostescalation->host_name = h->host_name; continue; } /* duplicate hostescalation definition */ - result = xodtemplate_duplicate_hostescalation(temp_hostescalation, temp_masterhost->name1); + result = xodtemplate_duplicate_hostescalation(temp_hostescalation, h->host_name); /* exit on error */ if(result == ERROR) { - xodtemplate_free_memberlist(&master_hostlist); + free_objectlist(&next); return ERROR; } } - - /* free memory we used for host list */ - xodtemplate_free_memberlist(&master_hostlist); } + timing_point("Created %u hostescalations (dupes possible)\n", xodcount.hostescalations); - /****** DUPLICATE SERVICE ESCALATION DEFINITIONS WITH ONE OR MORE HOSTGROUP AND/OR HOST NAMES ******/ - for(temp_serviceescalation = xodtemplate_serviceescalation_list; temp_serviceescalation != NULL; temp_serviceescalation = temp_serviceescalation->next) { - - /* skip service escalation definitions without enough data */ - if(temp_serviceescalation->hostgroup_name == NULL && temp_serviceescalation->host_name == NULL) - continue; - - /* get list of hosts */ - master_hostlist = xodtemplate_expand_hostgroups_and_hosts(temp_serviceescalation->hostgroup_name, temp_serviceescalation->host_name, temp_serviceescalation->_config_file, temp_serviceescalation->_start_line); - if(master_hostlist == NULL) { - logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not expand hostgroups and/or hosts specified in service escalation (config file '%s', starting on line %d)\n", xodtemplate_config_file_name(temp_serviceescalation->_config_file), temp_serviceescalation->_start_line); - return ERROR; - } - - /* duplicate service escalation entries */ - first_item = TRUE; - for(temp_masterhost = master_hostlist; temp_masterhost != NULL; temp_masterhost = temp_masterhost->next) { - - /* if this is the first duplication,use the existing entry */ - if(first_item == TRUE) { - - my_free(temp_serviceescalation->host_name); - temp_serviceescalation->host_name = (char *)strdup(temp_masterhost->name1); - if(temp_serviceescalation->host_name == NULL) { - xodtemplate_free_memberlist(&master_hostlist); - return ERROR; - } - - first_item = FALSE; - continue; - } - - /* duplicate service escalation definition */ - result = xodtemplate_duplicate_serviceescalation(temp_serviceescalation, temp_masterhost->name1, temp_serviceescalation->service_description); - - /* exit on error */ - if(result == ERROR) { - xodtemplate_free_memberlist(&master_hostlist); - return ERROR; - } - } - - /* free memory we used for host list */ - xodtemplate_free_memberlist(&master_hostlist); - } - - - /****** DUPLICATE SERVICE ESCALATION DEFINITIONS WITH MULTIPLE DESCRIPTIONS ******/ - /* THIS MUST BE DONE AFTER DUPLICATING FOR MULTIPLE HOST NAMES (SEE ABOVE) */ + /* duplicate service escalations */ for(temp_serviceescalation = xodtemplate_serviceescalation_list; temp_serviceescalation != NULL; temp_serviceescalation = temp_serviceescalation->next) { /* skip serviceescalations without enough data */ - if(temp_serviceescalation->service_description == NULL || temp_serviceescalation->host_name == NULL) + if(temp_serviceescalation->servicegroup_name == NULL && temp_serviceescalation->service_description == NULL && (temp_serviceescalation->host_name == NULL || temp_serviceescalation->hostgroup_name == NULL)) + continue; + if(temp_serviceescalation->register_object == FALSE) continue; + bitmap_clear(service_map); + + master_servicelist = NULL; + /* get list of services */ - master_servicelist = xodtemplate_expand_servicegroups_and_services(NULL, temp_serviceescalation->host_name, temp_serviceescalation->service_description, temp_serviceescalation->_config_file, temp_serviceescalation->_start_line); - if(master_servicelist == NULL) { - logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not expand services specified in service escalation (config file '%s', starting on line %d)\n", xodtemplate_config_file_name(temp_serviceescalation->_config_file), temp_serviceescalation->_start_line); + if(xodtemplate_create_service_list(&master_servicelist, service_map, temp_serviceescalation->host_name, temp_serviceescalation->hostgroup_name, temp_serviceescalation->servicegroup_name, temp_serviceescalation->service_description, temp_serviceescalation->_config_file, temp_serviceescalation->_start_line) != OK) return ERROR; - } + + /* we won't need these anymore */ + my_free(temp_serviceescalation->host_name); + my_free(temp_serviceescalation->hostgroup_name); + my_free(temp_serviceescalation->service_description); + my_free(temp_serviceescalation->servicegroup_name); /* duplicate service escalation entries */ - first_item = TRUE; - for(temp_masterservice = master_servicelist; temp_masterservice != NULL; temp_masterservice = temp_masterservice->next) { + for(list = master_servicelist; list; list = next) { + xodtemplate_service *s = (xodtemplate_service *)list->object_ptr; + next = list->next; + free(list); - /* if this is the first duplication, use the existing entry */ - if(first_item == TRUE) { + if(bitmap_isset(service_map, s->id)) + continue; - my_free(temp_serviceescalation->service_description); - temp_serviceescalation->service_description = (char *)strdup(temp_masterservice->name2); - if(temp_serviceescalation->service_description == NULL) { - xodtemplate_free_memberlist(&master_servicelist); - return ERROR; - } + xodcount.serviceescalations++; - first_item = FALSE; + /* if this is the last duplication, use the existing entry */ + if(!next) { + temp_serviceescalation->host_name = s->host_name; + temp_serviceescalation->service_description = s->service_description; continue; } /* duplicate service escalation definition */ - result = xodtemplate_duplicate_serviceescalation(temp_serviceescalation, temp_serviceescalation->host_name, temp_masterservice->name2); + result = xodtemplate_duplicate_serviceescalation(temp_serviceescalation, s->host_name, s->service_description); /* exit on error */ if(result == ERROR) { - xodtemplate_free_memberlist(&master_servicelist); + free_objectlist(&next); return ERROR; } } - - /* free memory we used for service list */ - xodtemplate_free_memberlist(&master_servicelist); } - - - - /****** DUPLICATE SERVICE ESCALATION DEFINITIONS WITH SERVICEGROUPS ******/ - /* THIS MUST BE DONE AFTER DUPLICATING FOR MULTIPLE HOST NAMES (SEE ABOVE) */ - for(temp_serviceescalation = xodtemplate_serviceescalation_list; temp_serviceescalation != NULL; temp_serviceescalation = temp_serviceescalation->next) { - - /* skip serviceescalations without enough data */ - if(temp_serviceescalation->servicegroup_name == NULL) - continue; - - /* get list of services */ - master_servicelist = xodtemplate_expand_servicegroups_and_services(temp_serviceescalation->servicegroup_name, NULL, NULL, temp_serviceescalation->_config_file, temp_serviceescalation->_start_line); - if(master_servicelist == NULL) { - logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not expand servicegroups specified in service escalation (config file '%s', starting on line %d)\n", xodtemplate_config_file_name(temp_serviceescalation->_config_file), temp_serviceescalation->_start_line); - return ERROR; - } - - /* duplicate service escalation entries */ - first_item = TRUE; - for(temp_masterservice = master_servicelist; temp_masterservice != NULL; temp_masterservice = temp_masterservice->next) { - - /* if this is the first duplication, use the existing entry if possible */ - if(first_item == TRUE && temp_serviceescalation->host_name == NULL && temp_serviceescalation->service_description == NULL) { - - my_free(temp_serviceescalation->host_name); - temp_serviceescalation->host_name = (char *)strdup(temp_masterservice->name1); - - my_free(temp_serviceescalation->service_description); - temp_serviceescalation->service_description = (char *)strdup(temp_masterservice->name2); - - if(temp_serviceescalation->host_name == NULL || temp_serviceescalation->service_description == NULL) { - xodtemplate_free_memberlist(&master_servicelist); - return ERROR; - } - - first_item = FALSE; - continue; - } - - /* duplicate service escalation definition */ - result = xodtemplate_duplicate_serviceescalation(temp_serviceescalation, temp_masterservice->name1, temp_masterservice->name2); - - /* exit on error */ - if(result == ERROR) { - xodtemplate_free_memberlist(&master_servicelist); - return ERROR; - } - } - - /* free memory we used for service list */ - xodtemplate_free_memberlist(&master_servicelist); - } - - - /****** DUPLICATE HOST DEPENDENCY DEFINITIONS WITH MULTIPLE HOSTGROUP AND/OR HOST NAMES (MASTER AND DEPENDENT) ******/ - for(temp_hostdependency = xodtemplate_hostdependency_list; temp_hostdependency != NULL; temp_hostdependency = temp_hostdependency->next) { - - /* skip host dependencies without enough data */ - if(temp_hostdependency->hostgroup_name == NULL && temp_hostdependency->dependent_hostgroup_name == NULL && temp_hostdependency->host_name == NULL && temp_hostdependency->dependent_host_name == NULL) - continue; - - /* get list of master host names */ - master_hostlist = xodtemplate_expand_hostgroups_and_hosts(temp_hostdependency->hostgroup_name, temp_hostdependency->host_name, temp_hostdependency->_config_file, temp_hostdependency->_start_line); - if(master_hostlist == NULL && allow_empty_hostgroup_assignment == 0) { - logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not expand master hostgroups and/or hosts specified in host dependency (config file '%s', starting on line %d)\n", xodtemplate_config_file_name(temp_hostdependency->_config_file), temp_hostdependency->_start_line); - return ERROR; - } - - /* get list of dependent host names */ - dependent_hostlist = xodtemplate_expand_hostgroups_and_hosts(temp_hostdependency->dependent_hostgroup_name, temp_hostdependency->dependent_host_name, temp_hostdependency->_config_file, temp_hostdependency->_start_line); - if(dependent_hostlist == NULL && allow_empty_hostgroup_assignment == 0) { - logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not expand dependent hostgroups and/or hosts specified in host dependency (config file '%s', starting on line %d)\n", xodtemplate_config_file_name(temp_hostdependency->_config_file), temp_hostdependency->_start_line); - xodtemplate_free_memberlist(&master_hostlist); - return ERROR; - } - - /* duplicate the dependency definitions */ - first_item = TRUE; - for(temp_masterhost = master_hostlist; temp_masterhost != NULL; temp_masterhost = temp_masterhost->next) { - - for(temp_dependenthost = dependent_hostlist; temp_dependenthost != NULL; temp_dependenthost = temp_dependenthost->next) { - - /* temp=master, this=dep */ - - /* existing definition gets first names */ - if(first_item == TRUE) { - my_free(temp_hostdependency->host_name); - my_free(temp_hostdependency->dependent_host_name); - temp_hostdependency->host_name = (char *)strdup(temp_masterhost->name1); - temp_hostdependency->dependent_host_name = (char *)strdup(temp_dependenthost->name1); - first_item = FALSE; - continue; - } - else - result = xodtemplate_duplicate_hostdependency(temp_hostdependency, temp_masterhost->name1, temp_dependenthost->name1); - /* exit on error */ - if(result == ERROR) { - xodtemplate_free_memberlist(&master_hostlist); - xodtemplate_free_memberlist(&dependent_hostlist); - return ERROR; - } - } - } - - /* free memory used to store host lists */ - xodtemplate_free_memberlist(&master_hostlist); - xodtemplate_free_memberlist(&dependent_hostlist); - } - - - - /****** PROCESS SERVICE DEPENDENCIES WITH MASTER SERVICEGROUPS *****/ - for(temp_servicedependency = xodtemplate_servicedependency_list; temp_servicedependency != NULL; temp_servicedependency = temp_servicedependency->next) { - - /* skip templates */ - if(temp_servicedependency->register_object == 0) - continue; - - /* expand master servicegroups into a list of services */ - if(temp_servicedependency->servicegroup_name) { - - master_servicelist = xodtemplate_expand_servicegroups_and_services(temp_servicedependency->servicegroup_name, NULL, NULL, temp_servicedependency->_config_file, temp_servicedependency->_start_line); - if(master_servicelist == NULL) { - logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not expand master servicegroups specified in service dependency (config file '%s', starting on line %d)\n", xodtemplate_config_file_name(temp_servicedependency->_config_file), temp_servicedependency->_start_line); - return ERROR; - } - - /* if dependency also has master host, hostgroup, and/or service, we must split that off to another definition */ - if(temp_servicedependency->host_name != NULL || temp_servicedependency->hostgroup_name != NULL || temp_servicedependency->service_description != NULL) { - - /* duplicate everything except master servicegroup */ - xodtemplate_duplicate_servicedependency(temp_servicedependency, temp_servicedependency->host_name, temp_servicedependency->service_description, temp_servicedependency->hostgroup_name, NULL, temp_servicedependency->dependent_host_name, temp_servicedependency->dependent_service_description, temp_servicedependency->dependent_hostgroup_name, temp_servicedependency->dependent_servicegroup_name); - - /* clear values in this definition */ - temp_servicedependency->have_host_name = FALSE; - temp_servicedependency->have_service_description = FALSE; - temp_servicedependency->have_hostgroup_name = FALSE; - my_free(temp_servicedependency->host_name); - my_free(temp_servicedependency->service_description); - my_free(temp_servicedependency->hostgroup_name); - } - - /* duplicate service dependency entries */ - first_item = TRUE; - for(temp_masterservice = master_servicelist; temp_masterservice != NULL; temp_masterservice = temp_masterservice->next) { - - /* just in case */ - if(temp_masterservice->name1 == NULL || temp_masterservice->name2 == NULL) - continue; - - /* if this is the first duplication, use the existing entry */ - if(first_item == TRUE) { - - my_free(temp_servicedependency->host_name); - temp_servicedependency->host_name = (char *)strdup(temp_masterservice->name1); - - my_free(temp_servicedependency->service_description); - temp_servicedependency->service_description = (char *)strdup(temp_masterservice->name2); - - /* clear the master servicegroup */ - temp_servicedependency->have_servicegroup_name = FALSE; - my_free(temp_servicedependency->servicegroup_name); - - if(temp_servicedependency->host_name == NULL || temp_servicedependency->service_description == NULL) { - xodtemplate_free_memberlist(&master_servicelist); - return ERROR; - } - - first_item = FALSE; - continue; - } - - /* duplicate service dependency definition */ - result = xodtemplate_duplicate_servicedependency(temp_servicedependency, temp_masterservice->name1, temp_masterservice->name2, NULL, NULL, temp_servicedependency->dependent_host_name, temp_servicedependency->dependent_service_description, temp_servicedependency->dependent_hostgroup_name, temp_servicedependency->dependent_servicegroup_name); - - /* exit on error */ - if(result == ERROR) { - xodtemplate_free_memberlist(&master_servicelist); - return ERROR; - } - } - - /* free memory we used for service list */ - xodtemplate_free_memberlist(&master_servicelist); - } - } - - - /****** PROCESS SERVICE DEPENDENCY MASTER HOSTS/HOSTGROUPS/SERVICES *****/ - for(temp_servicedependency = xodtemplate_servicedependency_list; temp_servicedependency != NULL; temp_servicedependency = temp_servicedependency->next) { - - /* skip templates */ - if(temp_servicedependency->register_object == 0) - continue; - - /* expand master hosts/hostgroups into a list of host names */ - if(temp_servicedependency->host_name != NULL || temp_servicedependency->hostgroup_name != NULL) { - -#ifdef DEBUG_SERVICE_DEPENDENCIES - printf("1a) H: %s HG: %s SD: %s\n", temp_servicedependency->host_name, temp_servicedependency->hostgroup_name, temp_servicedependency->service_description); -#endif - - master_hostlist = xodtemplate_expand_hostgroups_and_hosts(temp_servicedependency->hostgroup_name, temp_servicedependency->host_name, temp_servicedependency->_config_file, temp_servicedependency->_start_line); - if(master_hostlist == NULL && allow_empty_hostgroup_assignment == 0) { - logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not expand master hostgroups and/or hosts specified in service dependency (config file '%s', starting on line %d)\n", xodtemplate_config_file_name(temp_servicedependency->_config_file), temp_servicedependency->_start_line); - return ERROR; - } - - /* save service descriptions for later */ - if(temp_servicedependency->service_description) - service_descriptions = (char *)strdup(temp_servicedependency->service_description); - - /* for each host, expand master services */ - first_item = TRUE; - for(temp_masterhost = master_hostlist; temp_masterhost != NULL; temp_masterhost = temp_masterhost->next) { - - master_servicelist = xodtemplate_expand_servicegroups_and_services(NULL, temp_masterhost->name1, service_descriptions, temp_servicedependency->_config_file, temp_servicedependency->_start_line); - if(master_servicelist == NULL) { - logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not expand master services specified in service dependency (config file '%s', starting on line %d)\n", xodtemplate_config_file_name(temp_servicedependency->_config_file), temp_servicedependency->_start_line); - return ERROR; - } - - /* duplicate service dependency entries */ - for(temp_masterservice = master_servicelist; temp_masterservice != NULL; temp_masterservice = temp_masterservice->next) { - - /* just in case */ - if(temp_masterservice->name1 == NULL || temp_masterservice->name2 == NULL) - continue; - - /* if this is the first duplication, use the existing entry */ - if(first_item == TRUE) { - - my_free(temp_servicedependency->host_name); - temp_servicedependency->host_name = (char *)strdup(temp_masterhost->name1); - - my_free(temp_servicedependency->service_description); - temp_servicedependency->service_description = (char *)strdup(temp_masterservice->name2); - - if(temp_servicedependency->host_name == NULL || temp_servicedependency->service_description == NULL) { - xodtemplate_free_memberlist(&master_hostlist); - xodtemplate_free_memberlist(&master_servicelist); - return ERROR; - } - - first_item = FALSE; - continue; - } - - /* duplicate service dependency definition */ - result = xodtemplate_duplicate_servicedependency(temp_servicedependency, temp_masterhost->name1, temp_masterservice->name2, NULL, NULL, temp_servicedependency->dependent_host_name, temp_servicedependency->dependent_service_description, temp_servicedependency->dependent_hostgroup_name, temp_servicedependency->dependent_servicegroup_name); - - /* exit on error */ - if(result == ERROR) { - xodtemplate_free_memberlist(&master_hostlist); - xodtemplate_free_memberlist(&master_servicelist); - return ERROR; - } - } - - /* free memory we used for service list */ - xodtemplate_free_memberlist(&master_servicelist); - } - - /* free service descriptions */ - my_free(service_descriptions); - - /* free memory we used for host list */ - xodtemplate_free_memberlist(&master_hostlist); - } - } - - -#ifdef DEBUG_SERVICE_DEPENDENCIES - for(temp_servicedependency = xodtemplate_servicedependency_list; temp_servicedependency != NULL; temp_servicedependency = temp_servicedependency->next) { - printf("1**) H: %s HG: %s SG: %s SD: %s DH: %s DHG: %s DSG: %s DSD: %s\n", temp_servicedependency->host_name, temp_servicedependency->hostgroup_name, temp_servicedependency->servicegroup_name, temp_servicedependency->service_description, temp_servicedependency->dependent_host_name, temp_servicedependency->dependent_hostgroup_name, temp_servicedependency->dependent_servicegroup_name, temp_servicedependency->dependent_service_description); - } - printf("\n"); -#endif - - - /****** PROCESS SERVICE DEPENDENCIES WITH DEPENDENT SERVICEGROUPS *****/ - for(temp_servicedependency = xodtemplate_servicedependency_list; temp_servicedependency != NULL; temp_servicedependency = temp_servicedependency->next) { - - /* skip templates */ - if(temp_servicedependency->register_object == 0) - continue; - - /* expand dependent servicegroups into a list of services */ - if(temp_servicedependency->dependent_servicegroup_name) { - - dependent_servicelist = xodtemplate_expand_servicegroups_and_services(temp_servicedependency->dependent_servicegroup_name, NULL, NULL, temp_servicedependency->_config_file, temp_servicedependency->_start_line); - if(dependent_servicelist == NULL) { - logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not expand dependent servicegroups specified in service dependency (config file '%s', starting on line %d)\n", xodtemplate_config_file_name(temp_servicedependency->_config_file), temp_servicedependency->_start_line); - return ERROR; - } - - /* if dependency also has dependent host, hostgroup, and/or service, we must split that off to another definition */ - if(temp_servicedependency->dependent_host_name != NULL || temp_servicedependency->dependent_hostgroup_name != NULL || temp_servicedependency->dependent_service_description != NULL) { - - /* duplicate everything except dependent servicegroup */ - xodtemplate_duplicate_servicedependency(temp_servicedependency, temp_servicedependency->host_name, temp_servicedependency->service_description, temp_servicedependency->hostgroup_name, temp_servicedependency->servicegroup_name, temp_servicedependency->dependent_host_name, temp_servicedependency->dependent_service_description, temp_servicedependency->dependent_hostgroup_name, NULL); - - /* clear values in this definition */ - temp_servicedependency->have_dependent_host_name = FALSE; - temp_servicedependency->have_dependent_service_description = FALSE; - temp_servicedependency->have_dependent_hostgroup_name = FALSE; - my_free(temp_servicedependency->dependent_host_name); - my_free(temp_servicedependency->dependent_service_description); - my_free(temp_servicedependency->dependent_hostgroup_name); - } - - /* Detected same host servicegroups dependencies */ - same_host_servicedependency = FALSE; - if(temp_servicedependency->host_name == NULL && temp_servicedependency->hostgroup_name == NULL) - same_host_servicedependency = TRUE; - - /* duplicate service dependency entries */ - first_item = TRUE; - for(temp_dependentservice = dependent_servicelist; temp_dependentservice != NULL; temp_dependentservice = temp_dependentservice->next) { - - /* just in case */ - if(temp_dependentservice->name1 == NULL || temp_dependentservice->name2 == NULL) - continue; - - /* if this is the first duplication, use the existing entry */ - if(first_item == TRUE) { - - my_free(temp_servicedependency->dependent_host_name); - temp_servicedependency->dependent_host_name = (char *)strdup(temp_dependentservice->name1); - - my_free(temp_servicedependency->dependent_service_description); - temp_servicedependency->dependent_service_description = (char *)strdup(temp_dependentservice->name2); - - /* Same host servicegroups dependencies: Use dependentservice host_name for master host_name */ - if(same_host_servicedependency == TRUE) - temp_servicedependency->host_name = (char*)strdup(temp_dependentservice->name1); - - /* clear the dependent servicegroup */ - temp_servicedependency->have_dependent_servicegroup_name = FALSE; - my_free(temp_servicedependency->dependent_servicegroup_name); - - if(temp_servicedependency->dependent_host_name == NULL || temp_servicedependency->dependent_service_description == NULL) { - xodtemplate_free_memberlist(&dependent_servicelist); - return ERROR; - } - - first_item = FALSE; - continue; - } - - /* duplicate service dependency definition */ - /* Same host servicegroups dependencies: Use dependentservice host_name for master host_name instead of undefined (not yet) master host_name */ - if(same_host_servicedependency == TRUE) - result = xodtemplate_duplicate_servicedependency(temp_servicedependency, temp_dependentservice->name1, temp_servicedependency->service_description, NULL, NULL, temp_dependentservice->name1, temp_dependentservice->name2, NULL, NULL); - else - result = xodtemplate_duplicate_servicedependency(temp_servicedependency, temp_servicedependency->host_name, temp_servicedependency->service_description, NULL, NULL, temp_dependentservice->name1, temp_dependentservice->name2, NULL, NULL); - - /* exit on error */ - if(result == ERROR) { - xodtemplate_free_memberlist(&dependent_servicelist); - return ERROR; - } - } - - /* free memory we used for service list */ - xodtemplate_free_memberlist(&dependent_servicelist); - } - } - - -#ifdef DEBUG_SERVICE_DEPENDENCIES - printf("\n"); - for(temp_servicedependency = xodtemplate_servicedependency_list; temp_servicedependency != NULL; temp_servicedependency = temp_servicedependency->next) { - printf("2**) H: %s HG: %s SG: %s SD: %s DH: %s DHG: %s DSG: %s DSD: %s\n", temp_servicedependency->host_name, temp_servicedependency->hostgroup_name, temp_servicedependency->servicegroup_name, temp_servicedependency->service_description, temp_servicedependency->dependent_host_name, temp_servicedependency->dependent_hostgroup_name, temp_servicedependency->dependent_servicegroup_name, temp_servicedependency->dependent_service_description); - } -#endif - - - /****** PROCESS SERVICE DEPENDENCY DEPENDENT HOSTS/HOSTGROUPS/SERVICES *****/ - for(temp_servicedependency = xodtemplate_servicedependency_list; temp_servicedependency != NULL; temp_servicedependency = temp_servicedependency->next) { - - /* skip templates */ - if(temp_servicedependency->register_object == 0) - continue; - - /* ADDED 02/04/2007 - special case for "same host" dependencies */ - if(temp_servicedependency->dependent_host_name == NULL && temp_servicedependency->dependent_hostgroup_name == NULL) { - if(temp_servicedependency->host_name) - temp_servicedependency->dependent_host_name = (char *)strdup(temp_servicedependency->host_name); - } - - /* expand dependent hosts/hostgroups into a list of host names */ - if(temp_servicedependency->dependent_host_name != NULL || temp_servicedependency->dependent_hostgroup_name != NULL) { - - dependent_hostlist = xodtemplate_expand_hostgroups_and_hosts(temp_servicedependency->dependent_hostgroup_name, temp_servicedependency->dependent_host_name, temp_servicedependency->_config_file, temp_servicedependency->_start_line); - if(dependent_hostlist == NULL && allow_empty_hostgroup_assignment == 0) { - logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not expand dependent hostgroups and/or hosts specified in service dependency (config file '%s', starting on line %d)\n", xodtemplate_config_file_name(temp_servicedependency->_config_file), temp_servicedependency->_start_line); - return ERROR; - } - - /* save service descriptions for later */ - if(temp_servicedependency->dependent_service_description) - service_descriptions = (char *)strdup(temp_servicedependency->dependent_service_description); - - /* for each host, expand dependent services */ - first_item = TRUE; - for(temp_dependenthost = dependent_hostlist; temp_dependenthost != NULL; temp_dependenthost = temp_dependenthost->next) { - - dependent_servicelist = xodtemplate_expand_servicegroups_and_services(NULL, temp_dependenthost->name1, service_descriptions, temp_servicedependency->_config_file, temp_servicedependency->_start_line); - if(dependent_servicelist == NULL) { - logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not expand dependent services specified in service dependency (config file '%s', starting on line %d)\n", xodtemplate_config_file_name(temp_servicedependency->_config_file), temp_servicedependency->_start_line); - return ERROR; - } - - /* duplicate service dependency entries */ - for(temp_dependentservice = dependent_servicelist; temp_dependentservice != NULL; temp_dependentservice = temp_dependentservice->next) { - - /* just in case */ - if(temp_dependentservice->name1 == NULL || temp_dependentservice->name2 == NULL) - continue; - - /* if this is the first duplication, use the existing entry */ - if(first_item == TRUE) { - - my_free(temp_servicedependency->dependent_host_name); - temp_servicedependency->dependent_host_name = (char *)strdup(temp_dependentservice->name1); - - my_free(temp_servicedependency->dependent_service_description); - temp_servicedependency->dependent_service_description = (char *)strdup(temp_dependentservice->name2); - - if(temp_servicedependency->dependent_host_name == NULL || temp_servicedependency->dependent_service_description == NULL) { - xodtemplate_free_memberlist(&dependent_servicelist); - xodtemplate_free_memberlist(&dependent_hostlist); - return ERROR; - } - - first_item = FALSE; - continue; - } - - /* duplicate service dependency definition */ - result = xodtemplate_duplicate_servicedependency(temp_servicedependency, temp_servicedependency->host_name, temp_servicedependency->service_description, NULL, NULL, temp_dependentservice->name1, temp_dependentservice->name2, NULL, NULL); - - /* exit on error */ - if(result == ERROR) { - xodtemplate_free_memberlist(&dependent_servicelist); - xodtemplate_free_memberlist(&dependent_hostlist); - return ERROR; - } - } - - /* free memory we used for service list */ - xodtemplate_free_memberlist(&dependent_servicelist); - } - - /* free service descriptions */ - my_free(service_descriptions); - - /* free memory we used for host list */ - xodtemplate_free_memberlist(&dependent_hostlist); - } - } - - -#ifdef DEBUG_SERVICE_DEPENDENCIES - printf("\n"); - for(temp_servicedependency = xodtemplate_servicedependency_list; temp_servicedependency != NULL; temp_servicedependency = temp_servicedependency->next) { - printf("3**) MAS: %s/%s DEP: %s/%s\n", temp_servicedependency->host_name, temp_servicedependency->service_description, temp_servicedependency->dependent_host_name, temp_servicedependency->dependent_service_description); - } -#endif + timing_point("Created %u serviceescalations (dupes possible)\n", xodcount.serviceescalations); /****** DUPLICATE HOSTEXTINFO DEFINITIONS WITH ONE OR MORE HOSTGROUP AND/OR HOST NAMES ******/ - for(temp_hostextinfo = xodtemplate_hostextinfo_list; temp_hostextinfo != NULL; temp_hostextinfo = temp_hostextinfo->next) { + for(temp_hostextinfo = xodtemplate_hostextinfo_list; temp_hostextinfo != NULL; temp_hostextinfo = next_he) { + next_he = temp_hostextinfo->next; /* skip definitions without enough data */ if(temp_hostextinfo->hostgroup_name == NULL && temp_hostextinfo->host_name == NULL) @@ -4913,180 +4430,71 @@ int xodtemplate_duplicate_objects(void) { return ERROR; } - /* add a copy of the definition for every host in the hostgroup/host name list */ - first_item = TRUE; - for(temp_masterhost = master_hostlist; temp_masterhost != NULL; temp_masterhost = temp_masterhost->next) { + /* merge this extinfo with every host in the hostgroup/host name list */ + for(list = master_hostlist; list; list = next) { + xodtemplate_host *h = (xodtemplate_host *)list->object_ptr; + next = list->next; + free(list); - /* if this is the first duplication, use the existing entry */ - if(first_item == TRUE) { - - my_free(temp_hostextinfo->host_name); - temp_hostextinfo->host_name = (char *)strdup(temp_masterhost->name1); - if(temp_hostextinfo->host_name == NULL) { - xodtemplate_free_memberlist(&master_hostlist); - return ERROR; - } - first_item = FALSE; - continue; - } - - /* duplicate hostextinfo definition */ - result = xodtemplate_duplicate_hostextinfo(temp_hostextinfo, temp_masterhost->name1); - - /* exit on error */ - if(result == ERROR) { - xodtemplate_free_memberlist(&master_hostlist); - return ERROR; - } + /* merge it. we ignore errors here */ + xodtemplate_merge_host_extinfo_object(h, temp_hostextinfo); } - - /* free memory we used for host list */ - xodtemplate_free_memberlist(&master_hostlist); + /* might as well kill it off early */ + my_free(temp_hostextinfo->template); + my_free(temp_hostextinfo->name); + my_free(temp_hostextinfo->notes); + my_free(temp_hostextinfo->host_name); + my_free(temp_hostextinfo->hostgroup_name); + my_free(temp_hostextinfo->notes_url); + my_free(temp_hostextinfo->action_url); + my_free(temp_hostextinfo->icon_image); + my_free(temp_hostextinfo->vrml_image); + my_free(temp_hostextinfo->statusmap_image); + my_free(temp_hostextinfo); } + timing_point("Done merging hostextinfo\n"); /****** DUPLICATE SERVICEEXTINFO DEFINITIONS WITH ONE OR MORE HOSTGROUP AND/OR HOST NAMES ******/ - for(temp_serviceextinfo = xodtemplate_serviceextinfo_list; temp_serviceextinfo != NULL; temp_serviceextinfo = temp_serviceextinfo->next) { + for(temp_serviceextinfo = xodtemplate_serviceextinfo_list; temp_serviceextinfo != NULL; temp_serviceextinfo = next_se) { + next_se = temp_serviceextinfo->next; /* skip definitions without enough data */ - if(temp_serviceextinfo->hostgroup_name == NULL && temp_serviceextinfo->host_name == NULL) + if(temp_serviceextinfo->service_description == NULL || (temp_serviceextinfo->hostgroup_name == NULL && temp_serviceextinfo->host_name == NULL)) continue; - /* get list of hosts */ - master_hostlist = xodtemplate_expand_hostgroups_and_hosts(temp_serviceextinfo->hostgroup_name, temp_serviceextinfo->host_name, temp_serviceextinfo->_config_file, temp_serviceextinfo->_start_line); - if(master_hostlist == NULL) { - logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not expand hostgroups and/or hosts specified in extended service info (config file '%s', starting on line %d)\n", xodtemplate_config_file_name(temp_serviceextinfo->_config_file), temp_serviceextinfo->_start_line); + bitmap_clear(service_map); + master_servicelist = NULL; + + /* get list of services */ + if(xodtemplate_create_service_list(&master_servicelist, service_map, temp_serviceextinfo->host_name, temp_serviceextinfo->hostgroup_name, NULL, temp_serviceextinfo->service_description, temp_serviceextinfo->_config_file, temp_serviceextinfo->_start_line) != OK) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not expand services specified in extended service info (config file '%s', starting on line %d)\n", xodtemplate_config_file_name(temp_serviceextinfo->_config_file), temp_serviceextinfo->_start_line); return ERROR; } - /* add a copy of the definition for every host in the hostgroup/host name list */ - first_item = TRUE; - for(temp_masterhost = master_hostlist; temp_masterhost != NULL; temp_masterhost = temp_masterhost->next) { - - /* existing definition gets first host name */ - if(first_item == TRUE) { - my_free(temp_serviceextinfo->host_name); - temp_serviceextinfo->host_name = (char *)strdup(temp_masterhost->name1); - if(temp_serviceextinfo->host_name == NULL) { - xodtemplate_free_memberlist(&master_hostlist); - return ERROR; - } - first_item = FALSE; + /* merge this serviceextinfo with every service in the list */ + for(list = master_servicelist; list; list = next) { + xodtemplate_service *s = (xodtemplate_service *)list->object_ptr; + next = list->next; + free(list); + if(bitmap_isset(service_map, s->id)) continue; - } - - /* duplicate serviceextinfo definition */ - result = xodtemplate_duplicate_serviceextinfo(temp_serviceextinfo, temp_masterhost->name1); - - /* exit on error */ - if(result == ERROR) { - xodtemplate_free_memberlist(&master_hostlist); - return ERROR; - } + xodtemplate_merge_service_extinfo_object(s, temp_serviceextinfo); } - - /* free memory we used for host list */ - xodtemplate_free_memberlist(&master_hostlist); + /* now we're done, so we might as well kill it off */ + my_free(temp_serviceextinfo->template); + my_free(temp_serviceextinfo->name); + my_free(temp_serviceextinfo->host_name); + my_free(temp_serviceextinfo->hostgroup_name); + my_free(temp_serviceextinfo->service_description); + my_free(temp_serviceextinfo->notes); + my_free(temp_serviceextinfo->notes_url); + my_free(temp_serviceextinfo->action_url); + my_free(temp_serviceextinfo->icon_image); + my_free(temp_serviceextinfo->icon_image_alt); + my_free(temp_serviceextinfo); } - - - /***************************************/ - /* SKIPLIST STUFF FOR FAST SORT/SEARCH */ - /***************************************/ - - /* host escalations */ - for(temp_hostescalation = xodtemplate_hostescalation_list; temp_hostescalation != NULL; temp_hostescalation = temp_hostescalation->next) { - - /* skip escalations that shouldn't be registered */ - if(temp_hostescalation->register_object == FALSE) - continue; - - /* skip escalation definitions without enough data */ - if(temp_hostescalation->host_name == NULL) - continue; - - result = skiplist_insert(xobject_skiplists[X_HOSTESCALATION_SKIPLIST], (void *)temp_hostescalation); - switch(result) { - case SKIPLIST_OK: - result = OK; - break; - default: - result = ERROR; - break; - } - } - - /* service escalations */ - for(temp_serviceescalation = xodtemplate_serviceescalation_list; temp_serviceescalation != NULL; temp_serviceescalation = temp_serviceescalation->next) { - - /* skip escalations that shouldn't be registered */ - if(temp_serviceescalation->register_object == FALSE) - continue; - - /* skip escalation definitions without enough data */ - if(temp_serviceescalation->host_name == NULL || temp_serviceescalation->service_description == NULL) - continue; - - result = skiplist_insert(xobject_skiplists[X_SERVICEESCALATION_SKIPLIST], (void *)temp_serviceescalation); - switch(result) { - case SKIPLIST_OK: - result = OK; - break; - default: - result = ERROR; - break; - } - } - - /* host dependencies */ - for(temp_hostdependency = xodtemplate_hostdependency_list; temp_hostdependency != NULL; temp_hostdependency = temp_hostdependency->next) { - - /* skip dependencys that shouldn't be registered */ - if(temp_hostdependency->register_object == FALSE) - continue; - - /* skip dependency definitions without enough data */ - if(temp_hostdependency->host_name == NULL) - continue; - - result = skiplist_insert(xobject_skiplists[X_HOSTDEPENDENCY_SKIPLIST], (void *)temp_hostdependency); - switch(result) { - case SKIPLIST_OK: - result = OK; - break; - default: - result = ERROR; - break; - } - } - - /* service dependencies */ - for(temp_servicedependency = xodtemplate_servicedependency_list; temp_servicedependency != NULL; temp_servicedependency = temp_servicedependency->next) { - - /* skip dependencys that shouldn't be registered */ - if(temp_servicedependency->register_object == FALSE) - continue; - - /* skip dependency definitions without enough data */ - if(temp_servicedependency->dependent_host_name == NULL || temp_servicedependency->dependent_service_description == NULL) - continue; - - result = skiplist_insert(xobject_skiplists[X_SERVICEDEPENDENCY_SKIPLIST], (void *)temp_servicedependency); - switch(result) { - case SKIPLIST_OK: - result = OK; - break; - default: - result = ERROR; - break; - } - } - - /* host extinfo */ - /* NOT NEEDED */ - - /* service extinfo */ - /* NOT NEEDED */ + timing_point("Done merging serviceextinfo\n"); return OK; } @@ -5094,9 +4502,8 @@ int xodtemplate_duplicate_objects(void) { /* duplicates a service definition (with a new host name) */ -int xodtemplate_duplicate_service(xodtemplate_service *temp_service, char *host_name) { +int xodtemplate_duplicate_service(xodtemplate_service *temp_service, char *host_name, int from_hg) { xodtemplate_service *new_service = NULL; - xodtemplate_customvariablesmember *temp_customvariablesmember = NULL; int error = FALSE; /* allocate zero'd out memory for a new service definition */ @@ -5104,160 +4511,31 @@ int xodtemplate_duplicate_service(xodtemplate_service *temp_service, char *host_ if(new_service == NULL) return ERROR; - /* standard items */ - new_service->has_been_resolved = temp_service->has_been_resolved; - new_service->register_object = temp_service->register_object; - new_service->_config_file = temp_service->_config_file; - new_service->_start_line = temp_service->_start_line; - /*tag service apply on host group*/ - xodtemplate_set_service_is_from_hostgroup(new_service); + /* copy the entire thing and override what we have to */ + memcpy(new_service, temp_service, sizeof(*new_service)); + new_service->is_copy = TRUE; + new_service->id = xodcount.services++; + new_service->host_name = host_name; - /* string defaults */ - new_service->have_hostgroup_name = temp_service->have_hostgroup_name; - new_service->have_host_name = temp_service->have_host_name; - new_service->have_service_description = temp_service->have_service_description; - new_service->have_display_name = temp_service->have_display_name; - new_service->have_service_groups = temp_service->have_service_groups; - new_service->have_check_command = temp_service->have_check_command; - new_service->have_check_period = temp_service->have_check_period; - new_service->have_event_handler = temp_service->have_event_handler; - new_service->have_notification_period = temp_service->have_notification_period; - new_service->have_contact_groups = temp_service->have_contact_groups; - new_service->have_contacts = temp_service->have_contacts; - new_service->have_failure_prediction_options = temp_service->have_failure_prediction_options; - new_service->have_notes = temp_service->have_notes; - new_service->have_notes_url = temp_service->have_notes_url; - new_service->have_action_url = temp_service->have_action_url; - new_service->have_icon_image = temp_service->have_icon_image; - new_service->have_icon_image_alt = temp_service->have_icon_image_alt; + /* tag service apply on host group */ + new_service->is_from_hostgroup = from_hg; /* allocate memory for and copy string members of service definition (host name provided, DO NOT duplicate hostgroup member!)*/ - if(temp_service->host_name != NULL && (new_service->host_name = (char *)strdup(host_name)) == NULL) - error = TRUE; - if(temp_service->template != NULL && (new_service->template = (char *)strdup(temp_service->template)) == NULL) - error = TRUE; - if(temp_service->name != NULL && (new_service->name = (char *)strdup(temp_service->name)) == NULL) - error = TRUE; - if(temp_service->service_description != NULL && (new_service->service_description = (char *)strdup(temp_service->service_description)) == NULL) - error = TRUE; - if(temp_service->display_name != NULL && (new_service->display_name = (char *)strdup(temp_service->display_name)) == NULL) - error = TRUE; if(temp_service->service_groups != NULL && (new_service->service_groups = (char *)strdup(temp_service->service_groups)) == NULL) error = TRUE; - if(temp_service->check_command != NULL && (new_service->check_command = (char *)strdup(temp_service->check_command)) == NULL) - error = TRUE; - if(temp_service->check_period != NULL && (new_service->check_period = (char *)strdup(temp_service->check_period)) == NULL) - error = TRUE; - if(temp_service->event_handler != NULL && (new_service->event_handler = (char *)strdup(temp_service->event_handler)) == NULL) - error = TRUE; - if(temp_service->notification_period != NULL && (new_service->notification_period = (char *)strdup(temp_service->notification_period)) == NULL) - error = TRUE; if(temp_service->contact_groups != NULL && (new_service->contact_groups = (char *)strdup(temp_service->contact_groups)) == NULL) error = TRUE; if(temp_service->contacts != NULL && (new_service->contacts = (char *)strdup(temp_service->contacts)) == NULL) error = TRUE; - if(temp_service->failure_prediction_options != NULL && (new_service->failure_prediction_options = (char *)strdup(temp_service->failure_prediction_options)) == NULL) - error = TRUE; - if(temp_service->notes != NULL && (new_service->notes = (char *)strdup(temp_service->notes)) == NULL) - error = TRUE; - if(temp_service->notes_url != NULL && (new_service->notes_url = (char *)strdup(temp_service->notes_url)) == NULL) - error = TRUE; - if(temp_service->action_url != NULL && (new_service->action_url = (char *)strdup(temp_service->action_url)) == NULL) - error = TRUE; - if(temp_service->icon_image != NULL && (new_service->icon_image = (char *)strdup(temp_service->icon_image)) == NULL) - error = TRUE; - if(temp_service->icon_image_alt != NULL && (new_service->icon_image_alt = (char *)strdup(temp_service->icon_image_alt)) == NULL) - error = TRUE; if(error == TRUE) { - my_free(new_service->host_name); - my_free(new_service->template); - my_free(new_service->name); - my_free(new_service->service_description); - my_free(new_service->display_name); my_free(new_service->service_groups); - my_free(new_service->check_command); - my_free(new_service->check_period); - my_free(new_service->event_handler); - my_free(new_service->notification_period); my_free(new_service->contact_groups); my_free(new_service->contacts); - my_free(new_service->failure_prediction_options); - my_free(new_service->notes); - my_free(new_service->notes_url); - my_free(new_service->action_url); - my_free(new_service->icon_image); - my_free(new_service->icon_image_alt); my_free(new_service); return ERROR; } - /* duplicate custom variables */ - for(temp_customvariablesmember = temp_service->custom_variables; temp_customvariablesmember != NULL; temp_customvariablesmember = temp_customvariablesmember->next) - xodtemplate_add_custom_variable_to_service(new_service, temp_customvariablesmember->variable_name, temp_customvariablesmember->variable_value); - - /* duplicate non-string members */ - new_service->initial_state = temp_service->initial_state; - new_service->max_check_attempts = temp_service->max_check_attempts; - new_service->have_max_check_attempts = temp_service->have_max_check_attempts; - new_service->check_interval = temp_service->check_interval; - new_service->have_check_interval = temp_service->have_check_interval; - new_service->retry_interval = temp_service->retry_interval; - new_service->have_retry_interval = temp_service->have_retry_interval; - new_service->active_checks_enabled = temp_service->active_checks_enabled; - new_service->have_active_checks_enabled = temp_service->have_active_checks_enabled; - new_service->passive_checks_enabled = temp_service->passive_checks_enabled; - new_service->have_passive_checks_enabled = temp_service->have_passive_checks_enabled; - new_service->parallelize_check = temp_service->parallelize_check; - new_service->have_parallelize_check = temp_service->have_parallelize_check; - new_service->is_volatile = temp_service->is_volatile; - new_service->have_is_volatile = temp_service->have_is_volatile; - new_service->obsess_over_service = temp_service->obsess_over_service; - new_service->have_obsess_over_service = temp_service->have_obsess_over_service; - new_service->event_handler_enabled = temp_service->event_handler_enabled; - new_service->have_event_handler_enabled = temp_service->have_event_handler_enabled; - new_service->check_freshness = temp_service->check_freshness; - new_service->have_check_freshness = temp_service->have_check_freshness; - new_service->freshness_threshold = temp_service->freshness_threshold; - new_service->have_freshness_threshold = temp_service->have_freshness_threshold; - new_service->flap_detection_enabled = temp_service->flap_detection_enabled; - new_service->have_flap_detection_enabled = temp_service->have_flap_detection_enabled; - new_service->low_flap_threshold = temp_service->low_flap_threshold; - new_service->have_low_flap_threshold = temp_service->have_low_flap_threshold; - new_service->high_flap_threshold = temp_service->high_flap_threshold; - new_service->have_high_flap_threshold = temp_service->have_high_flap_threshold; - new_service->flap_detection_on_ok = temp_service->flap_detection_on_ok; - new_service->flap_detection_on_warning = temp_service->flap_detection_on_warning; - new_service->flap_detection_on_unknown = temp_service->flap_detection_on_unknown; - new_service->flap_detection_on_critical = temp_service->flap_detection_on_critical; - new_service->have_flap_detection_options = temp_service->have_flap_detection_options; - new_service->notify_on_unknown = temp_service->notify_on_unknown; - new_service->notify_on_warning = temp_service->notify_on_warning; - new_service->notify_on_critical = temp_service->notify_on_critical; - new_service->notify_on_recovery = temp_service->notify_on_recovery; - new_service->notify_on_flapping = temp_service->notify_on_flapping; - new_service->notify_on_downtime = temp_service->notify_on_downtime; - new_service->have_notification_options = temp_service->have_notification_options; - new_service->notifications_enabled = temp_service->notifications_enabled; - new_service->have_notifications_enabled = temp_service->have_notifications_enabled; - new_service->notification_interval = temp_service->notification_interval; - new_service->have_notification_interval = temp_service->have_notification_interval; - new_service->first_notification_delay = temp_service->first_notification_delay; - new_service->have_first_notification_delay = temp_service->have_first_notification_delay; - new_service->stalk_on_ok = temp_service->stalk_on_ok; - new_service->stalk_on_unknown = temp_service->stalk_on_unknown; - new_service->stalk_on_warning = temp_service->stalk_on_warning; - new_service->stalk_on_critical = temp_service->stalk_on_critical; - new_service->have_stalking_options = temp_service->have_stalking_options; - new_service->process_perf_data = temp_service->process_perf_data; - new_service->have_process_perf_data = temp_service->have_process_perf_data; - new_service->failure_prediction_enabled = temp_service->failure_prediction_enabled; - new_service->have_failure_prediction_enabled = temp_service->have_failure_prediction_enabled; - new_service->retain_status_information = temp_service->retain_status_information; - new_service->have_retain_status_information = temp_service->have_retain_status_information; - new_service->retain_nonstatus_information = temp_service->retain_nonstatus_information; - new_service->have_retain_nonstatus_information = temp_service->have_retain_nonstatus_information; - /* add new service to head of list in memory */ new_service->next = xodtemplate_service_list; xodtemplate_service_list = new_service; @@ -5279,57 +4557,23 @@ int xodtemplate_duplicate_hostescalation(xodtemplate_hostescalation *temp_hostes if(new_hostescalation == NULL) return ERROR; - /* standard items */ - new_hostescalation->has_been_resolved = temp_hostescalation->has_been_resolved; - new_hostescalation->register_object = temp_hostescalation->register_object; - new_hostescalation->_config_file = temp_hostescalation->_config_file; - new_hostescalation->_start_line = temp_hostescalation->_start_line; + memcpy(new_hostescalation, temp_hostescalation, sizeof(*new_hostescalation)); + new_hostescalation->is_copy = TRUE; - /* string defaults */ - new_hostescalation->have_hostgroup_name = temp_hostescalation->have_hostgroup_name; - new_hostescalation->have_host_name = (host_name) ? TRUE : FALSE; - new_hostescalation->have_contact_groups = temp_hostescalation->have_contact_groups; - new_hostescalation->have_contacts = temp_hostescalation->have_contacts; - new_hostescalation->have_escalation_period = temp_hostescalation->have_escalation_period; + new_hostescalation->host_name = host_name; - /* allocate memory for and copy string members of hostescalation definition */ - if(host_name != NULL && (new_hostescalation->host_name = (char *)strdup(host_name)) == NULL) - error = TRUE; - - if(temp_hostescalation->template != NULL && (new_hostescalation->template = (char *)strdup(temp_hostescalation->template)) == NULL) - error = TRUE; - if(temp_hostescalation->name != NULL && (new_hostescalation->name = (char *)strdup(temp_hostescalation->name)) == NULL) - error = TRUE; if(temp_hostescalation->contact_groups != NULL && (new_hostescalation->contact_groups = (char *)strdup(temp_hostescalation->contact_groups)) == NULL) error = TRUE; if(temp_hostescalation->contacts != NULL && (new_hostescalation->contacts = (char *)strdup(temp_hostescalation->contacts)) == NULL) error = TRUE; - if(temp_hostescalation->escalation_period != NULL && (new_hostescalation->escalation_period = (char *)strdup(temp_hostescalation->escalation_period)) == NULL) - error = TRUE; if(error == TRUE) { - my_free(new_hostescalation->escalation_period); my_free(new_hostescalation->contact_groups); my_free(new_hostescalation->contacts); - my_free(new_hostescalation->host_name); - my_free(new_hostescalation->template); - my_free(new_hostescalation->name); my_free(new_hostescalation); return ERROR; } - /* duplicate non-string members */ - new_hostescalation->first_notification = temp_hostescalation->first_notification; - new_hostescalation->last_notification = temp_hostescalation->last_notification; - new_hostescalation->have_first_notification = temp_hostescalation->have_first_notification; - new_hostescalation->have_last_notification = temp_hostescalation->have_last_notification; - new_hostescalation->notification_interval = temp_hostescalation->notification_interval; - new_hostescalation->have_notification_interval = temp_hostescalation->have_notification_interval; - new_hostescalation->escalate_on_down = temp_hostescalation->escalate_on_down; - new_hostescalation->escalate_on_unreachable = temp_hostescalation->escalate_on_unreachable; - new_hostescalation->escalate_on_recovery = temp_hostescalation->escalate_on_recovery; - new_hostescalation->have_escalation_options = temp_hostescalation->have_escalation_options; - /* add new hostescalation to head of list in memory */ new_hostescalation->next = xodtemplate_hostescalation_list; xodtemplate_hostescalation_list = new_hostescalation; @@ -5349,63 +4593,23 @@ int xodtemplate_duplicate_serviceescalation(xodtemplate_serviceescalation *temp_ if(new_serviceescalation == NULL) return ERROR; - /* standard items */ - new_serviceescalation->has_been_resolved = temp_serviceescalation->has_been_resolved; - new_serviceescalation->register_object = temp_serviceescalation->register_object; - new_serviceescalation->_config_file = temp_serviceescalation->_config_file; - new_serviceescalation->_start_line = temp_serviceescalation->_start_line; + memcpy(new_serviceescalation, temp_serviceescalation, sizeof(*new_serviceescalation)); + new_serviceescalation->is_copy = TRUE; + new_serviceescalation->host_name = host_name; + new_serviceescalation->service_description = svc_description; - /* string defaults */ - new_serviceescalation->have_servicegroup_name = FALSE; - new_serviceescalation->have_hostgroup_name = FALSE; - new_serviceescalation->have_host_name = (host_name) ? TRUE : FALSE; - new_serviceescalation->have_service_description = (svc_description) ? TRUE : FALSE; - new_serviceescalation->have_contact_groups = temp_serviceescalation->have_contact_groups; - new_serviceescalation->have_contacts = temp_serviceescalation->have_contacts; - new_serviceescalation->have_escalation_period = temp_serviceescalation->have_escalation_period; - - /* allocate memory for and copy string members of serviceescalation definition */ - if(host_name != NULL && (new_serviceescalation->host_name = (char *)strdup(host_name)) == NULL) - error = TRUE; - if(svc_description != NULL && (new_serviceescalation->service_description = (char *)strdup(svc_description)) == NULL) - error = TRUE; - - if(temp_serviceescalation->template != NULL && (new_serviceescalation->template = (char *)strdup(temp_serviceescalation->template)) == NULL) - error = TRUE; - if(temp_serviceescalation->name != NULL && (new_serviceescalation->name = (char *)strdup(temp_serviceescalation->name)) == NULL) - error = TRUE; if(temp_serviceescalation->contact_groups != NULL && (new_serviceescalation->contact_groups = (char *)strdup(temp_serviceescalation->contact_groups)) == NULL) error = TRUE; if(temp_serviceescalation->contacts != NULL && (new_serviceescalation->contacts = (char *)strdup(temp_serviceescalation->contacts)) == NULL) error = TRUE; - if(temp_serviceescalation->escalation_period != NULL && (new_serviceescalation->escalation_period = (char *)strdup(temp_serviceescalation->escalation_period)) == NULL) - error = TRUE; if(error == TRUE) { - my_free(new_serviceescalation->host_name); - my_free(new_serviceescalation->service_description); my_free(new_serviceescalation->contact_groups); my_free(new_serviceescalation->contacts); - my_free(new_serviceescalation->escalation_period); - my_free(new_serviceescalation->template); - my_free(new_serviceescalation->name); my_free(new_serviceescalation); return ERROR; } - /* duplicate non-string members */ - new_serviceescalation->first_notification = temp_serviceescalation->first_notification; - new_serviceescalation->last_notification = temp_serviceescalation->last_notification; - new_serviceescalation->have_first_notification = temp_serviceescalation->have_first_notification; - new_serviceescalation->have_last_notification = temp_serviceescalation->have_last_notification; - new_serviceescalation->notification_interval = temp_serviceescalation->notification_interval; - new_serviceescalation->have_notification_interval = temp_serviceescalation->have_notification_interval; - new_serviceescalation->escalate_on_warning = temp_serviceescalation->escalate_on_warning; - new_serviceescalation->escalate_on_unknown = temp_serviceescalation->escalate_on_unknown; - new_serviceescalation->escalate_on_critical = temp_serviceescalation->escalate_on_critical; - new_serviceescalation->escalate_on_recovery = temp_serviceescalation->escalate_on_recovery; - new_serviceescalation->have_escalation_options = temp_serviceescalation->have_escalation_options; - /* add new serviceescalation to head of list in memory */ new_serviceescalation->next = xodtemplate_serviceescalation_list; xodtemplate_serviceescalation_list = new_serviceescalation; @@ -5413,328 +4617,10 @@ int xodtemplate_duplicate_serviceescalation(xodtemplate_serviceescalation *temp_ return OK; } - - -/* duplicates a host dependency definition (with master and dependent host names) */ -int xodtemplate_duplicate_hostdependency(xodtemplate_hostdependency *temp_hostdependency, char *master_host_name, char *dependent_host_name) { - xodtemplate_hostdependency *new_hostdependency = NULL; - int error = FALSE; - - /* allocate memory for a new host dependency definition */ - new_hostdependency = (xodtemplate_hostdependency *)calloc(1, sizeof(xodtemplate_hostdependency)); - if(new_hostdependency == NULL) - return ERROR; - - /* standard items */ - new_hostdependency->has_been_resolved = temp_hostdependency->has_been_resolved; - new_hostdependency->register_object = temp_hostdependency->register_object; - new_hostdependency->_config_file = temp_hostdependency->_config_file; - new_hostdependency->_start_line = temp_hostdependency->_start_line; - - /* string defaults */ - new_hostdependency->have_hostgroup_name = FALSE; - new_hostdependency->have_dependent_hostgroup_name = FALSE; - new_hostdependency->have_host_name = temp_hostdependency->have_host_name; - new_hostdependency->have_dependent_host_name = temp_hostdependency->have_dependent_host_name; - new_hostdependency->have_dependency_period = temp_hostdependency->have_dependency_period; - - /* allocate memory for and copy string members of hostdependency definition */ - if(master_host_name != NULL && (new_hostdependency->host_name = (char *)strdup(master_host_name)) == NULL) - error = TRUE; - if(dependent_host_name != NULL && (new_hostdependency->dependent_host_name = (char *)strdup(dependent_host_name)) == NULL) - error = TRUE; - - if(temp_hostdependency->dependency_period != NULL && (new_hostdependency->dependency_period = (char *)strdup(temp_hostdependency->dependency_period)) == NULL) - error = TRUE; - if(temp_hostdependency->template != NULL && (new_hostdependency->template = (char *)strdup(temp_hostdependency->template)) == NULL) - error = TRUE; - if(temp_hostdependency->name != NULL && (new_hostdependency->name = (char *)strdup(temp_hostdependency->name)) == NULL) - error = TRUE; - - if(error == TRUE) { - my_free(new_hostdependency->dependent_host_name); - my_free(new_hostdependency->host_name); - my_free(new_hostdependency->template); - my_free(new_hostdependency->name); - my_free(new_hostdependency); - return ERROR; - } - - /* duplicate non-string members */ - new_hostdependency->fail_notify_on_up = temp_hostdependency->fail_notify_on_up; - new_hostdependency->fail_notify_on_down = temp_hostdependency->fail_notify_on_down; - new_hostdependency->fail_notify_on_unreachable = temp_hostdependency->fail_notify_on_unreachable; - new_hostdependency->fail_notify_on_pending = temp_hostdependency->fail_notify_on_pending; - new_hostdependency->have_notification_dependency_options = temp_hostdependency->have_notification_dependency_options; - new_hostdependency->fail_execute_on_up = temp_hostdependency->fail_execute_on_up; - new_hostdependency->fail_execute_on_down = temp_hostdependency->fail_execute_on_down; - new_hostdependency->fail_execute_on_unreachable = temp_hostdependency->fail_execute_on_unreachable; - new_hostdependency->fail_execute_on_pending = temp_hostdependency->fail_execute_on_pending; - new_hostdependency->have_execution_dependency_options = temp_hostdependency->have_execution_dependency_options; - new_hostdependency->inherits_parent = temp_hostdependency->inherits_parent; - new_hostdependency->have_inherits_parent = temp_hostdependency->have_inherits_parent; - - /* add new hostdependency to head of list in memory */ - new_hostdependency->next = xodtemplate_hostdependency_list; - xodtemplate_hostdependency_list = new_hostdependency; - - return OK; - } - - - -/* duplicates a service dependency definition */ -int xodtemplate_duplicate_servicedependency(xodtemplate_servicedependency *temp_servicedependency, char *master_host_name, char *master_service_description, char *master_hostgroup_name, char *master_servicegroup_name, char *dependent_host_name, char *dependent_service_description, char *dependent_hostgroup_name, char *dependent_servicegroup_name) { - xodtemplate_servicedependency *new_servicedependency = NULL; - int error = FALSE; - - /* allocate memory for a new service dependency definition */ - new_servicedependency = (xodtemplate_servicedependency *)calloc(1, sizeof(xodtemplate_servicedependency)); - if(new_servicedependency == NULL) - return ERROR; - - /* standard items */ - new_servicedependency->has_been_resolved = temp_servicedependency->has_been_resolved; - new_servicedependency->register_object = temp_servicedependency->register_object; - new_servicedependency->_config_file = temp_servicedependency->_config_file; - new_servicedependency->_start_line = temp_servicedependency->_start_line; - - /* string defaults */ - new_servicedependency->have_host_name = (master_host_name) ? TRUE : FALSE; - new_servicedependency->have_service_description = (master_service_description) ? TRUE : FALSE; - new_servicedependency->have_hostgroup_name = (master_hostgroup_name) ? TRUE : FALSE; - new_servicedependency->have_servicegroup_name = (master_servicegroup_name) ? TRUE : FALSE; - - new_servicedependency->have_dependent_host_name = (dependent_host_name) ? TRUE : FALSE; - new_servicedependency->have_dependent_service_description = (dependent_service_description) ? TRUE : FALSE; - new_servicedependency->have_dependent_hostgroup_name = (dependent_hostgroup_name) ? TRUE : FALSE; - new_servicedependency->have_dependent_servicegroup_name = (dependent_servicegroup_name) ? TRUE : FALSE; - - new_servicedependency->have_dependency_period = temp_servicedependency->have_dependency_period; - - /* duplicate strings */ - if(master_host_name != NULL && (new_servicedependency->host_name = (char *)strdup(master_host_name)) == NULL) - error = TRUE; - if(master_service_description != NULL && (new_servicedependency->service_description = (char *)strdup(master_service_description)) == NULL) - error = TRUE; - if(master_hostgroup_name != NULL && (new_servicedependency->hostgroup_name = (char *)strdup(master_hostgroup_name)) == NULL) - error = TRUE; - if(master_servicegroup_name != NULL && (new_servicedependency->servicegroup_name = (char *)strdup(master_servicegroup_name)) == NULL) - error = TRUE; - if(dependent_host_name != NULL && (new_servicedependency->dependent_host_name = (char *)strdup(dependent_host_name)) == NULL) - error = TRUE; - if(dependent_service_description != NULL && (new_servicedependency->dependent_service_description = (char *)strdup(dependent_service_description)) == NULL) - error = TRUE; - if(dependent_hostgroup_name != NULL && (new_servicedependency->dependent_hostgroup_name = (char *)strdup(dependent_hostgroup_name)) == NULL) - error = TRUE; - if(dependent_servicegroup_name != NULL && (new_servicedependency->dependent_servicegroup_name = (char *)strdup(dependent_servicegroup_name)) == NULL) - error = TRUE; - - if(temp_servicedependency->dependency_period != NULL && (new_servicedependency->dependency_period = (char *)strdup(temp_servicedependency->dependency_period)) == NULL) - error = TRUE; - if(temp_servicedependency->template != NULL && (new_servicedependency->template = (char *)strdup(temp_servicedependency->template)) == NULL) - error = TRUE; - if(temp_servicedependency->name != NULL && (new_servicedependency->name = (char *)strdup(temp_servicedependency->name)) == NULL) - error = TRUE; - - if(error == TRUE) { - my_free(new_servicedependency->host_name); - my_free(new_servicedependency->service_description); - my_free(new_servicedependency->hostgroup_name); - my_free(new_servicedependency->servicegroup_name); - my_free(new_servicedependency->dependent_host_name); - my_free(new_servicedependency->dependent_service_description); - my_free(new_servicedependency->dependent_hostgroup_name); - my_free(new_servicedependency->dependent_servicegroup_name); - my_free(new_servicedependency->dependency_period); - my_free(new_servicedependency->template); - my_free(new_servicedependency->name); - my_free(new_servicedependency); - return ERROR; - } - - /* duplicate non-string members */ - new_servicedependency->fail_notify_on_ok = temp_servicedependency->fail_notify_on_ok; - new_servicedependency->fail_notify_on_unknown = temp_servicedependency->fail_notify_on_unknown; - new_servicedependency->fail_notify_on_warning = temp_servicedependency->fail_notify_on_warning; - new_servicedependency->fail_notify_on_critical = temp_servicedependency->fail_notify_on_critical; - new_servicedependency->fail_notify_on_pending = temp_servicedependency->fail_notify_on_pending; - new_servicedependency->have_notification_dependency_options = temp_servicedependency->have_notification_dependency_options; - new_servicedependency->fail_execute_on_ok = temp_servicedependency->fail_execute_on_ok; - new_servicedependency->fail_execute_on_unknown = temp_servicedependency->fail_execute_on_unknown; - new_servicedependency->fail_execute_on_warning = temp_servicedependency->fail_execute_on_warning; - new_servicedependency->fail_execute_on_critical = temp_servicedependency->fail_execute_on_critical; - new_servicedependency->fail_execute_on_pending = temp_servicedependency->fail_execute_on_pending; - new_servicedependency->have_execution_dependency_options = temp_servicedependency->have_execution_dependency_options; - new_servicedependency->inherits_parent = temp_servicedependency->inherits_parent; - new_servicedependency->have_inherits_parent = temp_servicedependency->have_inherits_parent; - - /* add new servicedependency to head of list in memory */ - new_servicedependency->next = xodtemplate_servicedependency_list; - xodtemplate_servicedependency_list = new_servicedependency; - - return OK; - } - - - -/* duplicates a hostextinfo object definition */ -int xodtemplate_duplicate_hostextinfo(xodtemplate_hostextinfo *this_hostextinfo, char *host_name) { - xodtemplate_hostextinfo *new_hostextinfo = NULL; - int error = FALSE; - - /* allocate zero'd out memory for a new hostextinfo object */ - new_hostextinfo = (xodtemplate_hostextinfo *)calloc(1, sizeof(xodtemplate_hostextinfo)); - if(new_hostextinfo == NULL) - return ERROR; - - /* standard items */ - new_hostextinfo->has_been_resolved = this_hostextinfo->has_been_resolved; - new_hostextinfo->register_object = this_hostextinfo->register_object; - new_hostextinfo->_config_file = this_hostextinfo->_config_file; - new_hostextinfo->_start_line = this_hostextinfo->_start_line; - - /* string defaults */ - new_hostextinfo->have_host_name = this_hostextinfo->have_host_name; - new_hostextinfo->have_hostgroup_name = this_hostextinfo->have_hostgroup_name; - new_hostextinfo->have_notes = this_hostextinfo->have_notes; - new_hostextinfo->have_notes_url = this_hostextinfo->have_notes_url; - new_hostextinfo->have_action_url = this_hostextinfo->have_action_url; - new_hostextinfo->have_icon_image = this_hostextinfo->have_icon_image; - new_hostextinfo->have_icon_image_alt = this_hostextinfo->have_icon_image_alt; - new_hostextinfo->have_vrml_image = this_hostextinfo->have_vrml_image; - new_hostextinfo->have_statusmap_image = this_hostextinfo->have_statusmap_image; - - /* duplicate strings (host_name member is passed in) */ - if(host_name != NULL && (new_hostextinfo->host_name = (char *)strdup(host_name)) == NULL) - error = TRUE; - if(this_hostextinfo->template != NULL && (new_hostextinfo->template = (char *)strdup(this_hostextinfo->template)) == NULL) - error = TRUE; - if(this_hostextinfo->name != NULL && (new_hostextinfo->name = (char *)strdup(this_hostextinfo->name)) == NULL) - error = TRUE; - if(this_hostextinfo->notes != NULL && (new_hostextinfo->notes = (char *)strdup(this_hostextinfo->notes)) == NULL) - error = TRUE; - if(this_hostextinfo->notes_url != NULL && (new_hostextinfo->notes_url = (char *)strdup(this_hostextinfo->notes_url)) == NULL) - error = TRUE; - if(this_hostextinfo->action_url != NULL && (new_hostextinfo->action_url = (char *)strdup(this_hostextinfo->action_url)) == NULL) - error = TRUE; - if(this_hostextinfo->icon_image != NULL && (new_hostextinfo->icon_image = (char *)strdup(this_hostextinfo->icon_image)) == NULL) - error = TRUE; - if(this_hostextinfo->icon_image_alt != NULL && (new_hostextinfo->icon_image_alt = (char *)strdup(this_hostextinfo->icon_image_alt)) == NULL) - error = TRUE; - if(this_hostextinfo->vrml_image != NULL && (new_hostextinfo->vrml_image = (char *)strdup(this_hostextinfo->vrml_image)) == NULL) - error = TRUE; - if(this_hostextinfo->statusmap_image != NULL && (new_hostextinfo->statusmap_image = (char *)strdup(this_hostextinfo->statusmap_image)) == NULL) - error = TRUE; - - if(error == TRUE) { - my_free(new_hostextinfo->host_name); - my_free(new_hostextinfo->template); - my_free(new_hostextinfo->name); - my_free(new_hostextinfo->notes); - my_free(new_hostextinfo->notes_url); - my_free(new_hostextinfo->action_url); - my_free(new_hostextinfo->icon_image); - my_free(new_hostextinfo->icon_image_alt); - my_free(new_hostextinfo->vrml_image); - my_free(new_hostextinfo->statusmap_image); - my_free(new_hostextinfo); - return ERROR; - } - - /* duplicate non-string members */ - new_hostextinfo->x_2d = this_hostextinfo->x_2d; - new_hostextinfo->y_2d = this_hostextinfo->y_2d; - new_hostextinfo->have_2d_coords = this_hostextinfo->have_2d_coords; - new_hostextinfo->x_3d = this_hostextinfo->x_3d; - new_hostextinfo->y_3d = this_hostextinfo->y_3d; - new_hostextinfo->z_3d = this_hostextinfo->z_3d; - new_hostextinfo->have_3d_coords = this_hostextinfo->have_3d_coords; - - /* add new object to head of list */ - new_hostextinfo->next = xodtemplate_hostextinfo_list; - xodtemplate_hostextinfo_list = new_hostextinfo; - - return OK; - } - - - -/* duplicates a serviceextinfo object definition */ -int xodtemplate_duplicate_serviceextinfo(xodtemplate_serviceextinfo *this_serviceextinfo, char *host_name) { - xodtemplate_serviceextinfo *new_serviceextinfo = NULL; - int error = FALSE; - - /* allocate zero'd out object for a new serviceextinfo object */ - new_serviceextinfo = (xodtemplate_serviceextinfo *)calloc(1, sizeof(xodtemplate_serviceextinfo)); - if(new_serviceextinfo == NULL) - return ERROR; - - /* standard items */ - new_serviceextinfo->has_been_resolved = this_serviceextinfo->has_been_resolved; - new_serviceextinfo->register_object = this_serviceextinfo->register_object; - new_serviceextinfo->_config_file = this_serviceextinfo->_config_file; - new_serviceextinfo->_start_line = this_serviceextinfo->_start_line; - - /* string defaults */ - new_serviceextinfo->have_host_name = this_serviceextinfo->have_host_name; - new_serviceextinfo->have_service_description = this_serviceextinfo->have_service_description; - new_serviceextinfo->have_hostgroup_name = this_serviceextinfo->have_hostgroup_name; - new_serviceextinfo->have_notes = this_serviceextinfo->have_notes; - new_serviceextinfo->have_notes_url = this_serviceextinfo->have_notes_url; - new_serviceextinfo->have_action_url = this_serviceextinfo->have_action_url; - new_serviceextinfo->have_icon_image = this_serviceextinfo->have_icon_image; - new_serviceextinfo->have_icon_image_alt = this_serviceextinfo->have_icon_image_alt; - - /* duplicate strings (host_name member is passed in) */ - if(host_name != NULL && (new_serviceextinfo->host_name = (char *)strdup(host_name)) == NULL) - error = TRUE; - if(this_serviceextinfo->template != NULL && (new_serviceextinfo->template = (char *)strdup(this_serviceextinfo->template)) == NULL) - error = TRUE; - if(this_serviceextinfo->name != NULL && (new_serviceextinfo->name = (char *)strdup(this_serviceextinfo->name)) == NULL) - error = TRUE; - if(this_serviceextinfo->service_description != NULL && (new_serviceextinfo->service_description = (char *)strdup(this_serviceextinfo->service_description)) == NULL) - error = TRUE; - if(this_serviceextinfo->notes != NULL && (new_serviceextinfo->notes = (char *)strdup(this_serviceextinfo->notes)) == NULL) - error = TRUE; - if(this_serviceextinfo->notes_url != NULL && (new_serviceextinfo->notes_url = (char *)strdup(this_serviceextinfo->notes_url)) == NULL) - error = TRUE; - if(this_serviceextinfo->action_url != NULL && (new_serviceextinfo->action_url = (char *)strdup(this_serviceextinfo->action_url)) == NULL) - error = TRUE; - if(this_serviceextinfo->icon_image != NULL && (new_serviceextinfo->icon_image = (char *)strdup(this_serviceextinfo->icon_image)) == NULL) - error = TRUE; - if(this_serviceextinfo->icon_image_alt != NULL && (new_serviceextinfo->icon_image_alt = (char *)strdup(this_serviceextinfo->icon_image_alt)) == NULL) - error = TRUE; - - if(error == TRUE) { - my_free(new_serviceextinfo->host_name); - my_free(new_serviceextinfo->template); - my_free(new_serviceextinfo->name); - my_free(new_serviceextinfo->service_description); - my_free(new_serviceextinfo->notes); - my_free(new_serviceextinfo->notes_url); - my_free(new_serviceextinfo->action_url); - my_free(new_serviceextinfo->icon_image); - my_free(new_serviceextinfo->icon_image_alt); - my_free(new_serviceextinfo); - return ERROR; - } - - /* add new object to head of list */ - new_serviceextinfo->next = xodtemplate_serviceextinfo_list; - xodtemplate_serviceextinfo_list = new_serviceextinfo; - - return OK; - } - -#endif - - /******************************************************************/ /***************** OBJECT RESOLUTION FUNCTIONS ********************/ /******************************************************************/ -#ifdef NSCORE /* inherit object properties */ /* some missing defaults (notification options, etc.) are also applied here */ @@ -5750,11 +4636,7 @@ int xodtemplate_inherit_object_properties(void) { /* if notification options are missing, assume all */ if(temp_host->have_notification_options == FALSE) { - temp_host->notify_on_down = TRUE; - temp_host->notify_on_unreachable = TRUE; - temp_host->notify_on_recovery = TRUE; - temp_host->notify_on_flapping = TRUE; - temp_host->notify_on_downtime = TRUE; + temp_host->notification_options = OPT_ALL; temp_host->have_notification_options = TRUE; } } @@ -5766,38 +4648,24 @@ int xodtemplate_inherit_object_properties(void) { if((temp_host = xodtemplate_find_real_host(temp_service->host_name)) == NULL) continue; - /* services inherit contact groups from host if not already specified */ - if(temp_service->have_contact_groups == FALSE && temp_host->have_contact_groups == TRUE && temp_host->contact_groups != NULL) { - temp_service->contact_groups = (char *)strdup(temp_host->contact_groups); - temp_service->have_contact_groups = TRUE; - } - - /* services inherit contacts from host if not already specified */ - if(temp_service->have_contacts == FALSE && temp_host->have_contacts == TRUE && temp_host->contacts != NULL) { - temp_service->contacts = (char *)strdup(temp_host->contacts); - temp_service->have_contacts = TRUE; + /* + * if the service has no contacts specified, it will inherit + * them from the host + */ + if(temp_service->have_contact_groups == FALSE && temp_service->have_contacts == FALSE) { + xod_inherit_str(temp_service, temp_host, contact_groups); + xod_inherit_str(temp_service, temp_host, contacts); } /* services inherit notification interval from host if not already specified */ - if(temp_service->have_notification_interval == FALSE && temp_host->have_notification_interval == TRUE) { - temp_service->notification_interval = temp_host->notification_interval; - temp_service->have_notification_interval = TRUE; - } + xod_inherit(temp_service, temp_host, notification_interval); /* services inherit notification period from host if not already specified */ - if(temp_service->have_notification_period == FALSE && temp_host->have_notification_period == TRUE && temp_host->notification_period != NULL) { - temp_service->notification_period = (char *)strdup(temp_host->notification_period); - temp_service->have_notification_period = TRUE; - } + xod_inherit_str(temp_service, temp_host, notification_period); /* if notification options are missing, assume all */ if(temp_service->have_notification_options == FALSE) { - temp_service->notify_on_unknown = TRUE; - temp_service->notify_on_warning = TRUE; - temp_service->notify_on_critical = TRUE; - temp_service->notify_on_recovery = TRUE; - temp_service->notify_on_flapping = TRUE; - temp_service->notify_on_downtime = TRUE; + temp_service->notification_options = OPT_ALL; temp_service->have_notification_options = TRUE; } } @@ -5809,32 +4677,23 @@ int xodtemplate_inherit_object_properties(void) { if((temp_service = xodtemplate_find_real_service(temp_serviceescalation->host_name, temp_serviceescalation->service_description)) == NULL) continue; - /* service escalations inherit contact groups from service if not already specified */ - if(temp_serviceescalation->have_contact_groups == FALSE && temp_service->have_contact_groups == TRUE && temp_service->contact_groups != NULL) { - temp_serviceescalation->contact_groups = (char *)strdup(temp_service->contact_groups); - temp_serviceescalation->have_contact_groups = TRUE; - } - /* SPECIAL RULE 10/04/07 - additive inheritance from service's contactgroup(s) */ if(temp_serviceescalation->contact_groups != NULL && temp_serviceescalation->contact_groups[0] == '+') xodtemplate_get_inherited_string(&temp_service->have_contact_groups, &temp_service->contact_groups, &temp_serviceescalation->have_contact_groups, &temp_serviceescalation->contact_groups); - /* service escalations inherit contacts from service if not already specified */ - if(temp_serviceescalation->have_contacts == FALSE && temp_service->have_contacts == TRUE && temp_service->contacts != NULL) { - temp_serviceescalation->contacts = (char *)strdup(temp_service->contacts); - temp_serviceescalation->have_contacts = TRUE; - } - /* SPECIAL RULE 10/04/07 - additive inheritance from service's contact(s) */ if(temp_serviceescalation->contacts != NULL && temp_serviceescalation->contacts[0] == '+') xodtemplate_get_inherited_string(&temp_service->have_contacts, &temp_service->contacts, &temp_serviceescalation->have_contacts, &temp_serviceescalation->contacts); - /* service escalations inherit notification interval from service if not already defined */ - if(temp_serviceescalation->have_notification_interval == FALSE && temp_service->have_notification_interval == TRUE) { - temp_serviceescalation->notification_interval = temp_service->notification_interval; - temp_serviceescalation->have_notification_interval = TRUE; + /* service escalations inherit contacts from service if none are specified */ + if(temp_serviceescalation->have_contact_groups == FALSE && temp_serviceescalation->have_contacts == FALSE) { + xod_inherit_str(temp_serviceescalation, temp_service, contact_groups); + xod_inherit_str(temp_serviceescalation, temp_service, contacts); } + /* service escalations inherit notification interval from service if not already defined */ + xod_inherit(temp_serviceescalation, temp_service, notification_interval); + /* service escalations inherit escalation period from service if not already defined */ if(temp_serviceescalation->have_escalation_period == FALSE && temp_service->have_notification_period == TRUE && temp_service->notification_period != NULL) { temp_serviceescalation->escalation_period = (char *)strdup(temp_service->notification_period); @@ -5843,10 +4702,7 @@ int xodtemplate_inherit_object_properties(void) { /* if escalation options are missing, assume all */ if(temp_serviceescalation->have_escalation_options == FALSE) { - temp_serviceescalation->escalate_on_unknown = TRUE; - temp_serviceescalation->escalate_on_warning = TRUE; - temp_serviceescalation->escalate_on_critical = TRUE; - temp_serviceescalation->escalate_on_recovery = TRUE; + temp_serviceescalation->escalation_options = OPT_ALL; temp_serviceescalation->have_escalation_options = TRUE; } @@ -5862,32 +4718,23 @@ int xodtemplate_inherit_object_properties(void) { if((temp_host = xodtemplate_find_real_host(temp_hostescalation->host_name)) == NULL) continue; - /* host escalations inherit contact groups from service if not already specified */ - if(temp_hostescalation->have_contact_groups == FALSE && temp_host->have_contact_groups == TRUE && temp_host->contact_groups != NULL) { - temp_hostescalation->contact_groups = (char *)strdup(temp_host->contact_groups); - temp_hostescalation->have_contact_groups = TRUE; - } - /* SPECIAL RULE 10/04/07 - additive inheritance from host's contactgroup(s) */ if(temp_hostescalation->contact_groups != NULL && temp_hostescalation->contact_groups[0] == '+') xodtemplate_get_inherited_string(&temp_host->have_contact_groups, &temp_host->contact_groups, &temp_hostescalation->have_contact_groups, &temp_hostescalation->contact_groups); - /* host escalations inherit contacts from service if not already specified */ - if(temp_hostescalation->have_contacts == FALSE && temp_host->have_contacts == TRUE && temp_host->contacts != NULL) { - temp_hostescalation->contacts = (char *)strdup(temp_host->contacts); - temp_hostescalation->have_contacts = TRUE; - } - /* SPECIAL RULE 10/04/07 - additive inheritance from host's contact(s) */ if(temp_hostescalation->contacts != NULL && temp_hostescalation->contacts[0] == '+') xodtemplate_get_inherited_string(&temp_host->have_contacts, &temp_host->contacts, &temp_hostescalation->have_contacts, &temp_hostescalation->contacts); - /* host escalations inherit notification interval from host if not already defined */ - if(temp_hostescalation->have_notification_interval == FALSE && temp_host->have_notification_interval == TRUE) { - temp_hostescalation->notification_interval = temp_host->notification_interval; - temp_hostescalation->have_notification_interval = TRUE; + /* host escalations inherit contacts from host if none are specified */ + if(temp_hostescalation->have_contact_groups == FALSE && temp_hostescalation->have_contacts == FALSE) { + xod_inherit_str(temp_hostescalation, temp_host, contact_groups); + xod_inherit_str(temp_hostescalation, temp_host, contacts); } + /* host escalations inherit notification interval from host if not already defined */ + xod_inherit(temp_hostescalation, temp_host, notification_interval); + /* host escalations inherit escalation period from host if not already defined */ if(temp_hostescalation->have_escalation_period == FALSE && temp_host->have_notification_period == TRUE && temp_host->notification_period != NULL) { temp_hostescalation->escalation_period = (char *)strdup(temp_host->notification_period); @@ -5896,9 +4743,7 @@ int xodtemplate_inherit_object_properties(void) { /* if escalation options are missing, assume all */ if(temp_hostescalation->have_escalation_options == FALSE) { - temp_hostescalation->escalate_on_down = TRUE; - temp_hostescalation->escalate_on_unreachable = TRUE; - temp_hostescalation->escalate_on_recovery = TRUE; + temp_hostescalation->escalation_options = OPT_ALL; temp_hostescalation->have_escalation_options = TRUE; } @@ -5917,7 +4762,257 @@ int xodtemplate_inherit_object_properties(void) { /***************** OBJECT RESOLUTION FUNCTIONS ********************/ /******************************************************************/ -#ifdef NSCORE +static int xodtemplate_register_and_destroy_hostescalation(void *he_) +{ + xodtemplate_hostescalation *he = (xodtemplate_hostescalation *)he_; + int result; + + result = xodtemplate_register_hostescalation(he); + if(he->is_copy == FALSE) { + my_free(he->escalation_period); + } + my_free(he->contact_groups); + my_free(he->contacts); + my_free(he); + + return result; +} + +static int xodtemplate_register_and_destroy_serviceescalation(void *se_) +{ + xodtemplate_serviceescalation *se = (xodtemplate_serviceescalation *)se_; + int result; + result = xodtemplate_register_serviceescalation(se); + + if(se->is_copy == FALSE) + my_free(se->escalation_period); + + my_free(se->contact_groups); + my_free(se->contacts); + my_free(se); + + return result; +} + +#ifndef NSCGI +static int xodtemplate_register_and_destroy_hostdependency(void *hd_) +{ + xodtemplate_hostdependency *temp_hostdependency = (xodtemplate_hostdependency *)hd_; + objectlist *master_hostlist = NULL, *dependent_hostlist = NULL; + objectlist *list, *next, *l2; + + /* skip host dependencies without enough data */ + if(temp_hostdependency->hostgroup_name == NULL && temp_hostdependency->dependent_hostgroup_name == NULL && temp_hostdependency->host_name == NULL && temp_hostdependency->dependent_host_name == NULL) + return OK; + + /* get list of master host names */ + master_hostlist = xodtemplate_expand_hostgroups_and_hosts(temp_hostdependency->hostgroup_name, temp_hostdependency->host_name, temp_hostdependency->_config_file, temp_hostdependency->_start_line); + if(master_hostlist == NULL && allow_empty_hostgroup_assignment==0) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not expand master hostgroups and/or hosts specified in host dependency (config file '%s', starting on line %d)\n", xodtemplate_config_file_name(temp_hostdependency->_config_file), temp_hostdependency->_start_line); + return ERROR; + } + + /* get list of dependent host names */ + dependent_hostlist = xodtemplate_expand_hostgroups_and_hosts(temp_hostdependency->dependent_hostgroup_name, temp_hostdependency->dependent_host_name, temp_hostdependency->_config_file, temp_hostdependency->_start_line); + if(dependent_hostlist == NULL && allow_empty_hostgroup_assignment==0) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not expand dependent hostgroups (%s) and/or hosts (%s) specified in host dependency (config file '%s', starting on line %d)\n", temp_hostdependency->dependent_hostgroup_name, temp_hostdependency->dependent_host_name, xodtemplate_config_file_name(temp_hostdependency->_config_file), temp_hostdependency->_start_line); + free_objectlist(&master_hostlist); + return ERROR; + } + + my_free(temp_hostdependency->name); + my_free(temp_hostdependency->template); + my_free(temp_hostdependency->host_name); + my_free(temp_hostdependency->hostgroup_name); + my_free(temp_hostdependency->dependent_host_name); + my_free(temp_hostdependency->dependent_hostgroup_name); + + /* duplicate the dependency definitions */ + for(list = master_hostlist; list; list = next) { + xodtemplate_host *master = (xodtemplate_host *)list->object_ptr; + next = list->next; + free(list); + + for(l2 = dependent_hostlist; l2; l2 = l2->next) { + xodtemplate_host *child = (xodtemplate_host *)l2->object_ptr; + + temp_hostdependency->host_name = master->host_name; + temp_hostdependency->dependent_host_name = child->host_name; + if(xodtemplate_register_hostdependency(temp_hostdependency) != OK) { + /* exit on error */ + free_objectlist(&dependent_hostlist); + free_objectlist(&next); + return ERROR; + } + } + } + + free_objectlist(&dependent_hostlist); + my_free(temp_hostdependency->dependency_period); + my_free(temp_hostdependency); + + return OK; +} + +static int xodtemplate_register_and_destroy_servicedependency(void *sd_) +{ + objectlist *parents = NULL, *plist, *pnext; + objectlist *children = NULL, *clist; + xodtemplate_servicedependency *temp_servicedependency = (xodtemplate_servicedependency *)sd_; + int same_host = FALSE, children_first = FALSE, pret = OK, cret = OK; + char *hname, *sdesc, *dhname, *dsdesc; + + hname = temp_servicedependency->host_name; + sdesc = temp_servicedependency->service_description; + dhname = temp_servicedependency->dependent_host_name; + dsdesc = temp_servicedependency->dependent_service_description; + + my_free(temp_servicedependency->name); + my_free(temp_servicedependency->template); + + /* skip templates, but free them first */ + if(temp_servicedependency->register_object == 0) { + my_free(temp_servicedependency->host_name); + my_free(temp_servicedependency->service_description); + my_free(temp_servicedependency->hostgroup_name); + my_free(temp_servicedependency->dependent_host_name); + my_free(temp_servicedependency->dependent_service_description); + my_free(temp_servicedependency->dependent_hostgroup_name); + return OK; + } + + if(!temp_servicedependency->host_name && !temp_servicedependency->hostgroup_name + && !temp_servicedependency->servicegroup_name) + { + /* + * parent service is in exact. We must take children first + * and build parent chain from same-host deps there + */ + children_first = TRUE; + same_host = TRUE; + } + + /* take care of same-host dependencies */ + if(!temp_servicedependency->dependent_host_name && !temp_servicedependency->dependent_hostgroup_name) { + if (!temp_servicedependency->dependent_servicegroup_name) { + if (children_first || !temp_servicedependency->dependent_service_description) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Impossible service dependency definition\n (config file '%s', starting at line '%d')", + xodtemplate_config_file_name(temp_servicedependency->_config_file), + temp_servicedependency->_start_line); + return ERROR; + } + same_host = TRUE; + } + } + + parents = children = NULL; + bitmap_clear(parent_map); + bitmap_clear(service_map); + + /* create the two object lists */ + if(!children_first) { + pret = xodtemplate_create_service_list(&parents, parent_map, temp_servicedependency->host_name, temp_servicedependency->hostgroup_name, temp_servicedependency->servicegroup_name, temp_servicedependency->service_description, temp_servicedependency->_config_file, temp_servicedependency->_start_line); + if (!same_host) + cret = xodtemplate_create_service_list(&children, service_map, temp_servicedependency->dependent_host_name, temp_servicedependency->dependent_hostgroup_name, temp_servicedependency->dependent_servicegroup_name, temp_servicedependency->dependent_service_description, temp_servicedependency->_config_file, temp_servicedependency->_start_line); + } else { + /* + * NOTE: we flip the variables here to avoid duplicating + * the entire loop down below + */ + cret = xodtemplate_create_service_list(&parents, parent_map, temp_servicedependency->dependent_host_name, temp_servicedependency->dependent_hostgroup_name, temp_servicedependency->dependent_servicegroup_name, temp_servicedependency->dependent_service_description, temp_servicedependency->_config_file, temp_servicedependency->_start_line); + dsdesc = temp_servicedependency->service_description; + sdesc = temp_servicedependency->dependent_service_description; + } + + /* now log errors and bail out if we failed to get members */ + if(pret != OK) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not expand master service(s) (config file '%s', starting at line %d)\n", + xodtemplate_config_file_name(temp_servicedependency->_config_file), + temp_servicedependency->_start_line); + } + if(cret != OK) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not expand dependent service(s) (at config file '%s', starting on line %d)\n", + xodtemplate_config_file_name(temp_servicedependency->_config_file), + temp_servicedependency->_start_line); + } + + if(cret != OK || pret != OK) + return ERROR; + + /* + * every service in "children" depends on every service in + * "parents", so just loop twice and create them all. + */ + for(plist = parents; plist; plist = pnext) { + xodtemplate_service *p = (xodtemplate_service *)plist->object_ptr; + pnext = plist->next; + free(plist); /* free it as we go along */ + + if(bitmap_isset(parent_map, p->id)) + continue; + bitmap_set(parent_map, p->id); + + bitmap_clear(service_map); + + + /* + * if this is a same-host dependency, we must expand + * dependent_service_description for the host we're + * currently looking at + */ + if(same_host) { + children = NULL; + if(xodtemplate_expand_services(&children, service_map, p->host_name, dsdesc, temp_servicedependency->_config_file, temp_servicedependency->_start_line) != OK) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Failed to expand same-host servicedependency services (config file '%s', starting at line %d)\n", + xodtemplate_config_file_name(temp_servicedependency->_config_file), + temp_servicedependency->_start_line); + return ERROR; + } + } + + for(clist = children; clist; clist = clist->next) { + xodtemplate_service *c = (xodtemplate_service *)clist->object_ptr; + if(bitmap_isset(service_map, c->id)) + continue; + bitmap_set(service_map, c->id); + + /* now register, but flip the states again if necessary */ + if(children_first) { + xodtemplate_service *tmp = p; + p = c; + c = tmp; + } + temp_servicedependency->host_name = p->host_name; + temp_servicedependency->service_description = p->service_description; + temp_servicedependency->dependent_host_name = c->host_name; + temp_servicedependency->dependent_service_description = c->service_description; + if(xodtemplate_register_servicedependency(temp_servicedependency) != OK) { + logit(NSLOG_VERIFICATION_WARNING, TRUE, "Error: Failed to register servicedependency from '%s;%s' to '%s;%s' (config file '%s', starting at line %d)\n", + p->host_name, p->service_description, + c->host_name, c->service_description, + xodtemplate_config_file_name(temp_servicedependency->_config_file), temp_servicedependency->_start_line); + return ERROR; + } + } + if(same_host == TRUE) + free_objectlist(&children); + } + if(same_host == FALSE) + free_objectlist(&children); + + my_free(hname); + my_free(sdesc); + my_free(dhname); + my_free(dsdesc); + my_free(temp_servicedependency->hostgroup_name); + my_free(temp_servicedependency->servicegroup_name); + my_free(temp_servicedependency->dependent_hostgroup_name); + my_free(temp_servicedependency->dependent_servicegroup_name); + my_free(temp_servicedependency->dependency_period); + my_free(temp_servicedependency); + return OK; +} + /* resolves object definitions */ int xodtemplate_resolve_objects(void) { @@ -6023,8 +5118,6 @@ int xodtemplate_resolve_objects(void) { return OK; } - - /* resolves a timeperiod object */ int xodtemplate_resolve_timeperiod(xodtemplate_timeperiod *this_timeperiod) { char *temp_ptr = NULL; @@ -6065,17 +5158,12 @@ int xodtemplate_resolve_timeperiod(xodtemplate_timeperiod *this_timeperiod) { xodtemplate_resolve_timeperiod(template_timeperiod); /* apply missing properties from template timeperiod... */ - if(this_timeperiod->timeperiod_name == NULL && template_timeperiod->timeperiod_name != NULL) - this_timeperiod->timeperiod_name = (char *)strdup(template_timeperiod->timeperiod_name); - if(this_timeperiod->alias == NULL && template_timeperiod->alias != NULL) - this_timeperiod->alias = (char *)strdup(template_timeperiod->alias); - if(this_timeperiod->exclusions == NULL && template_timeperiod->exclusions != NULL) - this_timeperiod->exclusions = (char *)strdup(template_timeperiod->exclusions); - for(x = 0; x < 7; x++) { - if(this_timeperiod->timeranges[x] == NULL && template_timeperiod->timeranges[x] != NULL) { - this_timeperiod->timeranges[x] = (char *)strdup(template_timeperiod->timeranges[x]); - } - } + xod_inherit_str_nohave(this_timeperiod, template_timeperiod, timeperiod_name); + xod_inherit_str_nohave(this_timeperiod, template_timeperiod, alias); + xod_inherit_str_nohave(this_timeperiod, template_timeperiod, exclusions); + for(x = 0; x < 7; x++) + xod_inherit_str_nohave(this_timeperiod, template_timeperiod, timeranges[x]); + /* daterange exceptions require more work to apply missing ranges... */ for(x = 0; x < DATERANGE_TYPES; x++) { for(template_daterange = template_timeperiod->exceptions[x]; template_daterange != NULL; template_daterange = template_daterange->next) { @@ -6160,10 +5248,8 @@ int xodtemplate_resolve_command(xodtemplate_command *this_command) { xodtemplate_resolve_command(template_command); /* apply missing properties from template command... */ - if(this_command->command_name == NULL && template_command->command_name != NULL) - this_command->command_name = (char *)strdup(template_command->command_name); - if(this_command->command_line == NULL && template_command->command_line != NULL) - this_command->command_line = (char *)strdup(template_command->command_line); + xod_inherit_str_nohave(this_command, template_command, command_name); + xod_inherit_str_nohave(this_command, template_command, command_line); } my_free(template_names); @@ -6210,10 +5296,8 @@ int xodtemplate_resolve_contactgroup(xodtemplate_contactgroup *this_contactgroup xodtemplate_resolve_contactgroup(template_contactgroup); /* apply missing properties from template contactgroup... */ - if(this_contactgroup->contactgroup_name == NULL && template_contactgroup->contactgroup_name != NULL) - this_contactgroup->contactgroup_name = (char *)strdup(template_contactgroup->contactgroup_name); - if(this_contactgroup->alias == NULL && template_contactgroup->alias != NULL) - this_contactgroup->alias = (char *)strdup(template_contactgroup->alias); + xod_inherit_str_nohave(this_contactgroup, template_contactgroup, contactgroup_name); + xod_inherit_str_nohave(this_contactgroup, template_contactgroup, alias); xodtemplate_get_inherited_string(&template_contactgroup->have_members, &template_contactgroup->members, &this_contactgroup->have_members, &this_contactgroup->members); xodtemplate_get_inherited_string(&template_contactgroup->have_contactgroup_members, &template_contactgroup->contactgroup_members, &this_contactgroup->have_contactgroup_members, &this_contactgroup->contactgroup_members); @@ -6264,29 +5348,15 @@ int xodtemplate_resolve_hostgroup(xodtemplate_hostgroup *this_hostgroup) { xodtemplate_resolve_hostgroup(template_hostgroup); /* apply missing properties from template hostgroup... */ - if(this_hostgroup->hostgroup_name == NULL && template_hostgroup->hostgroup_name != NULL) - this_hostgroup->hostgroup_name = (char *)strdup(template_hostgroup->hostgroup_name); - if(this_hostgroup->alias == NULL && template_hostgroup->alias != NULL) - this_hostgroup->alias = (char *)strdup(template_hostgroup->alias); + xod_inherit_str_nohave(this_hostgroup, template_hostgroup, hostgroup_name); + xod_inherit_str_nohave(this_hostgroup, template_hostgroup, alias); xodtemplate_get_inherited_string(&template_hostgroup->have_members, &template_hostgroup->members, &this_hostgroup->have_members, &this_hostgroup->members); xodtemplate_get_inherited_string(&template_hostgroup->have_hostgroup_members, &template_hostgroup->hostgroup_members, &this_hostgroup->have_hostgroup_members, &this_hostgroup->hostgroup_members); - if(this_hostgroup->have_notes == FALSE && template_hostgroup->have_notes == TRUE) { - if(this_hostgroup->notes == NULL && template_hostgroup->notes != NULL) - this_hostgroup->notes = (char *)strdup(template_hostgroup->notes); - this_hostgroup->have_notes = TRUE; - } - if(this_hostgroup->have_notes_url == FALSE && template_hostgroup->have_notes_url == TRUE) { - if(this_hostgroup->notes_url == NULL && template_hostgroup->notes_url != NULL) - this_hostgroup->notes_url = (char *)strdup(template_hostgroup->notes_url); - this_hostgroup->have_notes_url = TRUE; - } - if(this_hostgroup->have_action_url == FALSE && template_hostgroup->have_action_url == TRUE) { - if(this_hostgroup->action_url == NULL && template_hostgroup->action_url != NULL) - this_hostgroup->action_url = (char *)strdup(template_hostgroup->action_url); - this_hostgroup->have_action_url = TRUE; - } + xod_inherit_str(this_hostgroup, template_hostgroup, notes); + xod_inherit_str(this_hostgroup, template_hostgroup, notes_url); + xod_inherit_str(this_hostgroup, template_hostgroup, action_url); } my_free(template_names); @@ -6333,29 +5403,15 @@ int xodtemplate_resolve_servicegroup(xodtemplate_servicegroup *this_servicegroup xodtemplate_resolve_servicegroup(template_servicegroup); /* apply missing properties from template servicegroup... */ - if(this_servicegroup->servicegroup_name == NULL && template_servicegroup->servicegroup_name != NULL) - this_servicegroup->servicegroup_name = (char *)strdup(template_servicegroup->servicegroup_name); - if(this_servicegroup->alias == NULL && template_servicegroup->alias != NULL) - this_servicegroup->alias = (char *)strdup(template_servicegroup->alias); + xod_inherit_str_nohave(this_servicegroup, template_servicegroup, servicegroup_name); + xod_inherit_str_nohave(this_servicegroup, template_servicegroup, alias); xodtemplate_get_inherited_string(&template_servicegroup->have_members, &template_servicegroup->members, &this_servicegroup->have_members, &this_servicegroup->members); xodtemplate_get_inherited_string(&template_servicegroup->have_servicegroup_members, &template_servicegroup->servicegroup_members, &this_servicegroup->have_servicegroup_members, &this_servicegroup->servicegroup_members); - if(this_servicegroup->have_notes == FALSE && template_servicegroup->have_notes == TRUE) { - if(this_servicegroup->notes == NULL && template_servicegroup->notes != NULL) - this_servicegroup->notes = (char *)strdup(template_servicegroup->notes); - this_servicegroup->have_notes = TRUE; - } - if(this_servicegroup->have_notes_url == FALSE && template_servicegroup->have_notes_url == TRUE) { - if(this_servicegroup->notes_url == NULL && template_servicegroup->notes_url != NULL) - this_servicegroup->notes_url = (char *)strdup(template_servicegroup->notes_url); - this_servicegroup->have_notes_url = TRUE; - } - if(this_servicegroup->have_action_url == FALSE && template_servicegroup->have_action_url == TRUE) { - if(this_servicegroup->action_url == NULL && template_servicegroup->action_url != NULL) - this_servicegroup->action_url = (char *)strdup(template_servicegroup->action_url); - this_servicegroup->have_action_url = TRUE; - } + xod_inherit_str(this_servicegroup, template_servicegroup, notes); + xod_inherit_str(this_servicegroup, template_servicegroup, notes_url); + xod_inherit_str(this_servicegroup, template_servicegroup, action_url); } my_free(template_names); @@ -6418,21 +5474,13 @@ int xodtemplate_resolve_servicedependency(xodtemplate_servicedependency *this_se this_servicedependency->inherits_parent = template_servicedependency->inherits_parent; this_servicedependency->have_inherits_parent = TRUE; } - if(this_servicedependency->have_execution_dependency_options == FALSE && template_servicedependency->have_execution_dependency_options == TRUE) { - this_servicedependency->fail_execute_on_ok = template_servicedependency->fail_execute_on_ok; - this_servicedependency->fail_execute_on_unknown = template_servicedependency->fail_execute_on_unknown; - this_servicedependency->fail_execute_on_warning = template_servicedependency->fail_execute_on_warning; - this_servicedependency->fail_execute_on_critical = template_servicedependency->fail_execute_on_critical; - this_servicedependency->fail_execute_on_pending = template_servicedependency->fail_execute_on_pending; - this_servicedependency->have_execution_dependency_options = TRUE; + if(this_servicedependency->have_execution_failure_options == FALSE && template_servicedependency->have_execution_failure_options == TRUE) { + this_servicedependency->execution_failure_options = template_servicedependency->execution_failure_options; + this_servicedependency->have_execution_failure_options = TRUE; } - if(this_servicedependency->have_notification_dependency_options == FALSE && template_servicedependency->have_notification_dependency_options == TRUE) { - this_servicedependency->fail_notify_on_ok = template_servicedependency->fail_notify_on_ok; - this_servicedependency->fail_notify_on_unknown = template_servicedependency->fail_notify_on_unknown; - this_servicedependency->fail_notify_on_warning = template_servicedependency->fail_notify_on_warning; - this_servicedependency->fail_notify_on_critical = template_servicedependency->fail_notify_on_critical; - this_servicedependency->fail_notify_on_pending = template_servicedependency->fail_notify_on_pending; - this_servicedependency->have_notification_dependency_options = TRUE; + if(this_servicedependency->have_notification_failure_options == FALSE && template_servicedependency->have_notification_failure_options == TRUE) { + this_servicedependency->notification_failure_options = template_servicedependency->notification_failure_options; + this_servicedependency->have_notification_failure_options = TRUE; } } @@ -6503,10 +5551,7 @@ int xodtemplate_resolve_serviceescalation(xodtemplate_serviceescalation *this_se this_serviceescalation->have_notification_interval = TRUE; } if(this_serviceescalation->have_escalation_options == FALSE && template_serviceescalation->have_escalation_options == TRUE) { - this_serviceescalation->escalate_on_warning = template_serviceescalation->escalate_on_warning; - this_serviceescalation->escalate_on_unknown = template_serviceescalation->escalate_on_unknown; - this_serviceescalation->escalate_on_critical = template_serviceescalation->escalate_on_critical; - this_serviceescalation->escalate_on_recovery = template_serviceescalation->escalate_on_recovery; + this_serviceescalation->escalation_options = template_serviceescalation->escalation_options; this_serviceescalation->have_escalation_options = TRUE; } } @@ -6557,80 +5602,28 @@ int xodtemplate_resolve_contact(xodtemplate_contact *this_contact) { xodtemplate_resolve_contact(template_contact); /* apply missing properties from template contact... */ - if(this_contact->contact_name == NULL && template_contact->contact_name != NULL) - this_contact->contact_name = (char *)strdup(template_contact->contact_name); - if(this_contact->alias == NULL && template_contact->alias != NULL) - this_contact->alias = (char *)strdup(template_contact->alias); + xod_inherit_str_nohave(this_contact, template_contact, contact_name); + xod_inherit_str_nohave(this_contact, template_contact, alias); - if(this_contact->have_email == FALSE && template_contact->have_email == TRUE) { - if(this_contact->email == NULL && template_contact->email != NULL) - this_contact->email = (char *)strdup(template_contact->email); - this_contact->have_email = TRUE; - } - if(this_contact->have_pager == FALSE && template_contact->have_pager == TRUE) { - if(this_contact->pager == NULL && template_contact->pager != NULL) - this_contact->pager = (char *)strdup(template_contact->pager); - this_contact->have_pager = TRUE; - } - for(x = 0; x < MAX_XODTEMPLATE_CONTACT_ADDRESSES; x++) { - if(this_contact->have_address[x] == FALSE && template_contact->have_address[x] == TRUE) { - if(this_contact->address[x] == NULL && template_contact->address[x] != NULL) - this_contact->address[x] = (char *)strdup(template_contact->address[x]); - this_contact->have_address[x] = TRUE; - } - } + xod_inherit_str(this_contact, template_contact, email); + xod_inherit_str(this_contact, template_contact, pager); + for(x = 0; x < MAX_XODTEMPLATE_CONTACT_ADDRESSES; x++) + xod_inherit_str(this_contact, template_contact, address[x]); xodtemplate_get_inherited_string(&template_contact->have_contact_groups, &template_contact->contact_groups, &this_contact->have_contact_groups, &this_contact->contact_groups); xodtemplate_get_inherited_string(&template_contact->have_host_notification_commands, &template_contact->host_notification_commands, &this_contact->have_host_notification_commands, &this_contact->host_notification_commands); xodtemplate_get_inherited_string(&template_contact->have_service_notification_commands, &template_contact->service_notification_commands, &this_contact->have_service_notification_commands, &this_contact->service_notification_commands); - if(this_contact->have_host_notification_period == FALSE && template_contact->have_host_notification_period == TRUE) { - if(this_contact->host_notification_period == NULL && template_contact->host_notification_period != NULL) - this_contact->host_notification_period = (char *)strdup(template_contact->host_notification_period); - this_contact->have_host_notification_period = TRUE; - } - if(this_contact->have_service_notification_period == FALSE && template_contact->have_service_notification_period == TRUE) { - if(this_contact->service_notification_period == NULL && template_contact->service_notification_period != NULL) - this_contact->service_notification_period = (char *)strdup(template_contact->service_notification_period); - this_contact->have_service_notification_period = TRUE; - } - if(this_contact->have_host_notification_options == FALSE && template_contact->have_host_notification_options == TRUE) { - this_contact->notify_on_host_down = template_contact->notify_on_host_down; - this_contact->notify_on_host_unreachable = template_contact->notify_on_host_unreachable; - this_contact->notify_on_host_recovery = template_contact->notify_on_host_recovery; - this_contact->notify_on_host_flapping = template_contact->notify_on_host_flapping; - this_contact->notify_on_host_downtime = template_contact->notify_on_host_downtime; - this_contact->have_host_notification_options = TRUE; - } - if(this_contact->have_service_notification_options == FALSE && template_contact->have_service_notification_options == TRUE) { - this_contact->notify_on_service_unknown = template_contact->notify_on_service_unknown; - this_contact->notify_on_service_warning = template_contact->notify_on_service_warning; - this_contact->notify_on_service_critical = template_contact->notify_on_service_critical; - this_contact->notify_on_service_recovery = template_contact->notify_on_service_recovery; - this_contact->notify_on_service_flapping = template_contact->notify_on_service_flapping; - this_contact->notify_on_service_downtime = template_contact->notify_on_service_downtime; - this_contact->have_service_notification_options = TRUE; - } - if(this_contact->have_host_notifications_enabled == FALSE && template_contact->have_host_notifications_enabled == TRUE) { - this_contact->host_notifications_enabled = template_contact->host_notifications_enabled; - this_contact->have_host_notifications_enabled = TRUE; - } - if(this_contact->have_service_notifications_enabled == FALSE && template_contact->have_service_notifications_enabled == TRUE) { - this_contact->service_notifications_enabled = template_contact->service_notifications_enabled; - this_contact->have_service_notifications_enabled = TRUE; - } - if(this_contact->have_can_submit_commands == FALSE && template_contact->have_can_submit_commands == TRUE) { - this_contact->can_submit_commands = template_contact->can_submit_commands; - this_contact->have_can_submit_commands = TRUE; - } - if(this_contact->have_retain_status_information == FALSE && template_contact->have_retain_status_information == TRUE) { - this_contact->retain_status_information = template_contact->retain_status_information; - this_contact->have_retain_status_information = TRUE; - } - if(this_contact->have_retain_nonstatus_information == FALSE && template_contact->have_retain_nonstatus_information == TRUE) { - this_contact->retain_nonstatus_information = template_contact->retain_nonstatus_information; - this_contact->have_retain_nonstatus_information = TRUE; - } + xod_inherit_str(this_contact, template_contact, host_notification_period); + xod_inherit_str(this_contact, template_contact, service_notification_period); + xod_inherit(this_contact, template_contact, host_notification_options); + xod_inherit(this_contact, template_contact, service_notification_options); + xod_inherit(this_contact, template_contact, host_notifications_enabled); + xod_inherit(this_contact, template_contact, service_notifications_enabled); + xod_inherit(this_contact, template_contact, can_submit_commands); + xod_inherit(this_contact, template_contact, retain_status_information); + xod_inherit(this_contact, template_contact, retain_nonstatus_information); + xod_inherit(this_contact, template_contact, minimum_value); /* apply missing custom variables from template contact... */ for(temp_customvariablesmember = template_contact->custom_variables; temp_customvariablesmember != NULL; temp_customvariablesmember = temp_customvariablesmember->next) { @@ -6692,175 +5685,50 @@ int xodtemplate_resolve_host(xodtemplate_host *this_host) { xodtemplate_resolve_host(template_host); /* apply missing properties from template host... */ - if(this_host->host_name == NULL && template_host->host_name != NULL) - this_host->host_name = (char *)strdup(template_host->host_name); - if(this_host->have_display_name == FALSE && template_host->have_display_name == TRUE) { - if(this_host->display_name == NULL && template_host->display_name != NULL) - this_host->display_name = (char *)strdup(template_host->display_name); - this_host->have_display_name = TRUE; - } - if(this_host->alias == NULL && template_host->alias != NULL) - this_host->alias = (char *)strdup(template_host->alias); - if(this_host->address == NULL && template_host->address != NULL) - this_host->address = (char *)strdup(template_host->address); + xod_inherit_str_nohave(this_host, template_host, host_name); + xod_inherit_str(this_host, template_host, display_name); + xod_inherit_str_nohave(this_host, template_host, alias); + xod_inherit_str_nohave(this_host, template_host, address); xodtemplate_get_inherited_string(&template_host->have_parents, &template_host->parents, &this_host->have_parents, &this_host->parents); xodtemplate_get_inherited_string(&template_host->have_host_groups, &template_host->host_groups, &this_host->have_host_groups, &this_host->host_groups); xodtemplate_get_inherited_string(&template_host->have_contact_groups, &template_host->contact_groups, &this_host->have_contact_groups, &this_host->contact_groups); xodtemplate_get_inherited_string(&template_host->have_contacts, &template_host->contacts, &this_host->have_contacts, &this_host->contacts); - if(this_host->have_check_command == FALSE && template_host->have_check_command == TRUE) { - if(this_host->check_command == NULL && template_host->check_command != NULL) - this_host->check_command = (char *)strdup(template_host->check_command); - this_host->have_check_command = TRUE; - } - if(this_host->have_check_period == FALSE && template_host->have_check_period == TRUE) { - if(this_host->check_period == NULL && template_host->check_period != NULL) - this_host->check_period = (char *)strdup(template_host->check_period); - this_host->have_check_period = TRUE; - } - if(this_host->have_event_handler == FALSE && template_host->have_event_handler == TRUE) { - if(this_host->event_handler == NULL && template_host->event_handler != NULL) - this_host->event_handler = (char *)strdup(template_host->event_handler); - this_host->have_event_handler = TRUE; - } - if(this_host->have_notification_period == FALSE && template_host->have_notification_period == TRUE) { - if(this_host->notification_period == NULL && template_host->notification_period != NULL) - this_host->notification_period = (char *)strdup(template_host->notification_period); - this_host->have_notification_period = TRUE; - } - if(this_host->have_failure_prediction_options == FALSE && template_host->have_failure_prediction_options == TRUE) { - if(this_host->failure_prediction_options == NULL && template_host->failure_prediction_options != NULL) - this_host->failure_prediction_options = (char *)strdup(template_host->failure_prediction_options); - this_host->have_failure_prediction_options = TRUE; - } - if(this_host->have_notes == FALSE && template_host->have_notes == TRUE) { - if(this_host->notes == NULL && template_host->notes != NULL) - this_host->notes = (char *)strdup(template_host->notes); - this_host->have_notes = TRUE; - } - if(this_host->have_notes_url == FALSE && template_host->have_notes_url == TRUE) { - if(this_host->notes_url == NULL && template_host->notes_url != NULL) - this_host->notes_url = (char *)strdup(template_host->notes_url); - this_host->have_notes_url = TRUE; - } - if(this_host->have_action_url == FALSE && template_host->have_action_url == TRUE) { - if(this_host->action_url == NULL && template_host->action_url != NULL) - this_host->action_url = (char *)strdup(template_host->action_url); - this_host->have_action_url = TRUE; - } - if(this_host->have_icon_image == FALSE && template_host->have_icon_image == TRUE) { - if(this_host->icon_image == NULL && template_host->icon_image != NULL) - this_host->icon_image = (char *)strdup(template_host->icon_image); - this_host->have_icon_image = TRUE; - } - if(this_host->have_icon_image_alt == FALSE && template_host->have_icon_image_alt == TRUE) { - if(this_host->icon_image_alt == NULL && template_host->icon_image_alt != NULL) - this_host->icon_image_alt = (char *)strdup(template_host->icon_image_alt); - this_host->have_icon_image_alt = TRUE; - } - if(this_host->have_vrml_image == FALSE && template_host->have_vrml_image == TRUE) { - if(this_host->vrml_image == NULL && template_host->vrml_image != NULL) - this_host->vrml_image = (char *)strdup(template_host->vrml_image); - this_host->have_vrml_image = TRUE; - } - if(this_host->have_statusmap_image == FALSE && template_host->have_statusmap_image == TRUE) { - if(this_host->statusmap_image == NULL && template_host->statusmap_image != NULL) - this_host->statusmap_image = (char *)strdup(template_host->statusmap_image); - this_host->have_statusmap_image = TRUE; - } - if(this_host->have_initial_state == FALSE && template_host->have_initial_state == TRUE) { - this_host->initial_state = template_host->initial_state; - this_host->have_initial_state = TRUE; - } - if(this_host->have_check_interval == FALSE && template_host->have_check_interval == TRUE) { - this_host->check_interval = template_host->check_interval; - this_host->have_check_interval = TRUE; - } - if(this_host->have_retry_interval == FALSE && template_host->have_retry_interval == TRUE) { - this_host->retry_interval = template_host->retry_interval; - this_host->have_retry_interval = TRUE; - } - if(this_host->have_max_check_attempts == FALSE && template_host->have_max_check_attempts == TRUE) { - this_host->max_check_attempts = template_host->max_check_attempts; - this_host->have_max_check_attempts = TRUE; - } - if(this_host->have_active_checks_enabled == FALSE && template_host->have_active_checks_enabled == TRUE) { - this_host->active_checks_enabled = template_host->active_checks_enabled; - this_host->have_active_checks_enabled = TRUE; - } - if(this_host->have_passive_checks_enabled == FALSE && template_host->have_passive_checks_enabled == TRUE) { - this_host->passive_checks_enabled = template_host->passive_checks_enabled; - this_host->have_passive_checks_enabled = TRUE; - } - if(this_host->have_obsess_over_host == FALSE && template_host->have_obsess_over_host == TRUE) { - this_host->obsess_over_host = template_host->obsess_over_host; - this_host->have_obsess_over_host = TRUE; - } - if(this_host->have_event_handler_enabled == FALSE && template_host->have_event_handler_enabled == TRUE) { - this_host->event_handler_enabled = template_host->event_handler_enabled; - this_host->have_event_handler_enabled = TRUE; - } - if(this_host->have_check_freshness == FALSE && template_host->have_check_freshness == TRUE) { - this_host->check_freshness = template_host->check_freshness; - this_host->have_check_freshness = TRUE; - } - if(this_host->have_freshness_threshold == FALSE && template_host->have_freshness_threshold == TRUE) { - this_host->freshness_threshold = template_host->freshness_threshold; - this_host->have_freshness_threshold = TRUE; - } - if(this_host->have_low_flap_threshold == FALSE && template_host->have_low_flap_threshold == TRUE) { - this_host->low_flap_threshold = template_host->low_flap_threshold; - this_host->have_low_flap_threshold = TRUE; - } - if(this_host->have_high_flap_threshold == FALSE && template_host->have_high_flap_threshold == TRUE) { - this_host->high_flap_threshold = template_host->high_flap_threshold; - this_host->have_high_flap_threshold = TRUE; - } - if(this_host->have_flap_detection_enabled == FALSE && template_host->have_flap_detection_enabled == TRUE) { - this_host->flap_detection_enabled = template_host->flap_detection_enabled; - this_host->have_flap_detection_enabled = TRUE; - } - if(this_host->have_flap_detection_options == FALSE && template_host->have_flap_detection_options == TRUE) { - this_host->flap_detection_on_up = template_host->flap_detection_on_up; - this_host->flap_detection_on_down = template_host->flap_detection_on_down; - this_host->flap_detection_on_unreachable = template_host->flap_detection_on_unreachable; - this_host->have_flap_detection_options = TRUE; - } - if(this_host->have_notification_options == FALSE && template_host->have_notification_options == TRUE) { - this_host->notify_on_down = template_host->notify_on_down; - this_host->notify_on_unreachable = template_host->notify_on_unreachable; - this_host->notify_on_recovery = template_host->notify_on_recovery; - this_host->notify_on_flapping = template_host->notify_on_flapping; - this_host->notify_on_downtime = template_host->notify_on_downtime; - this_host->have_notification_options = TRUE; - } - if(this_host->have_notifications_enabled == FALSE && template_host->have_notifications_enabled == TRUE) { - this_host->notifications_enabled = template_host->notifications_enabled; - this_host->have_notifications_enabled = TRUE; - } - if(this_host->have_notification_interval == FALSE && template_host->have_notification_interval == TRUE) { - this_host->notification_interval = template_host->notification_interval; - this_host->have_notification_interval = TRUE; - } - if(this_host->have_first_notification_delay == FALSE && template_host->have_first_notification_delay == TRUE) { - this_host->first_notification_delay = template_host->first_notification_delay; - this_host->have_first_notification_delay = TRUE; - } - if(this_host->have_stalking_options == FALSE && template_host->have_stalking_options == TRUE) { - this_host->stalk_on_up = template_host->stalk_on_up; - this_host->stalk_on_down = template_host->stalk_on_down; - this_host->stalk_on_unreachable = template_host->stalk_on_unreachable; - this_host->have_stalking_options = TRUE; - } - if(this_host->have_process_perf_data == FALSE && template_host->have_process_perf_data == TRUE) { - this_host->process_perf_data = template_host->process_perf_data; - this_host->have_process_perf_data = TRUE; - } - if(this_host->have_failure_prediction_enabled == FALSE && template_host->have_failure_prediction_enabled == TRUE) { - this_host->failure_prediction_enabled = template_host->failure_prediction_enabled; - this_host->have_failure_prediction_enabled = TRUE; - } + xod_inherit_str(this_host, template_host, check_command); + xod_inherit_str(this_host, template_host, check_period); + xod_inherit_str(this_host, template_host, event_handler); + xod_inherit_str(this_host, template_host, notification_period); + xod_inherit_str(this_host, template_host, notes); + xod_inherit_str(this_host, template_host, notes_url); + xod_inherit_str(this_host, template_host, action_url); + xod_inherit_str(this_host, template_host, icon_image); + xod_inherit_str(this_host, template_host, icon_image_alt); + xod_inherit_str(this_host, template_host, vrml_image); + xod_inherit_str(this_host, template_host, statusmap_image); + + xod_inherit(this_host, template_host, initial_state); + xod_inherit(this_host, template_host, check_interval); + xod_inherit(this_host, template_host, retry_interval); + xod_inherit(this_host, template_host, max_check_attempts); + xod_inherit(this_host, template_host, active_checks_enabled); + xod_inherit(this_host, template_host, passive_checks_enabled); + xod_inherit(this_host, template_host, obsess); + xod_inherit(this_host, template_host, event_handler_enabled); + xod_inherit(this_host, template_host, check_freshness); + xod_inherit(this_host, template_host, freshness_threshold); + xod_inherit(this_host, template_host, low_flap_threshold); + xod_inherit(this_host, template_host, high_flap_threshold); + xod_inherit(this_host, template_host, flap_detection_enabled); + xod_inherit(this_host, template_host, flap_detection_options); + xod_inherit(this_host, template_host, notification_options); + xod_inherit(this_host, template_host, notifications_enabled); + xod_inherit(this_host, template_host, notification_interval); + xod_inherit(this_host, template_host, first_notification_delay); + xod_inherit(this_host, template_host, stalking_options); + xod_inherit(this_host, template_host, process_perf_data); + xod_inherit(this_host, template_host, hourly_value); + if(this_host->have_2d_coords == FALSE && template_host->have_2d_coords == TRUE) { this_host->x_2d = template_host->x_2d; this_host->y_2d = template_host->y_2d; @@ -6872,14 +5740,9 @@ int xodtemplate_resolve_host(xodtemplate_host *this_host) { this_host->z_3d = template_host->z_3d; this_host->have_3d_coords = TRUE; } - if(this_host->have_retain_status_information == FALSE && template_host->have_retain_status_information == TRUE) { - this_host->retain_status_information = template_host->retain_status_information; - this_host->have_retain_status_information = TRUE; - } - if(this_host->have_retain_nonstatus_information == FALSE && template_host->have_retain_nonstatus_information == TRUE) { - this_host->retain_nonstatus_information = template_host->retain_nonstatus_information; - this_host->have_retain_nonstatus_information = TRUE; - } + + xod_inherit(this_host, template_host, retain_status_information); + xod_inherit(this_host, template_host, retain_nonstatus_information); /* apply missing custom variables from template host... */ for(temp_customvariablesmember = template_host->custom_variables; temp_customvariablesmember != NULL; temp_customvariablesmember = temp_customvariablesmember->next) { @@ -6941,17 +5804,10 @@ int xodtemplate_resolve_service(xodtemplate_service *this_service) { xodtemplate_resolve_service(template_service); /* apply missing properties from template service... */ - if(this_service->have_service_description == FALSE && template_service->have_service_description == TRUE) { - if(this_service->service_description == NULL && template_service->service_description != NULL) - this_service->service_description = (char *)strdup(template_service->service_description); - this_service->have_service_description = TRUE; - } - if(this_service->have_display_name == FALSE && template_service->have_display_name == TRUE) { - if(this_service->display_name == NULL && template_service->display_name != NULL) - this_service->display_name = (char *)strdup(template_service->display_name); - this_service->have_display_name = TRUE; - } + xod_inherit_str(this_service, template_service, service_description); + xod_inherit_str(this_service, template_service, display_name); + xodtemplate_get_inherited_string(&template_service->have_parents, &template_service->parents, &this_service->have_parents, &this_service->parents); xodtemplate_get_inherited_string(&template_service->have_host_name, &template_service->host_name, &this_service->have_host_name, &this_service->host_name); xodtemplate_get_inherited_string(&template_service->have_hostgroup_name, &template_service->hostgroup_name, &this_service->have_hostgroup_name, &this_service->hostgroup_name); xodtemplate_get_inherited_string(&template_service->have_service_groups, &template_service->service_groups, &this_service->have_service_groups, &this_service->service_groups); @@ -6963,168 +5819,43 @@ int xodtemplate_resolve_service(xodtemplate_service *this_service) { my_free(this_service->check_command); this_service->have_check_command = FALSE; } - if(this_service->have_check_command == FALSE) { - if(this_service->check_command == NULL && template_service->check_command != NULL) - this_service->check_command = (char *)strdup(template_service->check_command); - this_service->have_check_command = TRUE; - } - } - if(this_service->have_check_period == FALSE && template_service->have_check_period == TRUE) { - if(this_service->check_period == NULL && template_service->check_period != NULL) - this_service->check_period = (char *)strdup(template_service->check_period); - this_service->have_check_period = TRUE; - } - if(this_service->have_event_handler == FALSE && template_service->have_event_handler == TRUE) { - if(this_service->event_handler == NULL && template_service->event_handler != NULL) - this_service->event_handler = (char *)strdup(template_service->event_handler); - this_service->have_event_handler = TRUE; - } - if(this_service->have_notification_period == FALSE && template_service->have_notification_period == TRUE) { - if(this_service->notification_period == NULL && template_service->notification_period != NULL) - this_service->notification_period = (char *)strdup(template_service->notification_period); - this_service->have_notification_period = TRUE; - } - if(this_service->have_failure_prediction_options == FALSE && template_service->have_failure_prediction_options == TRUE) { - if(this_service->failure_prediction_options == NULL && template_service->failure_prediction_options != NULL) - this_service->failure_prediction_options = (char *)strdup(template_service->failure_prediction_options); - this_service->have_failure_prediction_options = TRUE; - } - if(this_service->have_notes == FALSE && template_service->have_notes == TRUE) { - if(this_service->notes == NULL && template_service->notes != NULL) - this_service->notes = (char *)strdup(template_service->notes); - this_service->have_notes = TRUE; - } - if(this_service->have_notes_url == FALSE && template_service->have_notes_url == TRUE) { - if(this_service->notes_url == NULL && template_service->notes_url != NULL) - this_service->notes_url = (char *)strdup(template_service->notes_url); - this_service->have_notes_url = TRUE; - } - if(this_service->have_action_url == FALSE && template_service->have_action_url == TRUE) { - if(this_service->action_url == NULL && template_service->action_url != NULL) - this_service->action_url = (char *)strdup(template_service->action_url); - this_service->have_action_url = TRUE; - } - if(this_service->have_icon_image == FALSE && template_service->have_icon_image == TRUE) { - if(this_service->icon_image == NULL && template_service->icon_image != NULL) - this_service->icon_image = (char *)strdup(template_service->icon_image); - this_service->have_icon_image = TRUE; - } - if(this_service->have_icon_image_alt == FALSE && template_service->have_icon_image_alt == TRUE) { - if(this_service->icon_image_alt == NULL && template_service->icon_image_alt != NULL) - this_service->icon_image_alt = (char *)strdup(template_service->icon_image_alt); - this_service->have_icon_image_alt = TRUE; - } - if(this_service->have_initial_state == FALSE && template_service->have_initial_state == TRUE) { - this_service->initial_state = template_service->initial_state; - this_service->have_initial_state = TRUE; - } - if(this_service->have_max_check_attempts == FALSE && template_service->have_max_check_attempts == TRUE) { - this_service->max_check_attempts = template_service->max_check_attempts; - this_service->have_max_check_attempts = TRUE; - } - if(this_service->have_check_interval == FALSE && template_service->have_check_interval == TRUE) { - this_service->check_interval = template_service->check_interval; - this_service->have_check_interval = TRUE; - } - if(this_service->have_retry_interval == FALSE && template_service->have_retry_interval == TRUE) { - this_service->retry_interval = template_service->retry_interval; - this_service->have_retry_interval = TRUE; - } - if(this_service->have_active_checks_enabled == FALSE && template_service->have_active_checks_enabled == TRUE) { - this_service->active_checks_enabled = template_service->active_checks_enabled; - this_service->have_active_checks_enabled = TRUE; - } - if(this_service->have_passive_checks_enabled == FALSE && template_service->have_passive_checks_enabled == TRUE) { - this_service->passive_checks_enabled = template_service->passive_checks_enabled; - this_service->have_passive_checks_enabled = TRUE; - } - if(this_service->have_parallelize_check == FALSE && template_service->have_parallelize_check == TRUE) { - this_service->parallelize_check = template_service->parallelize_check; - this_service->have_parallelize_check = TRUE; - } - if(this_service->have_is_volatile == FALSE && template_service->have_is_volatile == TRUE) { - this_service->is_volatile = template_service->is_volatile; - this_service->have_is_volatile = TRUE; - } - if(this_service->have_obsess_over_service == FALSE && template_service->have_obsess_over_service == TRUE) { - this_service->obsess_over_service = template_service->obsess_over_service; - this_service->have_obsess_over_service = TRUE; - } - if(this_service->have_event_handler_enabled == FALSE && template_service->have_event_handler_enabled == TRUE) { - this_service->event_handler_enabled = template_service->event_handler_enabled; - this_service->have_event_handler_enabled = TRUE; - } - if(this_service->have_check_freshness == FALSE && template_service->have_check_freshness == TRUE) { - this_service->check_freshness = template_service->check_freshness; - this_service->have_check_freshness = TRUE; - } - if(this_service->have_freshness_threshold == FALSE && template_service->have_freshness_threshold == TRUE) { - this_service->freshness_threshold = template_service->freshness_threshold; - this_service->have_freshness_threshold = TRUE; - } - if(this_service->have_low_flap_threshold == FALSE && template_service->have_low_flap_threshold == TRUE) { - this_service->low_flap_threshold = template_service->low_flap_threshold; - this_service->have_low_flap_threshold = TRUE; - } - if(this_service->have_high_flap_threshold == FALSE && template_service->have_high_flap_threshold == TRUE) { - this_service->high_flap_threshold = template_service->high_flap_threshold; - this_service->have_high_flap_threshold = TRUE; - } - if(this_service->have_flap_detection_enabled == FALSE && template_service->have_flap_detection_enabled == TRUE) { - this_service->flap_detection_enabled = template_service->flap_detection_enabled; - this_service->have_flap_detection_enabled = TRUE; - } - if(this_service->have_flap_detection_options == FALSE && template_service->have_flap_detection_options == TRUE) { - this_service->flap_detection_on_ok = template_service->flap_detection_on_ok; - this_service->flap_detection_on_unknown = template_service->flap_detection_on_unknown; - this_service->flap_detection_on_warning = template_service->flap_detection_on_warning; - this_service->flap_detection_on_critical = template_service->flap_detection_on_critical; - this_service->have_flap_detection_options = TRUE; - } - if(this_service->have_notification_options == FALSE && template_service->have_notification_options == TRUE) { - this_service->notify_on_unknown = template_service->notify_on_unknown; - this_service->notify_on_warning = template_service->notify_on_warning; - this_service->notify_on_critical = template_service->notify_on_critical; - this_service->notify_on_recovery = template_service->notify_on_recovery; - this_service->notify_on_flapping = template_service->notify_on_flapping; - this_service->notify_on_downtime = template_service->notify_on_downtime; - this_service->have_notification_options = TRUE; - } - if(this_service->have_notifications_enabled == FALSE && template_service->have_notifications_enabled == TRUE) { - this_service->notifications_enabled = template_service->notifications_enabled; - this_service->have_notifications_enabled = TRUE; - } - if(this_service->have_notification_interval == FALSE && template_service->have_notification_interval == TRUE) { - this_service->notification_interval = template_service->notification_interval; - this_service->have_notification_interval = TRUE; - } - if(this_service->have_first_notification_delay == FALSE && template_service->have_first_notification_delay == TRUE) { - this_service->first_notification_delay = template_service->first_notification_delay; - this_service->have_first_notification_delay = TRUE; - } - if(this_service->have_stalking_options == FALSE && template_service->have_stalking_options == TRUE) { - this_service->stalk_on_ok = template_service->stalk_on_ok; - this_service->stalk_on_unknown = template_service->stalk_on_unknown; - this_service->stalk_on_warning = template_service->stalk_on_warning; - this_service->stalk_on_critical = template_service->stalk_on_critical; - this_service->have_stalking_options = TRUE; - } - if(this_service->have_process_perf_data == FALSE && template_service->have_process_perf_data == TRUE) { - this_service->process_perf_data = template_service->process_perf_data; - this_service->have_process_perf_data = TRUE; - } - if(this_service->have_failure_prediction_enabled == FALSE && template_service->have_failure_prediction_enabled == TRUE) { - this_service->failure_prediction_enabled = template_service->failure_prediction_enabled; - this_service->have_failure_prediction_enabled = TRUE; - } - if(this_service->have_retain_status_information == FALSE && template_service->have_retain_status_information == TRUE) { - this_service->retain_status_information = template_service->retain_status_information; - this_service->have_retain_status_information = TRUE; - } - if(this_service->have_retain_nonstatus_information == FALSE && template_service->have_retain_nonstatus_information == TRUE) { - this_service->retain_nonstatus_information = template_service->retain_nonstatus_information; - this_service->have_retain_nonstatus_information = TRUE; } + xod_inherit_str(this_service, template_service, check_command); + + xod_inherit_str(this_service, template_service, check_period); + xod_inherit_str(this_service, template_service, event_handler); + xod_inherit_str(this_service, template_service, notification_period); + xod_inherit_str(this_service, template_service, notes); + xod_inherit_str(this_service, template_service, notes_url); + xod_inherit_str(this_service, template_service, action_url); + xod_inherit_str(this_service, template_service, icon_image); + xod_inherit_str(this_service, template_service, icon_image_alt); + + xod_inherit(this_service, template_service, initial_state); + xod_inherit(this_service, template_service, max_check_attempts); + xod_inherit(this_service, template_service, check_interval); + xod_inherit(this_service, template_service, retry_interval); + xod_inherit(this_service, template_service, active_checks_enabled); + xod_inherit(this_service, template_service, passive_checks_enabled); + xod_inherit(this_service, template_service, parallelize_check); + xod_inherit(this_service, template_service, is_volatile); + xod_inherit(this_service, template_service, obsess); + xod_inherit(this_service, template_service, event_handler_enabled); + xod_inherit(this_service, template_service, check_freshness); + xod_inherit(this_service, template_service, freshness_threshold); + xod_inherit(this_service, template_service, low_flap_threshold); + xod_inherit(this_service, template_service, high_flap_threshold); + xod_inherit(this_service, template_service, flap_detection_enabled); + xod_inherit(this_service, template_service, flap_detection_options); + xod_inherit(this_service, template_service, notification_options); + xod_inherit(this_service, template_service, notifications_enabled); + xod_inherit(this_service, template_service, notification_interval); + xod_inherit(this_service, template_service, first_notification_delay); + xod_inherit(this_service, template_service, stalking_options); + xod_inherit(this_service, template_service, process_perf_data); + xod_inherit(this_service, template_service, retain_status_information); + xod_inherit(this_service, template_service, retain_nonstatus_information); + xod_inherit(this_service, template_service, hourly_value); /* apply missing custom variables from template service... */ for(temp_customvariablesmember = template_service->custom_variables; temp_customvariablesmember != NULL; temp_customvariablesmember = temp_customvariablesmember->next) { @@ -7189,29 +5920,10 @@ int xodtemplate_resolve_hostdependency(xodtemplate_hostdependency *this_hostdepe xodtemplate_get_inherited_string(&template_hostdependency->have_hostgroup_name, &template_hostdependency->hostgroup_name, &this_hostdependency->have_hostgroup_name, &this_hostdependency->hostgroup_name); xodtemplate_get_inherited_string(&template_hostdependency->have_dependent_hostgroup_name, &template_hostdependency->dependent_hostgroup_name, &this_hostdependency->have_dependent_hostgroup_name, &this_hostdependency->dependent_hostgroup_name); - if(this_hostdependency->have_dependency_period == FALSE && template_hostdependency->have_dependency_period == TRUE) { - if(this_hostdependency->dependency_period == NULL && template_hostdependency->dependency_period != NULL) - this_hostdependency->dependency_period = (char *)strdup(template_hostdependency->dependency_period); - this_hostdependency->have_dependency_period = TRUE; - } - if(this_hostdependency->have_inherits_parent == FALSE && template_hostdependency->have_inherits_parent == TRUE) { - this_hostdependency->inherits_parent = template_hostdependency->inherits_parent; - this_hostdependency->have_inherits_parent = TRUE; - } - if(this_hostdependency->have_execution_dependency_options == FALSE && template_hostdependency->have_execution_dependency_options == TRUE) { - this_hostdependency->fail_execute_on_up = template_hostdependency->fail_execute_on_up; - this_hostdependency->fail_execute_on_down = template_hostdependency->fail_execute_on_down; - this_hostdependency->fail_execute_on_unreachable = template_hostdependency->fail_execute_on_unreachable; - this_hostdependency->fail_execute_on_pending = template_hostdependency->fail_execute_on_pending; - this_hostdependency->have_execution_dependency_options = TRUE; - } - if(this_hostdependency->have_notification_dependency_options == FALSE && template_hostdependency->have_notification_dependency_options == TRUE) { - this_hostdependency->fail_notify_on_up = template_hostdependency->fail_notify_on_up; - this_hostdependency->fail_notify_on_down = template_hostdependency->fail_notify_on_down; - this_hostdependency->fail_notify_on_unreachable = template_hostdependency->fail_notify_on_unreachable; - this_hostdependency->fail_notify_on_pending = template_hostdependency->fail_notify_on_pending; - this_hostdependency->have_notification_dependency_options = TRUE; - } + xod_inherit_str(this_hostdependency, template_hostdependency, dependency_period); + xod_inherit(this_hostdependency, template_hostdependency, inherits_parent); + xod_inherit(this_hostdependency, template_hostdependency, execution_failure_options); + xod_inherit(this_hostdependency, template_hostdependency, notification_failure_options); } my_free(template_names); @@ -7261,29 +5973,11 @@ int xodtemplate_resolve_hostescalation(xodtemplate_hostescalation *this_hostesca xodtemplate_get_inherited_string(&template_hostescalation->have_contact_groups, &template_hostescalation->contact_groups, &this_hostescalation->have_contact_groups, &this_hostescalation->contact_groups); xodtemplate_get_inherited_string(&template_hostescalation->have_contacts, &template_hostescalation->contacts, &this_hostescalation->have_contacts, &this_hostescalation->contacts); - if(this_hostescalation->have_escalation_period == FALSE && template_hostescalation->have_escalation_period == TRUE) { - if(this_hostescalation->escalation_period == NULL && template_hostescalation->escalation_period != NULL) - this_hostescalation->escalation_period = (char *)strdup(template_hostescalation->escalation_period); - this_hostescalation->have_escalation_period = TRUE; - } - if(this_hostescalation->have_first_notification == FALSE && template_hostescalation->have_first_notification == TRUE) { - this_hostescalation->first_notification = template_hostescalation->first_notification; - this_hostescalation->have_first_notification = TRUE; - } - if(this_hostescalation->have_last_notification == FALSE && template_hostescalation->have_last_notification == TRUE) { - this_hostescalation->last_notification = template_hostescalation->last_notification; - this_hostescalation->have_last_notification = TRUE; - } - if(this_hostescalation->have_notification_interval == FALSE && template_hostescalation->have_notification_interval == TRUE) { - this_hostescalation->notification_interval = template_hostescalation->notification_interval; - this_hostescalation->have_notification_interval = TRUE; - } - if(this_hostescalation->have_escalation_options == FALSE && template_hostescalation->have_escalation_options == TRUE) { - this_hostescalation->escalate_on_down = template_hostescalation->escalate_on_down; - this_hostescalation->escalate_on_unreachable = template_hostescalation->escalate_on_unreachable; - this_hostescalation->escalate_on_recovery = template_hostescalation->escalate_on_recovery; - this_hostescalation->have_escalation_options = TRUE; - } + xod_inherit_str(this_hostescalation, template_hostescalation, escalation_period); + xod_inherit(this_hostescalation, template_hostescalation, first_notification); + xod_inherit(this_hostescalation, template_hostescalation, last_notification); + xod_inherit(this_hostescalation, template_hostescalation, notification_interval); + xod_inherit(this_hostescalation, template_hostescalation, escalation_options); } my_free(template_names); @@ -7329,51 +6023,16 @@ int xodtemplate_resolve_hostextinfo(xodtemplate_hostextinfo *this_hostextinfo) { xodtemplate_resolve_hostextinfo(template_hostextinfo); /* apply missing properties from template hostextinfo... */ - if(this_hostextinfo->have_host_name == FALSE && template_hostextinfo->have_host_name == TRUE) { - if(this_hostextinfo->host_name == NULL && template_hostextinfo->host_name != NULL) - this_hostextinfo->host_name = (char *)strdup(template_hostextinfo->host_name); - this_hostextinfo->have_host_name = TRUE; - } - if(this_hostextinfo->have_hostgroup_name == FALSE && template_hostextinfo->have_hostgroup_name == TRUE) { - if(this_hostextinfo->hostgroup_name == NULL && template_hostextinfo->hostgroup_name != NULL) - this_hostextinfo->hostgroup_name = (char *)strdup(template_hostextinfo->hostgroup_name); - this_hostextinfo->have_hostgroup_name = TRUE; - } - if(this_hostextinfo->have_notes == FALSE && template_hostextinfo->have_notes == TRUE) { - if(this_hostextinfo->notes == NULL && template_hostextinfo->notes != NULL) - this_hostextinfo->notes = (char *)strdup(template_hostextinfo->notes); - this_hostextinfo->have_notes = TRUE; - } - if(this_hostextinfo->have_notes_url == FALSE && template_hostextinfo->have_notes_url == TRUE) { - if(this_hostextinfo->notes_url == NULL && template_hostextinfo->notes_url != NULL) - this_hostextinfo->notes_url = (char *)strdup(template_hostextinfo->notes_url); - this_hostextinfo->have_notes_url = TRUE; - } - if(this_hostextinfo->have_action_url == FALSE && template_hostextinfo->have_action_url == TRUE) { - if(this_hostextinfo->action_url == NULL && template_hostextinfo->action_url != NULL) - this_hostextinfo->action_url = (char *)strdup(template_hostextinfo->action_url); - this_hostextinfo->have_action_url = TRUE; - } - if(this_hostextinfo->have_icon_image == FALSE && template_hostextinfo->have_icon_image == TRUE) { - if(this_hostextinfo->icon_image == NULL && template_hostextinfo->icon_image != NULL) - this_hostextinfo->icon_image = (char *)strdup(template_hostextinfo->icon_image); - this_hostextinfo->have_icon_image = TRUE; - } - if(this_hostextinfo->have_icon_image_alt == FALSE && template_hostextinfo->have_icon_image_alt == TRUE) { - if(this_hostextinfo->icon_image_alt == NULL && template_hostextinfo->icon_image_alt != NULL) - this_hostextinfo->icon_image_alt = (char *)strdup(template_hostextinfo->icon_image_alt); - this_hostextinfo->have_icon_image_alt = TRUE; - } - if(this_hostextinfo->have_vrml_image == FALSE && template_hostextinfo->have_vrml_image == TRUE) { - if(this_hostextinfo->vrml_image == NULL && template_hostextinfo->vrml_image != NULL) - this_hostextinfo->vrml_image = (char *)strdup(template_hostextinfo->vrml_image); - this_hostextinfo->have_vrml_image = TRUE; - } - if(this_hostextinfo->have_statusmap_image == FALSE && template_hostextinfo->have_statusmap_image == TRUE) { - if(this_hostextinfo->statusmap_image == NULL && template_hostextinfo->statusmap_image != NULL) - this_hostextinfo->statusmap_image = (char *)strdup(template_hostextinfo->statusmap_image); - this_hostextinfo->have_statusmap_image = TRUE; - } + xod_inherit_str(this_hostextinfo, template_hostextinfo, host_name); + xod_inherit_str(this_hostextinfo, template_hostextinfo, hostgroup_name); + xod_inherit_str(this_hostextinfo, template_hostextinfo, notes); + xod_inherit_str(this_hostextinfo, template_hostextinfo, notes_url); + xod_inherit_str(this_hostextinfo, template_hostextinfo, action_url); + xod_inherit_str(this_hostextinfo, template_hostextinfo, icon_image); + xod_inherit_str(this_hostextinfo, template_hostextinfo, icon_image_alt); + xod_inherit_str(this_hostextinfo, template_hostextinfo, vrml_image); + xod_inherit_str(this_hostextinfo, template_hostextinfo, statusmap_image); + if(this_hostextinfo->have_2d_coords == FALSE && template_hostextinfo->have_2d_coords == TRUE) { this_hostextinfo->x_2d = template_hostextinfo->x_2d; this_hostextinfo->y_2d = template_hostextinfo->y_2d; @@ -7430,46 +6089,14 @@ int xodtemplate_resolve_serviceextinfo(xodtemplate_serviceextinfo *this_servicee xodtemplate_resolve_serviceextinfo(template_serviceextinfo); /* apply missing properties from template serviceextinfo... */ - if(this_serviceextinfo->have_host_name == FALSE && template_serviceextinfo->have_host_name == TRUE) { - if(this_serviceextinfo->host_name == NULL && template_serviceextinfo->host_name != NULL) - this_serviceextinfo->host_name = (char *)strdup(template_serviceextinfo->host_name); - this_serviceextinfo->have_host_name = TRUE; - } - if(this_serviceextinfo->have_hostgroup_name == FALSE && template_serviceextinfo->have_hostgroup_name == TRUE) { - if(this_serviceextinfo->hostgroup_name == NULL && template_serviceextinfo->hostgroup_name != NULL) - this_serviceextinfo->hostgroup_name = (char *)strdup(template_serviceextinfo->hostgroup_name); - this_serviceextinfo->have_hostgroup_name = TRUE; - } - if(this_serviceextinfo->have_service_description == FALSE && template_serviceextinfo->have_service_description == TRUE) { - if(this_serviceextinfo->service_description == NULL && template_serviceextinfo->service_description != NULL) - this_serviceextinfo->service_description = (char *)strdup(template_serviceextinfo->service_description); - this_serviceextinfo->have_service_description = TRUE; - } - if(this_serviceextinfo->have_notes == FALSE && template_serviceextinfo->have_notes == TRUE) { - if(this_serviceextinfo->notes == NULL && template_serviceextinfo->notes != NULL) - this_serviceextinfo->notes = (char *)strdup(template_serviceextinfo->notes); - this_serviceextinfo->have_notes = TRUE; - } - if(this_serviceextinfo->have_notes_url == FALSE && template_serviceextinfo->have_notes_url == TRUE) { - if(this_serviceextinfo->notes_url == NULL && template_serviceextinfo->notes_url != NULL) - this_serviceextinfo->notes_url = (char *)strdup(template_serviceextinfo->notes_url); - this_serviceextinfo->have_notes_url = TRUE; - } - if(this_serviceextinfo->have_action_url == FALSE && template_serviceextinfo->have_action_url == TRUE) { - if(this_serviceextinfo->action_url == NULL && template_serviceextinfo->action_url != NULL) - this_serviceextinfo->action_url = (char *)strdup(template_serviceextinfo->action_url); - this_serviceextinfo->have_action_url = TRUE; - } - if(this_serviceextinfo->have_icon_image == FALSE && template_serviceextinfo->have_icon_image == TRUE) { - if(this_serviceextinfo->icon_image == NULL && template_serviceextinfo->icon_image != NULL) - this_serviceextinfo->icon_image = (char *)strdup(template_serviceextinfo->icon_image); - this_serviceextinfo->have_icon_image = TRUE; - } - if(this_serviceextinfo->have_icon_image_alt == FALSE && template_serviceextinfo->have_icon_image_alt == TRUE) { - if(this_serviceextinfo->icon_image_alt == NULL && template_serviceextinfo->icon_image_alt != NULL) - this_serviceextinfo->icon_image_alt = (char *)strdup(template_serviceextinfo->icon_image_alt); - this_serviceextinfo->have_icon_image_alt = TRUE; - } + xod_inherit_str(this_serviceextinfo, template_serviceextinfo, host_name); + xod_inherit_str(this_serviceextinfo, template_serviceextinfo, hostgroup_name); + xod_inherit_str(this_serviceextinfo, template_serviceextinfo, service_description); + xod_inherit_str(this_serviceextinfo, template_serviceextinfo, notes); + xod_inherit_str(this_serviceextinfo, template_serviceextinfo, notes_url); + xod_inherit_str(this_serviceextinfo, template_serviceextinfo, action_url); + xod_inherit_str(this_serviceextinfo, template_serviceextinfo, icon_image); + xod_inherit_str(this_serviceextinfo, template_serviceextinfo, icon_image_alt); } my_free(template_names); @@ -7477,29 +6104,161 @@ int xodtemplate_resolve_serviceextinfo(xodtemplate_serviceextinfo *this_servicee return OK; } + + #endif - - /******************************************************************/ /*************** OBJECT RECOMBOBULATION FUNCTIONS *****************/ /******************************************************************/ -#ifdef NSCORE +/* + * note: The cast to xodtemplate_host works for all objects because 'id' + * is the first item of host, service and contact structs, and C + * guarantees that the first member is always the same as the one listed + * in the struct definition. + */ +static int _xodtemplate_add_group_member(objectlist **list, bitmap *in, bitmap *reject, void *obj) { + xodtemplate_host *h = (xodtemplate_host *)obj; + + if(!list || !obj) + return ERROR; + + if(bitmap_isset(in, h->id) || bitmap_isset(reject, h->id)) + return OK; + bitmap_set(in, h->id); + return prepend_object_to_objectlist(list, obj); + } +#define xodtemplate_add_group_member(g, m) \ + _xodtemplate_add_group_member(&g->member_list, g->member_map, g->reject_map, m) +#define xodtemplate_add_servicegroup_member xodtemplate_add_group_member +#define xodtemplate_add_contactgroup_member xodtemplate_add_group_member +#define xodtemplate_add_hostgroup_member xodtemplate_add_group_member /* recombobulates contactgroup definitions */ +static int xodtemplate_recombobulate_contactgroup_subgroups(xodtemplate_contactgroup *temp_contactgroup) { + objectlist *mlist, *glist; + + if(temp_contactgroup == NULL) + return ERROR; + + /* if this one's already handled somehow, we return early */ + if(temp_contactgroup->loop_status != XOD_NEW) + return temp_contactgroup->loop_status; + + /* mark it as seen */ + temp_contactgroup->loop_status = XOD_SEEN; + + /* resolve included groups' members and add them to ours */ + for(glist = temp_contactgroup->group_list; glist; glist = glist->next) { + int result; + xodtemplate_contactgroup *inc = (xodtemplate_contactgroup *)glist->object_ptr; + result = xodtemplate_recombobulate_contactgroup_subgroups(inc); + if(result != XOD_OK) { + if(result == ERROR) + return ERROR; + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Contactgroups '%s' and '%s' are part of a contactgroup_members include loop\n", temp_contactgroup->contactgroup_name, inc->contactgroup_name); + inc->loop_status = XOD_LOOPY; + temp_contactgroup->loop_status = XOD_LOOPY; + break; + } + + for(mlist = inc->member_list; mlist; mlist = mlist->next) { + xodtemplate_contact *c = (xodtemplate_contact *)mlist->object_ptr; + if(xodtemplate_add_contactgroup_member(temp_contactgroup, c) != OK) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Failed to add '%s' as a subgroup member contact of contactgroup '%s' from contactgroup '%s'\n", + c->contact_name, temp_contactgroup->contactgroup_name, inc->contactgroup_name); + return ERROR; + } + } + } + + if(temp_contactgroup->loop_status == XOD_SEEN) + temp_contactgroup->loop_status = XOD_OK; + + return temp_contactgroup->loop_status; + } + + + int xodtemplate_recombobulate_contactgroups(void) { xodtemplate_contact *temp_contact = NULL; xodtemplate_contactgroup *temp_contactgroup = NULL; - xodtemplate_memberlist *temp_memberlist = NULL; - xodtemplate_memberlist *this_memberlist = NULL; char *contactgroup_names = NULL; char *temp_ptr = NULL; - char *new_members = NULL; - /* This should happen before we expand contactgroup members, to avoid duplicate contact memberships 01/07/2006 EG */ - /* process all contacts that have contactgroup directives */ + /* expand members of all contactgroups - this could be done in xodtemplate_register_contactgroup(), but we can save the CGIs some work if we do it here */ + for(temp_contactgroup = xodtemplate_contactgroup_list; temp_contactgroup; temp_contactgroup = temp_contactgroup->next) { + objectlist *next, *list, *accept = NULL; + + /* + * If the contactgroup has no accept or reject list and no group + * members we don't need the bitmaps for it. bitmap_isset() + * will return 0 when passed a NULL map, so we can safely use + * that to add any items from the object list later + */ + if(temp_contactgroup->members == NULL && temp_contactgroup->contactgroup_members == NULL) + continue; + + if(!(temp_contactgroup->member_map = bitmap_create(xodcount.contacts))) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not create contactgroup bitmap\n"); + return ERROR; + } + + if(temp_contactgroup->contactgroup_members) { + xodtemplate_contactgroup *cg; + char *ptr, *next_ptr; + + for(next_ptr = ptr = temp_contactgroup->contactgroup_members; next_ptr; ptr = next_ptr + 1) { + next_ptr = strchr(ptr, ','); + if(next_ptr) + *next_ptr = 0; + while(*ptr == ' ' || *ptr == '\t') + ptr++; + strip(ptr); + if(!(cg = xodtemplate_find_real_contactgroup(ptr))) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not find member group '%s' specified in contactgroup '%s' (config file '%s', starting on line %d)\n", ptr, temp_contactgroup->contactgroup_name, xodtemplate_config_file_name(temp_contactgroup->_config_file), temp_contactgroup->_start_line); + return ERROR; + } + add_object_to_objectlist(&temp_contactgroup->group_list, cg); + } + my_free(temp_contactgroup->contactgroup_members); + } + + /* move on if we have no members */ + if(temp_contactgroup->members == NULL) + continue; + + /* we might need this */ + if(!use_precached_objects && !(temp_contactgroup->reject_map = bitmap_create(xodcount.contacts))) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not create reject map for contactgroup '%s'", temp_contactgroup->contactgroup_name); + return ERROR; + } + + /* get list of contacts in the contactgroup */ + if(xodtemplate_expand_contacts(&accept, temp_contactgroup->reject_map, temp_contactgroup->members, temp_contactgroup->_config_file, temp_contactgroup->_start_line) != OK) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Failed to expand contacts for contactgroup '%s' (config file '%s', starting at line %d)\n", + temp_contactgroup->contactgroup_name, + xodtemplate_config_file_name(temp_contactgroup->_config_file), + temp_contactgroup->_start_line); + return ERROR; + } + + my_free(temp_contactgroup->members); + for(list = accept; list; list = next) { + temp_contact = (xodtemplate_contact *)list->object_ptr; + next = list->next; + free(list); + xodtemplate_add_contactgroup_member(temp_contactgroup, temp_contact); + } + } + + /* if we're using precached objects we can bail out now */ + if(use_precached_objects) + return OK; + + /* process all contacts with contactgroups directives */ for(temp_contact = xodtemplate_contact_list; temp_contact != NULL; temp_contact = temp_contact->next) { /* skip contacts without contactgroup directives or contact names */ @@ -7507,8 +6266,11 @@ int xodtemplate_recombobulate_contactgroups(void) { continue; /* preprocess the contactgroup list, to change "grp1,grp2,grp3,!grp2" into "grp1,grp3" */ - if((contactgroup_names = xodtemplate_process_contactgroup_names(temp_contact->contact_groups, temp_contact->_config_file, temp_contact->_start_line)) == NULL) + if((contactgroup_names = xodtemplate_process_contactgroup_names(temp_contact->contact_groups, temp_contact->_config_file, temp_contact->_start_line)) == NULL) { + logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Failed to process contactgroups for contact '%s' (config file '%s', starting at line %d)\n", + temp_contact->contact_name, xodtemplate_config_file_name(temp_contact->_config_file), temp_contact->_start_line); return ERROR; + } /* process the list of contactgroups */ for(temp_ptr = strtok(contactgroup_names, ","); temp_ptr; temp_ptr = strtok(NULL, ",")) { @@ -7524,164 +6286,157 @@ int xodtemplate_recombobulate_contactgroups(void) { return ERROR; } - /* add this contact to the contactgroup members directive */ - if(temp_contactgroup->members == NULL) - temp_contactgroup->members = (char *)strdup(temp_contact->contact_name); - else { - new_members = (char *)realloc(temp_contactgroup->members, strlen(temp_contactgroup->members) + strlen(temp_contact->contact_name) + 2); - if(new_members != NULL) { - temp_contactgroup->members = new_members; - strcat(temp_contactgroup->members, ","); - strcat(temp_contactgroup->members, temp_contact->contact_name); - } + if(!temp_contactgroup->member_map && !(temp_contactgroup->member_map = bitmap_create(xodcount.contacts))) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Failed to create member map for contactgroup '%s'\n", + temp_contactgroup->contactgroup_name); + return ERROR; } + /* add this contact to the contactgroup members directive */ + xodtemplate_add_contactgroup_member(temp_contactgroup, temp_contact); } /* free memory */ my_free(contactgroup_names); } - /* expand subgroup membership recursively */ - for(temp_contactgroup = xodtemplate_contactgroup_list; temp_contactgroup; temp_contactgroup = temp_contactgroup->next) - xodtemplate_recombobulate_contactgroup_subgroups(temp_contactgroup, NULL); - - - /* expand members of all contactgroups - this could be done in xodtemplate_register_contactgroup(), but we can save the CGIs some work if we do it here */ for(temp_contactgroup = xodtemplate_contactgroup_list; temp_contactgroup; temp_contactgroup = temp_contactgroup->next) { - - if(temp_contactgroup->members == NULL) - continue; - - /* get list of contacts in the contactgroup */ - temp_memberlist = xodtemplate_expand_contactgroups_and_contacts(temp_contactgroup->contactgroup_members, temp_contactgroup->members, temp_contactgroup->_config_file, temp_contactgroup->_start_line); - - /* add all members to the contact group */ - if(temp_memberlist == NULL) { - logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not expand member contacts specified in contactgroup (config file '%s', starting on line %d)\n", xodtemplate_config_file_name(temp_contactgroup->_config_file), temp_contactgroup->_start_line); + if(xodtemplate_recombobulate_contactgroup_subgroups(temp_contactgroup) != XOD_OK) return ERROR; - } - my_free(temp_contactgroup->members); - for(this_memberlist = temp_memberlist; this_memberlist; this_memberlist = this_memberlist->next) { - - /* add this contact to the contactgroup members directive */ - if(temp_contactgroup->members == NULL) - temp_contactgroup->members = (char *)strdup(this_memberlist->name1); - else { - new_members = (char *)realloc(temp_contactgroup->members, strlen(temp_contactgroup->members) + strlen(this_memberlist->name1) + 2); - if(new_members != NULL) { - temp_contactgroup->members = new_members; - strcat(temp_contactgroup->members, ","); - strcat(temp_contactgroup->members, this_memberlist->name1); - } - } - } - xodtemplate_free_memberlist(&temp_memberlist); - } + /* rejects are no longer necessary */ + bitmap_destroy(temp_contactgroup->reject_map); + /* make sure we don't recursively add subgroup members again */ + free_objectlist(&temp_contactgroup->group_list); + } return OK; } -int xodtemplate_recombobulate_contactgroup_subgroups(xodtemplate_contactgroup *temp_contactgroup, char **members) { - xodtemplate_contactgroup *sub_group = NULL; - char *orig_cgmembers = NULL; - char *cgmembers = NULL; - char *newmembers = NULL; - char *buf = NULL; - char *ptr = NULL; +static int xodtemplate_recombobulate_hostgroup_subgroups(xodtemplate_hostgroup *temp_hostgroup) { + objectlist *mlist, *glist; - if(temp_contactgroup == NULL) + if(temp_hostgroup == NULL) return ERROR; - /* resolve subgroup memberships first */ - if(temp_contactgroup->contactgroup_members != NULL) { + /* if this one's already handled somehow, we return early */ + if(temp_hostgroup->loop_status != XOD_NEW) + return temp_hostgroup->loop_status; - /* save members, null pointer so we don't recurse into infinite hell */ - orig_cgmembers = temp_contactgroup->contactgroup_members; - temp_contactgroup->contactgroup_members = NULL; + /* mark this one as seen */ + temp_hostgroup->loop_status = XOD_SEEN; - /* make new working copy of members */ - cgmembers = (char *)strdup(orig_cgmembers); - - ptr = cgmembers; - while((buf = ptr) != NULL) { - - /* get next member for next run*/ - ptr = strchr(ptr, ','); - if(ptr) { - ptr[0] = '\x0'; - ptr++; - } - - strip(buf); - - /* find subgroup and recurse */ - if((sub_group = xodtemplate_find_real_contactgroup(buf)) == NULL) { - logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not find member group '%s' specified in contactgroup (config file '%s', starting on line %d)\n", buf, xodtemplate_config_file_name(temp_contactgroup->_config_file), temp_contactgroup->_start_line); + /* resolve included groups' members and add them to ours */ + for(glist = temp_hostgroup->group_list; glist; glist = glist->next) { + int result; + xodtemplate_hostgroup *inc = (xodtemplate_hostgroup *)glist->object_ptr; + result = xodtemplate_recombobulate_hostgroup_subgroups(inc); + if(result != XOD_OK) { + if(result == ERROR) + return ERROR; + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Hostgroups '%s' and '%s' part of a hostgroup_members include loop\n", temp_hostgroup->hostgroup_name, inc->hostgroup_name); + inc->loop_status = XOD_LOOPY; + temp_hostgroup->loop_status = XOD_LOOPY; + break; + } + for(mlist = inc->member_list; mlist; mlist = mlist->next) { + xodtemplate_host *h = (xodtemplate_host *)mlist->object_ptr; + if (xodtemplate_add_hostgroup_member(temp_hostgroup, mlist->object_ptr) != OK) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Failed to add '%s' as a subgroup member host of hostgroup '%s' from hostgroup '%s'\n", + h->host_name, temp_hostgroup->hostgroup_name, inc->hostgroup_name); return ERROR; } - xodtemplate_recombobulate_contactgroup_subgroups(sub_group, &newmembers); - - /* add new (sub) members */ - if(newmembers != NULL) { - if(temp_contactgroup->members == NULL) - temp_contactgroup->members = (char *)strdup(newmembers); - else if((temp_contactgroup->members = realloc(temp_contactgroup->members, strlen(temp_contactgroup->members) + strlen(newmembers) + 2))) { - strcat(temp_contactgroup->members, ","); - strcat(temp_contactgroup->members, newmembers); - } - } } - - /* free memory */ - my_free(cgmembers); - - /* restore group members */ - temp_contactgroup->contactgroup_members = orig_cgmembers; } - /* return contact members */ - if(members != NULL) - *members = temp_contactgroup->members; + if(temp_hostgroup->loop_status == XOD_SEEN) + temp_hostgroup->loop_status = XOD_OK; - return OK; + return temp_hostgroup->loop_status; } -/* NOTE: this was originally implemented in the late alpha cycle of - * 3.0 development, but was removed in 3.0b2, as flattening - * contactgroups into a list of contacts makes it impossible for - * NDOUtils to create a reverse mapping */ -/* recombobulates contacts in various object definitions */ -int xodtemplate_recombobulate_object_contacts(void) { - return OK; - } - - /* recombobulates hostgroup definitions */ int xodtemplate_recombobulate_hostgroups(void) { xodtemplate_host *temp_host = NULL; xodtemplate_hostgroup *temp_hostgroup = NULL; - xodtemplate_memberlist *temp_memberlist = NULL; - xodtemplate_memberlist *this_memberlist = NULL; char *hostgroup_names = NULL; - char *temp_ptr = NULL; - char *new_members = NULL; + char *ptr, *next_ptr, *temp_ptr = NULL; -#ifdef DEBUG - printf("** PRE-EXPANSION 1\n"); + /* expand members of all hostgroups - this could be done in xodtemplate_register_hostgroup(), but we can save the CGIs some work if we do it here */ for(temp_hostgroup = xodtemplate_hostgroup_list; temp_hostgroup; temp_hostgroup = temp_hostgroup->next) { - printf("HOSTGROUP [%s]\n", temp_hostgroup->hostgroup_name); - printf("H MEMBERS: %s\n", temp_hostgroup->members); - printf("G MEMBERS: %s\n", temp_hostgroup->hostgroup_members); - printf("\n"); - } -#endif + objectlist *next, *list, *accept = NULL; + + /* + * if the hostgroup has no accept or reject list and no group + * members we don't need the bitmaps for it. bitmap_isset() + * will return 0 when passed a NULL map, so we can safely use + * that to add any items from the object list later. + */ + if(temp_hostgroup->members == NULL && temp_hostgroup->hostgroup_members == NULL) + continue; + + /* we'll need the member_map */ + if (!(temp_hostgroup->member_map = bitmap_create(xodcount.hosts))) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not create member map for hostgroup '%s'\n", temp_hostgroup->hostgroup_name); + return ERROR; + } + + /* resolve groups into a group-list */ + for(next_ptr = ptr = temp_hostgroup->hostgroup_members; next_ptr; ptr = next_ptr + 1) { + xodtemplate_hostgroup *hg; + next_ptr = strchr(ptr, ','); + if(next_ptr) + *next_ptr = 0; + while(*ptr == ' ' || *ptr == '\t') + ptr++; + + strip(ptr); + + if (!(hg = xodtemplate_find_real_hostgroup(ptr))) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not find member group '%s' specified in hostgroup '%s' (config file '%s', starting on line %d)\n", ptr, temp_hostgroup->hostgroup_name, xodtemplate_config_file_name(temp_hostgroup->_config_file), temp_hostgroup->_start_line); + return ERROR; + } + add_object_to_objectlist(&temp_hostgroup->group_list, hg); + } + + /* move on if we have no members */ + if(temp_hostgroup->members == NULL) + continue; + + /* we might need this */ + if(!use_precached_objects && !(temp_hostgroup->reject_map = bitmap_create(xodcount.hosts))) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not create reject map for hostgroup '%s'\n", temp_hostgroup->hostgroup_name); + return ERROR; + } + + /* get list of hosts in the hostgroup */ + if (xodtemplate_expand_hosts(&accept, temp_hostgroup->reject_map, temp_hostgroup->members, temp_hostgroup->_config_file, temp_hostgroup->_start_line) == ERROR) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not expand members specified in hostgroup (config file '%s', starting on line %d)\n", xodtemplate_config_file_name(temp_hostgroup->_config_file), temp_hostgroup->_start_line); + return ERROR; + } + + if (!accept && !bitmap_count_set_bits(temp_hostgroup->reject_map)) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not expand members specified in hostgroup (config file '%s', starting on line %d)\n", xodtemplate_config_file_name(temp_hostgroup->_config_file), temp_hostgroup->_start_line); + return ERROR; + } + + my_free(temp_hostgroup->members); + + for (list = accept; list; list = next) { + temp_host = (xodtemplate_host *)list->object_ptr; + next = list->next; + free(list); + xodtemplate_add_hostgroup_member(temp_hostgroup, temp_host); + } + } + + /* if we're using precached objects we can bail out now */ + if(use_precached_objects) + return OK; - /* This should happen before we expand hostgroup members, to avoid duplicate host memberships 01/07/2006 EG */ /* process all hosts that have hostgroup directives */ for(temp_host = xodtemplate_host_list; temp_host != NULL; temp_host = temp_host->next) { @@ -7695,8 +6450,11 @@ int xodtemplate_recombobulate_hostgroups(void) { /* preprocess the hostgroup list, to change "grp1,grp2,grp3,!grp2" into "grp1,grp3" */ /* 10/18/07 EG an empty return value means an error occured */ - if((hostgroup_names = xodtemplate_process_hostgroup_names(temp_host->host_groups, temp_host->_config_file, temp_host->_start_line)) == NULL) + if((hostgroup_names = xodtemplate_process_hostgroup_names(temp_host->host_groups, temp_host->_config_file, temp_host->_start_line)) == NULL) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Failed to process hostgroup names for host '%s' (config file '%s', starting at line %d)\n", + temp_host->host_name, xodtemplate_config_file_name(temp_host->_config_file), temp_host->_start_line); return ERROR; + } /* process the list of hostgroups */ for(temp_ptr = strtok(hostgroup_names, ","); temp_ptr; temp_ptr = strtok(NULL, ",")) { @@ -7711,174 +6469,156 @@ int xodtemplate_recombobulate_hostgroups(void) { my_free(hostgroup_names); return ERROR; } - - /* add this list to the hostgroup members directive */ - if(temp_hostgroup->members == NULL) - temp_hostgroup->members = (char *)strdup(temp_host->host_name); - else { - new_members = (char *)realloc(temp_hostgroup->members, strlen(temp_hostgroup->members) + strlen(temp_host->host_name) + 2); - if(new_members != NULL) { - temp_hostgroup->members = new_members; - strcat(temp_hostgroup->members, ","); - strcat(temp_hostgroup->members, temp_host->host_name); - } + if(!temp_hostgroup->member_map && !(temp_hostgroup->member_map = bitmap_create(xodcount.hosts))) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Failed to create bitmap to join host '%s' to group '%s'\n", + temp_host->host_name, temp_hostgroup->hostgroup_name); + return ERROR; } + + /* add ourselves to the hostgroup member list */ + xodtemplate_add_hostgroup_member(temp_hostgroup, temp_host); } /* free memory */ my_free(hostgroup_names); } -#ifdef DEBUG - printf("** POST-EXPANSION 1\n"); - for(temp_hostgroup = xodtemplate_hostgroup_list; temp_hostgroup; temp_hostgroup = temp_hostgroup->next) { - printf("HOSTGROUP [%s]\n", temp_hostgroup->hostgroup_name); - printf("H MEMBERS: %s\n", temp_hostgroup->members); - printf("G MEMBERS: %s\n", temp_hostgroup->hostgroup_members); - printf("\n"); - } -#endif - /* expand subgroup membership recursively */ - for(temp_hostgroup = xodtemplate_hostgroup_list; temp_hostgroup; temp_hostgroup = temp_hostgroup->next) - xodtemplate_recombobulate_hostgroup_subgroups(temp_hostgroup, NULL); - - /* expand members of all hostgroups - this could be done in xodtemplate_register_hostgroup(), but we can save the CGIs some work if we do it here */ for(temp_hostgroup = xodtemplate_hostgroup_list; temp_hostgroup; temp_hostgroup = temp_hostgroup->next) { - - if(temp_hostgroup->members == NULL && temp_hostgroup->hostgroup_members == NULL) - continue; - - /* skip hostgroups that shouldn't be registered */ - if(temp_hostgroup->register_object == FALSE) - continue; - - /* get list of hosts in the hostgroup */ - temp_memberlist = xodtemplate_expand_hostgroups_and_hosts(NULL, temp_hostgroup->members, temp_hostgroup->_config_file, temp_hostgroup->_start_line); - - /* add all members to the host group */ - if(temp_memberlist == NULL) { - logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not expand members specified in hostgroup (config file '%s', starting on line %d)\n", xodtemplate_config_file_name(temp_hostgroup->_config_file), temp_hostgroup->_start_line); + if(xodtemplate_recombobulate_hostgroup_subgroups(temp_hostgroup) != XOD_OK) { return ERROR; } - my_free(temp_hostgroup->members); - for(this_memberlist = temp_memberlist; this_memberlist; this_memberlist = this_memberlist->next) { - - /* add this host to the hostgroup members directive */ - if(temp_hostgroup->members == NULL) - temp_hostgroup->members = (char *)strdup(this_memberlist->name1); - else { - new_members = (char *)realloc(temp_hostgroup->members, strlen(temp_hostgroup->members) + strlen(this_memberlist->name1) + 2); - if(new_members != NULL) { - temp_hostgroup->members = new_members; - strcat(temp_hostgroup->members, ","); - strcat(temp_hostgroup->members, this_memberlist->name1); - } - } - } - xodtemplate_free_memberlist(&temp_memberlist); + /* rejects are no longer necessary */ + bitmap_destroy(temp_hostgroup->reject_map); + /* make sure we don't recursively add subgroup members again */ + free_objectlist(&temp_hostgroup->group_list); } -#ifdef DEBUG - printf("** POST-EXPANSION 2\n"); - for(temp_hostgroup = xodtemplate_hostgroup_list; temp_hostgroup; temp_hostgroup = temp_hostgroup->next) { - printf("HOSTGROUP [%s]\n", temp_hostgroup->hostgroup_name); - printf("H MEMBERS: %s\n", temp_hostgroup->members); - printf("G MEMBERS: %s\n", temp_hostgroup->hostgroup_members); - printf("\n"); - } -#endif - return OK; } +static int xodtemplate_recombobulate_servicegroup_subgroups(xodtemplate_servicegroup *temp_servicegroup) { + objectlist *mlist, *glist; -int xodtemplate_recombobulate_hostgroup_subgroups(xodtemplate_hostgroup *temp_hostgroup, char **members) { - xodtemplate_hostgroup *sub_group = NULL; - char *orig_hgmembers = NULL; - char *hgmembers = NULL; - char *newmembers = NULL; - char *buf = NULL; - char *ptr = NULL; - - if(temp_hostgroup == NULL) + if(temp_servicegroup == NULL) return ERROR; - /* resolve subgroup memberships first */ - if(temp_hostgroup->hostgroup_members != NULL) { + if(temp_servicegroup->loop_status != XOD_NEW) + return temp_servicegroup->loop_status; - /* save members, null pointer so we don't recurse into infinite hell */ - orig_hgmembers = temp_hostgroup->hostgroup_members; - temp_hostgroup->hostgroup_members = NULL; + /* mark this as seen */ + temp_servicegroup->loop_status = XOD_SEEN; - /* make new working copy of members */ - hgmembers = (char *)strdup(orig_hgmembers); + for(glist = temp_servicegroup->group_list; glist; glist = glist->next) { + int result; + xodtemplate_servicegroup *inc = (xodtemplate_servicegroup *)glist->object_ptr; - ptr = hgmembers; - while((buf = ptr) != NULL) { - - /* get next member for next run*/ - ptr = strchr(ptr, ','); - if(ptr) { - ptr[0] = '\x0'; - ptr++; - } - - strip(buf); - - /* find subgroup and recurse */ - if((sub_group = xodtemplate_find_real_hostgroup(buf)) == NULL) { - logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not find member group '%s' specified in hostgroup (config file '%s', starting on line %d)\n", buf, xodtemplate_config_file_name(temp_hostgroup->_config_file), temp_hostgroup->_start_line); + result = xodtemplate_recombobulate_servicegroup_subgroups(inc); + if(result != XOD_OK) { + if(result == ERROR) + return ERROR; + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Servicegroups '%s' and '%s' are part of a servicegroup_members include loop\n", + temp_servicegroup->servicegroup_name, inc->servicegroup_name); + inc->loop_status = XOD_LOOPY; + temp_servicegroup->loop_status = XOD_LOOPY; + break; + } + for(mlist = inc->member_list; mlist; mlist = mlist->next) { + xodtemplate_service *s = (xodtemplate_service *)mlist->object_ptr; + if(xodtemplate_add_servicegroup_member(temp_servicegroup, s) != OK) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Failed to add service '%s' on host '%s' as a subgroup member of servicegroup '%s' from servicegroup '%s'\n", + s->host_name, s->service_description, temp_servicegroup->servicegroup_name, inc->servicegroup_name); return ERROR; } - xodtemplate_recombobulate_hostgroup_subgroups(sub_group, &newmembers); - - /* add new (sub) members */ - if(newmembers != NULL) { - if(temp_hostgroup->members == NULL) - temp_hostgroup->members = (char *)strdup(newmembers); - else if((temp_hostgroup->members = realloc(temp_hostgroup->members, strlen(temp_hostgroup->members) + strlen(newmembers) + 2))) { - strcat(temp_hostgroup->members, ","); - strcat(temp_hostgroup->members, newmembers); - } - } } - - /* free memory */ - my_free(hgmembers); - - /* restore group members */ - temp_hostgroup->hostgroup_members = orig_hgmembers; } - /* return host members */ - if(members != NULL) - *members = temp_hostgroup->members; + if(temp_servicegroup->loop_status == XOD_SEEN) + temp_servicegroup->loop_status = XOD_OK; - return OK; + return temp_servicegroup->loop_status; } - - /* recombobulates servicegroup definitions */ /***** THIS NEEDS TO BE CALLED AFTER OBJECTS (SERVICES) ARE RESOLVED AND DUPLICATED *****/ int xodtemplate_recombobulate_servicegroups(void) { xodtemplate_service *temp_service = NULL; xodtemplate_servicegroup *temp_servicegroup = NULL; - xodtemplate_memberlist *temp_memberlist = NULL; - xodtemplate_memberlist *this_memberlist = NULL; char *servicegroup_names = NULL; - char *member_names = NULL; - char *host_name = NULL; - char *service_description = NULL; - char *temp_ptr = NULL; - char *temp_ptr2 = NULL; - char *new_members = NULL; + char *temp_ptr; - /* This should happen before we expand servicegroup members, to avoid duplicate service memberships 01/07/2006 EG */ - /* process all services that have servicegroup directives */ + /* + * expand servicegroup members. We need this to get the rejected ones + * before we add members from the servicelist. + */ + for(temp_servicegroup = xodtemplate_servicegroup_list; temp_servicegroup; temp_servicegroup = temp_servicegroup->next) { + objectlist *list, *next, *accept = NULL; + + if(temp_servicegroup->members == NULL && temp_servicegroup->servicegroup_members == NULL) + continue; + + /* we'll need the member map */ + if(!(temp_servicegroup->member_map = bitmap_create(xodcount.services))) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not create member map for servicegroup '%s'\n", temp_servicegroup->servicegroup_name); + return ERROR; + } + + /* resolve groups into a group-list */ + if(temp_servicegroup->servicegroup_members) { + xodtemplate_servicegroup *sg; + char *ptr, *next_ptr = NULL; + for(ptr = temp_servicegroup->servicegroup_members; ptr; ptr = next_ptr + 1) { + next_ptr = strchr(ptr, ','); + if(next_ptr) + *next_ptr = 0; + strip(ptr); + if(!(sg = xodtemplate_find_real_servicegroup(ptr))) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not find member group '%s' specified in servicegroup '%s' (config file '%s', starting on line %d)\n", ptr, temp_servicegroup->servicegroup_name, xodtemplate_config_file_name(temp_servicegroup->_config_file), temp_servicegroup->_start_line); + return ERROR; + + } + add_object_to_objectlist(&temp_servicegroup->group_list, sg); + if(!next_ptr) + break; + } + my_free(temp_servicegroup->servicegroup_members); + } + + /* move on if we have no members */ + if(temp_servicegroup->members == NULL) + continue; + + /* we might need this */ + if(!use_precached_objects && !(temp_servicegroup->reject_map = bitmap_create(xodcount.services))) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not create reject map for hostgroup '%s'\n", temp_servicegroup->servicegroup_name); + return ERROR; + } + + /* get list of service members in the servicegroup */ + xodtemplate_expand_services(&accept, temp_servicegroup->reject_map, NULL, temp_servicegroup->members, temp_servicegroup->_config_file, temp_servicegroup->_start_line); + if(!accept && !bitmap_count_set_bits(temp_servicegroup->reject_map)) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not expand members specified in servicegroup '%s' (config file '%s', starting at line %d)\n", temp_servicegroup->servicegroup_name, xodtemplate_config_file_name(temp_servicegroup->_config_file), temp_servicegroup->_start_line); + return ERROR; + } + + /* we don't need this anymore */ + my_free(temp_servicegroup->members); + + for(list = accept; list; list = next) { + xodtemplate_service *s = (xodtemplate_service *)list->object_ptr; + next = list->next; + free(list); + xodtemplate_add_servicegroup_member(temp_servicegroup, s); + } + } + + /* if we're using precached objects we can bail out now */ + if(use_precached_objects == TRUE) + return OK; + + /* Add services from 'servicegroups' directive */ for(temp_service = xodtemplate_service_list; temp_service != NULL; temp_service = temp_service->next) { /* skip services without servicegroup directives or service names */ @@ -7890,9 +6630,12 @@ int xodtemplate_recombobulate_servicegroups(void) { continue; /* preprocess the servicegroup list, to change "grp1,grp2,grp3,!grp2" into "grp1,grp3" */ - /* 10/19/07 EG an empry return value means an error occured */ - if((servicegroup_names = xodtemplate_process_servicegroup_names(temp_service->service_groups, temp_service->_config_file, temp_service->_start_line)) == NULL) + /* 10/19/07 EG an empty return value means an error occured */ + if((servicegroup_names = xodtemplate_process_servicegroup_names(temp_service->service_groups, temp_service->_config_file, temp_service->_start_line)) == NULL) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Failed to process servicegroup names for service '%s' on host '%s' (config file '%s', starting at line %d)\n", + temp_service->service_description, temp_service->host_name, xodtemplate_config_file_name(temp_service->_config_file), temp_service->_start_line); return ERROR; + } /* process the list of servicegroups */ for(temp_ptr = strtok(servicegroup_names, ","); temp_ptr; temp_ptr = strtok(NULL, ",")) { @@ -7908,120 +6651,27 @@ int xodtemplate_recombobulate_servicegroups(void) { return ERROR; } - /* add this list to the servicegroup members directive */ - if(temp_servicegroup->members == NULL) { - temp_servicegroup->members = (char *)malloc(strlen(temp_service->host_name) + strlen(temp_service->service_description) + 2); - if(temp_servicegroup->members != NULL) { - strcpy(temp_servicegroup->members, temp_service->host_name); - strcat(temp_servicegroup->members, ","); - strcat(temp_servicegroup->members, temp_service->service_description); - } + if(!temp_servicegroup->member_map && !(temp_servicegroup->member_map = bitmap_create(xodcount.services))) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Failed to create member map for service group %s\n", temp_servicegroup->servicegroup_name); + return ERROR; } - else { - new_members = (char *)realloc(temp_servicegroup->members, strlen(temp_servicegroup->members) + strlen(temp_service->host_name) + strlen(temp_service->service_description) + 3); - if(new_members != NULL) { - temp_servicegroup->members = new_members; - strcat(temp_servicegroup->members, ","); - strcat(temp_servicegroup->members, temp_service->host_name); - strcat(temp_servicegroup->members, ","); - strcat(temp_servicegroup->members, temp_service->service_description); - } - } - } + /* add ourselves as members to the group */ + xodtemplate_add_servicegroup_member(temp_servicegroup, temp_service); + } /* free servicegroup names */ my_free(servicegroup_names); } - /* expand subgroup membership recursively */ - for(temp_servicegroup = xodtemplate_servicegroup_list; temp_servicegroup; temp_servicegroup = temp_servicegroup->next) - xodtemplate_recombobulate_servicegroup_subgroups(temp_servicegroup, NULL); - - /* expand members of all servicegroups - this could be done in xodtemplate_register_servicegroup(), but we can save the CGIs some work if we do it here */ for(temp_servicegroup = xodtemplate_servicegroup_list; temp_servicegroup; temp_servicegroup = temp_servicegroup->next) { - - if(temp_servicegroup->members == NULL) - continue; - - /* skip servicegroups that shouldn't be registered */ - if(temp_servicegroup->register_object == FALSE) - continue; - - member_names = temp_servicegroup->members; - temp_servicegroup->members = NULL; - - for(temp_ptr = member_names; temp_ptr; temp_ptr = strchr(temp_ptr + 1, ',')) { - - /* this is the host name */ - if(host_name == NULL) - host_name = (char *)strdup((temp_ptr[0] == ',') ? temp_ptr + 1 : temp_ptr); - - /* this is the service description */ - else { - service_description = (char *)strdup(temp_ptr + 1); - - /* strsep and strtok cannot be used, as they're used in expand_servicegroups...() */ - temp_ptr2 = strchr(host_name, ','); - if(temp_ptr2) - temp_ptr2[0] = '\x0'; - temp_ptr2 = strchr(service_description, ','); - if(temp_ptr2) - temp_ptr2[0] = '\x0'; - - /* strip trailing spaces */ - strip(host_name); - strip(service_description); - - /* get list of services in the servicegroup */ - temp_memberlist = xodtemplate_expand_servicegroups_and_services(NULL, host_name, service_description, temp_servicegroup->_config_file, temp_servicegroup->_start_line); - - /* add all members to the service group */ - if(temp_memberlist == NULL) { - logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not expand member services specified in servicegroup (config file '%s', starting on line %d)\n", xodtemplate_config_file_name(temp_servicegroup->_config_file), temp_servicegroup->_start_line); - my_free(member_names); - my_free(host_name); - my_free(service_description); - return ERROR; - } - - for(this_memberlist = temp_memberlist; this_memberlist; this_memberlist = this_memberlist->next) { - - /* add this service to the servicegroup members directive */ - if(temp_servicegroup->members == NULL) { - temp_servicegroup->members = (char *)malloc(strlen(this_memberlist->name1) + strlen(this_memberlist->name2) + 2); - if(temp_servicegroup != NULL) { - strcpy(temp_servicegroup->members, this_memberlist->name1); - strcat(temp_servicegroup->members, ","); - strcat(temp_servicegroup->members, this_memberlist->name2); - } - } - else { - new_members = (char *)realloc(temp_servicegroup->members, strlen(temp_servicegroup->members) + strlen(this_memberlist->name1) + strlen(this_memberlist->name2) + 3); - if(new_members != NULL) { - temp_servicegroup->members = new_members; - strcat(temp_servicegroup->members, ","); - strcat(temp_servicegroup->members, this_memberlist->name1); - strcat(temp_servicegroup->members, ","); - strcat(temp_servicegroup->members, this_memberlist->name2); - } - } - } - xodtemplate_free_memberlist(&temp_memberlist); - - my_free(host_name); - my_free(service_description); - } - } - - my_free(member_names); - - /* error if there were an odd number of items specified (unmatched host/service pair) */ - if(host_name != NULL) { - logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Servicegroup members must be specified in , pairs (config file '%s', starting on line %d)\n", xodtemplate_config_file_name(temp_servicegroup->_config_file), temp_servicegroup->_start_line); - my_free(host_name); + if(xodtemplate_recombobulate_servicegroup_subgroups(temp_servicegroup) != XOD_OK) { return ERROR; } + /* rejects are no longer necessary */ + bitmap_destroy(temp_servicegroup->reject_map); + /* make sure we don't recursively add subgroup members again */ + free_objectlist(&temp_servicegroup->group_list); } return OK; @@ -8030,75 +6680,6 @@ int xodtemplate_recombobulate_servicegroups(void) { -int xodtemplate_recombobulate_servicegroup_subgroups(xodtemplate_servicegroup *temp_servicegroup, char **members) { - xodtemplate_servicegroup *sub_group = NULL; - char *orig_sgmembers = NULL; - char *sgmembers = NULL; - char *newmembers = NULL; - char *buf = NULL; - char *ptr = NULL; - - if(temp_servicegroup == NULL) - return ERROR; - - /* resolve subgroup memberships first */ - if(temp_servicegroup->servicegroup_members != NULL) { - - /* save members, null pointer so we don't recurse into infinite hell */ - orig_sgmembers = temp_servicegroup->servicegroup_members; - temp_servicegroup->servicegroup_members = NULL; - - /* make new working copy of members */ - sgmembers = (char *)strdup(orig_sgmembers); - - ptr = sgmembers; - while((buf = ptr) != NULL) { - - /* get next member for next run*/ - ptr = strchr(ptr, ','); - if(ptr) { - ptr[0] = '\x0'; - ptr++; - } - - strip(buf); - - /* find subgroup and recurse */ - if((sub_group = xodtemplate_find_real_servicegroup(buf)) == NULL) { - logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not find member group '%s' specified in servicegroup (config file '%s', starting on line %d)\n", buf, xodtemplate_config_file_name(temp_servicegroup->_config_file), temp_servicegroup->_start_line); - return ERROR; - } - xodtemplate_recombobulate_servicegroup_subgroups(sub_group, &newmembers); - - /* add new (sub) members */ - if(newmembers != NULL) { - if(temp_servicegroup->members == NULL) - temp_servicegroup->members = (char *)strdup(newmembers); - else if((temp_servicegroup->members = realloc(temp_servicegroup->members, strlen(temp_servicegroup->members) + strlen(newmembers) + 2))) { - strcat(temp_servicegroup->members, ","); - strcat(temp_servicegroup->members, newmembers); - } - } - } - - /* free memory */ - my_free(sgmembers); - - /* restore group members */ - temp_servicegroup->servicegroup_members = orig_sgmembers; - } - - /* return service members */ - if(members != NULL) - *members = temp_servicegroup->members; - - return OK; - } - -#endif - - - /******************************************************************/ /******************* OBJECT SEARCH FUNCTIONS **********************/ /******************************************************************/ @@ -8114,7 +6695,7 @@ xodtemplate_timeperiod *xodtemplate_find_timeperiod(char *name) { temp_timeperiod.name = name; - return skiplist_find_first(xobject_template_skiplists[X_TIMEPERIOD_SKIPLIST], &temp_timeperiod, NULL); + return skiplist_find_first(xobject_template_skiplists[TIMEPERIOD_SKIPLIST], &temp_timeperiod, NULL); } @@ -8127,9 +6708,10 @@ xodtemplate_command *xodtemplate_find_command(char *name) { temp_command.name = name; - return skiplist_find_first(xobject_template_skiplists[X_COMMAND_SKIPLIST], &temp_command, NULL); + return skiplist_find_first(xobject_template_skiplists[COMMAND_SKIPLIST], &temp_command, NULL); } +#endif /* finds a specific contactgroup object */ xodtemplate_contactgroup *xodtemplate_find_contactgroup(char *name) { @@ -8140,7 +6722,7 @@ xodtemplate_contactgroup *xodtemplate_find_contactgroup(char *name) { temp_contactgroup.name = name; - return skiplist_find_first(xobject_template_skiplists[X_CONTACTGROUP_SKIPLIST], &temp_contactgroup, NULL); + return skiplist_find_first(xobject_template_skiplists[CONTACTGROUP_SKIPLIST], &temp_contactgroup, NULL); } @@ -8153,7 +6735,7 @@ xodtemplate_contactgroup *xodtemplate_find_real_contactgroup(char *name) { temp_contactgroup.contactgroup_name = name; - return skiplist_find_first(xobject_skiplists[X_CONTACTGROUP_SKIPLIST], &temp_contactgroup, NULL); + return skiplist_find_first(xobject_skiplists[CONTACTGROUP_SKIPLIST], &temp_contactgroup, NULL); } @@ -8166,7 +6748,7 @@ xodtemplate_hostgroup *xodtemplate_find_hostgroup(char *name) { temp_hostgroup.name = name; - return skiplist_find_first(xobject_template_skiplists[X_HOSTGROUP_SKIPLIST], &temp_hostgroup, NULL); + return skiplist_find_first(xobject_template_skiplists[HOSTGROUP_SKIPLIST], &temp_hostgroup, NULL); } @@ -8179,7 +6761,7 @@ xodtemplate_hostgroup *xodtemplate_find_real_hostgroup(char *name) { temp_hostgroup.hostgroup_name = name; - return skiplist_find_first(xobject_skiplists[X_HOSTGROUP_SKIPLIST], &temp_hostgroup, NULL); + return skiplist_find_first(xobject_skiplists[HOSTGROUP_SKIPLIST], &temp_hostgroup, NULL); } @@ -8192,7 +6774,7 @@ xodtemplate_servicegroup *xodtemplate_find_servicegroup(char *name) { temp_servicegroup.name = name; - return skiplist_find_first(xobject_template_skiplists[X_SERVICEGROUP_SKIPLIST], &temp_servicegroup, NULL); + return skiplist_find_first(xobject_template_skiplists[SERVICEGROUP_SKIPLIST], &temp_servicegroup, NULL); } @@ -8205,7 +6787,7 @@ xodtemplate_servicegroup *xodtemplate_find_real_servicegroup(char *name) { temp_servicegroup.servicegroup_name = name; - return skiplist_find_first(xobject_skiplists[X_SERVICEGROUP_SKIPLIST], &temp_servicegroup, NULL); + return skiplist_find_first(xobject_skiplists[SERVICEGROUP_SKIPLIST], &temp_servicegroup, NULL); } @@ -8218,7 +6800,7 @@ xodtemplate_servicedependency *xodtemplate_find_servicedependency(char *name) { temp_servicedependency.name = name; - return skiplist_find_first(xobject_template_skiplists[X_SERVICEDEPENDENCY_SKIPLIST], &temp_servicedependency, NULL); + return skiplist_find_first(xobject_template_skiplists[SERVICEDEPENDENCY_SKIPLIST], &temp_servicedependency, NULL); } @@ -8231,7 +6813,7 @@ xodtemplate_serviceescalation *xodtemplate_find_serviceescalation(char *name) { temp_serviceescalation.name = name; - return skiplist_find_first(xobject_template_skiplists[X_SERVICEESCALATION_SKIPLIST], &temp_serviceescalation, NULL); + return skiplist_find_first(xobject_template_skiplists[SERVICEESCALATION_SKIPLIST], &temp_serviceescalation, NULL); } @@ -8244,7 +6826,7 @@ xodtemplate_contact *xodtemplate_find_contact(char *name) { temp_contact.name = name; - return skiplist_find_first(xobject_template_skiplists[X_CONTACT_SKIPLIST], &temp_contact, NULL); + return skiplist_find_first(xobject_template_skiplists[CONTACT_SKIPLIST], &temp_contact, NULL); } @@ -8257,7 +6839,7 @@ xodtemplate_contact *xodtemplate_find_real_contact(char *name) { temp_contact.contact_name = name; - return skiplist_find_first(xobject_skiplists[X_CONTACT_SKIPLIST], &temp_contact, NULL); + return skiplist_find_first(xobject_skiplists[CONTACT_SKIPLIST], &temp_contact, NULL); } @@ -8270,7 +6852,7 @@ xodtemplate_host *xodtemplate_find_host(char *name) { temp_host.name = name; - return skiplist_find_first(xobject_template_skiplists[X_HOST_SKIPLIST], &temp_host, NULL); + return skiplist_find_first(xobject_template_skiplists[HOST_SKIPLIST], &temp_host, NULL); } @@ -8283,7 +6865,7 @@ xodtemplate_host *xodtemplate_find_real_host(char *name) { temp_host.host_name = name; - return skiplist_find_first(xobject_skiplists[X_HOST_SKIPLIST], &temp_host, NULL); + return skiplist_find_first(xobject_skiplists[HOST_SKIPLIST], &temp_host, NULL); } @@ -8296,7 +6878,7 @@ xodtemplate_hostdependency *xodtemplate_find_hostdependency(char *name) { temp_hostdependency.name = name; - return skiplist_find_first(xobject_template_skiplists[X_HOSTDEPENDENCY_SKIPLIST], &temp_hostdependency, NULL); + return skiplist_find_first(xobject_template_skiplists[HOSTDEPENDENCY_SKIPLIST], &temp_hostdependency, NULL); } @@ -8309,7 +6891,7 @@ xodtemplate_hostescalation *xodtemplate_find_hostescalation(char *name) { temp_hostescalation.name = name; - return skiplist_find_first(xobject_template_skiplists[X_HOSTESCALATION_SKIPLIST], &temp_hostescalation, NULL); + return skiplist_find_first(xobject_template_skiplists[HOSTESCALATION_SKIPLIST], &temp_hostescalation, NULL); } @@ -8322,7 +6904,7 @@ xodtemplate_hostextinfo *xodtemplate_find_hostextinfo(char *name) { temp_hostextinfo.name = name; - return skiplist_find_first(xobject_template_skiplists[X_HOSTEXTINFO_SKIPLIST], &temp_hostextinfo, NULL); + return skiplist_find_first(xobject_template_skiplists[HOSTEXTINFO_SKIPLIST], &temp_hostextinfo, NULL); } @@ -8335,7 +6917,7 @@ xodtemplate_serviceextinfo *xodtemplate_find_serviceextinfo(char *name) { temp_serviceextinfo.name = name; - return skiplist_find_first(xobject_template_skiplists[X_SERVICEEXTINFO_SKIPLIST], &temp_serviceextinfo, NULL); + return skiplist_find_first(xobject_template_skiplists[SERVICEEXTINFO_SKIPLIST], &temp_serviceextinfo, NULL); } @@ -8348,10 +6930,9 @@ xodtemplate_service *xodtemplate_find_service(char *name) { temp_service.name = name; - return skiplist_find_first(xobject_template_skiplists[X_SERVICE_SKIPLIST], &temp_service, NULL); + return skiplist_find_first(xobject_template_skiplists[SERVICE_SKIPLIST], &temp_service, NULL); } - /* finds a specific service object by its REAL name, not its TEMPLATE name */ xodtemplate_service *xodtemplate_find_real_service(char *host_name, char *service_description) { xodtemplate_service temp_service; @@ -8362,10 +6943,9 @@ xodtemplate_service *xodtemplate_find_real_service(char *host_name, char *servic temp_service.host_name = host_name; temp_service.service_description = service_description; - return skiplist_find_first(xobject_skiplists[X_SERVICE_SKIPLIST], &temp_service, NULL); + return skiplist_find_first(xobject_skiplists[SERVICE_SKIPLIST], &temp_service, NULL); } -#endif @@ -8373,9 +6953,95 @@ xodtemplate_service *xodtemplate_find_real_service(char *host_name, char *servic /**************** OBJECT REGISTRATION FUNCTIONS *******************/ /******************************************************************/ -/* registers object definitions */ +static int xodtemplate_register_contactgroup_members(xodtemplate_contactgroup *this_contactgroup) +{ + objectlist *list; + struct contactgroup *cg; + int num_regs = 0; + + if (!this_contactgroup->register_object) + return 0; + + cg = find_contactgroup(this_contactgroup->contactgroup_name); + for(list = this_contactgroup->member_list; list; list = list->next) { + xodtemplate_contact *c = (xodtemplate_contact *)list->object_ptr; + if (!add_contact_to_contactgroup(cg, c->contact_name)) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Bad member of contactgroup '%s' (config file '%s', starting on line %d)\n", cg->group_name, xodtemplate_config_file_name(this_contactgroup->_config_file), this_contactgroup->_start_line); + return -1; + } + num_regs++; + } + return num_regs; +} + +static int xodtemplate_register_hostgroup_members(xodtemplate_hostgroup *this_hostgroup) +{ + objectlist *list; + struct hostgroup *hg; + int num_regs = 0; + + if (!this_hostgroup->register_object) + return 0; + + hg = find_hostgroup(this_hostgroup->hostgroup_name); + for(list = this_hostgroup->member_list; list; list = list->next) { + xodtemplate_host *h = (xodtemplate_host *)list->object_ptr; + if (!add_host_to_hostgroup(hg, h->host_name)) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Bad member of hostgroup '%s' (config file '%s', starting on line %d)\n", hg->group_name, xodtemplate_config_file_name(this_hostgroup->_config_file), this_hostgroup->_start_line); + return -1; + } + num_regs++; + } + return num_regs; + } + +static int xodtemplate_register_servicegroup_members(xodtemplate_servicegroup *this_servicegroup) +{ + objectlist *list, *next; + struct servicegroup *sg; + int num_regs = 0; + + if (!this_servicegroup->register_object) + return 0; + + sg = find_servicegroup(this_servicegroup->servicegroup_name); + for(list = this_servicegroup->member_list; list; list = next) { + xodtemplate_service *s = (xodtemplate_service *)list->object_ptr; + next = list->next; + if (!add_service_to_servicegroup(sg, s->host_name, s->service_description)) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Bad member of servicegroup '%s' (config file '%s', starting on line %d)\n", sg->group_name, xodtemplate_config_file_name(this_servicegroup->_config_file), this_servicegroup->_start_line); + return -1; + } + num_regs++; + } + + return num_regs; + } + +/* + * registers object definitions + * The order goes like this: + * Timeperiods + * Commands + * Contactgroups + * Hostgroups + * Servicegroups + * Contacts + * Hosts + * Services + * Servicedependencies + * Serviceescalations + * Hostdependencies + * Hostescalations + * + * Why are contactgroups done before contacts? A reasonable assumption + * would be that contacts should be flattened and added to the checked + * objects directly rather than forcing us to fiddle with that crap + * during runtime. + */ int xodtemplate_register_objects(void) { - int result = OK; + unsigned int i; + int mcount; xodtemplate_timeperiod *temp_timeperiod = NULL; xodtemplate_command *temp_command = NULL; xodtemplate_contactgroup *temp_contactgroup = NULL; @@ -8384,108 +7050,174 @@ int xodtemplate_register_objects(void) { xodtemplate_contact *temp_contact = NULL; xodtemplate_host *temp_host = NULL; xodtemplate_service *temp_service = NULL; - xodtemplate_servicedependency *temp_servicedependency = NULL; - xodtemplate_serviceescalation *temp_serviceescalation = NULL; - xodtemplate_hostdependency *temp_hostdependency = NULL; - xodtemplate_hostescalation *temp_hostescalation = NULL; void *ptr = NULL; + xodtemplate_hostdependency *hd, *next_hd; + xodtemplate_hostescalation *he, *next_he; + xodtemplate_servicedependency *sd, *next_sd; + xodtemplate_serviceescalation *se, *next_se; + unsigned int ocount[NUM_OBJECT_SKIPLISTS]; + unsigned int tot_members = 0; + + + for (i = 0; i < ARRAY_SIZE(ocount); i++) { + ocount[i] = (unsigned int)skiplist_num_items(xobject_skiplists[i]); + } + + /* dependencies are handled specially */ + ocount[SERVICEDEPENDENCY_SKIPLIST] = 0; + ocount[HOSTDEPENDENCY_SKIPLIST] = 0; + ocount[HOSTESCALATION_SKIPLIST] = xodcount.hostescalations; + ocount[SERVICEESCALATION_SKIPLIST] = xodcount.serviceescalations; + + if (create_object_tables(ocount) != OK) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Failed to create object tables\n"); + return ERROR; + } /* register timeperiods */ - /*for(temp_timeperiod=xodtemplate_timeperiod_list;temp_timeperiod!=NULL;temp_timeperiod=temp_timeperiod->next){*/ ptr = NULL; - for(temp_timeperiod = (xodtemplate_timeperiod *)skiplist_get_first(xobject_skiplists[X_TIMEPERIOD_SKIPLIST], &ptr); temp_timeperiod != NULL; temp_timeperiod = (xodtemplate_timeperiod *)skiplist_get_next(&ptr)) { - if((result = xodtemplate_register_timeperiod(temp_timeperiod)) == ERROR) + for(temp_timeperiod = (xodtemplate_timeperiod *)skiplist_get_first(xobject_skiplists[TIMEPERIOD_SKIPLIST], &ptr); temp_timeperiod != NULL; temp_timeperiod = (xodtemplate_timeperiod *)skiplist_get_next(&ptr)) { + if(xodtemplate_register_timeperiod(temp_timeperiod) == ERROR) return ERROR; } + timing_point("%u timeperiods registered\n", num_objects.timeperiods); /* register commands */ - /*for(temp_command=xodtemplate_command_list;temp_command!=NULL;temp_command=temp_command->next){*/ ptr = NULL; - for(temp_command = (xodtemplate_command *)skiplist_get_first(xobject_skiplists[X_COMMAND_SKIPLIST], &ptr); temp_command != NULL; temp_command = (xodtemplate_command *)skiplist_get_next(&ptr)) { - if((result = xodtemplate_register_command(temp_command)) == ERROR) + for(temp_command = (xodtemplate_command *)skiplist_get_first(xobject_skiplists[COMMAND_SKIPLIST], &ptr); temp_command != NULL; temp_command = (xodtemplate_command *)skiplist_get_next(&ptr)) { + if(xodtemplate_register_command(temp_command) == ERROR) return ERROR; } + timing_point("%u commands registered\n", num_objects.commands); /* register contactgroups */ - /*for(temp_contactgroup=xodtemplate_contactgroup_list;temp_contactgroup!=NULL;temp_contactgroup=temp_contactgroup->next){*/ ptr = NULL; - for(temp_contactgroup = (xodtemplate_contactgroup *)skiplist_get_first(xobject_skiplists[X_CONTACTGROUP_SKIPLIST], &ptr); temp_contactgroup != NULL; temp_contactgroup = (xodtemplate_contactgroup *)skiplist_get_next(&ptr)) { - if((result = xodtemplate_register_contactgroup(temp_contactgroup)) == ERROR) + for(temp_contactgroup = (xodtemplate_contactgroup *)skiplist_get_first(xobject_skiplists[CONTACTGROUP_SKIPLIST], &ptr); temp_contactgroup != NULL; temp_contactgroup = (xodtemplate_contactgroup *)skiplist_get_next(&ptr)) { + if(xodtemplate_register_contactgroup(temp_contactgroup) == ERROR) return ERROR; } + timing_point("%u contactgroups registered\n", num_objects.contactgroups); /* register hostgroups */ - /*for(temp_hostgroup=xodtemplate_hostgroup_list;temp_hostgroup!=NULL;temp_hostgroup=temp_hostgroup->next){*/ ptr = NULL; - for(temp_hostgroup = (xodtemplate_hostgroup *)skiplist_get_first(xobject_skiplists[X_HOSTGROUP_SKIPLIST], &ptr); temp_hostgroup != NULL; temp_hostgroup = (xodtemplate_hostgroup *)skiplist_get_next(&ptr)) { - if((result = xodtemplate_register_hostgroup(temp_hostgroup)) == ERROR) + for(temp_hostgroup = (xodtemplate_hostgroup *)skiplist_get_first(xobject_skiplists[HOSTGROUP_SKIPLIST], &ptr); temp_hostgroup != NULL; temp_hostgroup = (xodtemplate_hostgroup *)skiplist_get_next(&ptr)) { + if(xodtemplate_register_hostgroup(temp_hostgroup) == ERROR) return ERROR; } + timing_point("%u hostgroups registered\n", num_objects.hostgroups); /* register servicegroups */ - /*for(temp_servicegroup=xodtemplate_servicegroup_list;temp_servicegroup!=NULL;temp_servicegroup=temp_servicegroup->next){*/ ptr = NULL; - for(temp_servicegroup = (xodtemplate_servicegroup *)skiplist_get_first(xobject_skiplists[X_SERVICEGROUP_SKIPLIST], &ptr); temp_servicegroup != NULL; temp_servicegroup = (xodtemplate_servicegroup *)skiplist_get_next(&ptr)) { - if((result = xodtemplate_register_servicegroup(temp_servicegroup)) == ERROR) + for(temp_servicegroup = (xodtemplate_servicegroup *)skiplist_get_first(xobject_skiplists[SERVICEGROUP_SKIPLIST], &ptr); temp_servicegroup != NULL; temp_servicegroup = (xodtemplate_servicegroup *)skiplist_get_next(&ptr)) { + if(xodtemplate_register_servicegroup(temp_servicegroup) == ERROR) return ERROR; } + timing_point("%u servicegroups registered\n", num_objects.servicegroups); /* register contacts */ - /*for(temp_contact=xodtemplate_contact_list;temp_contact!=NULL;temp_contact=temp_contact->next){*/ ptr = NULL; - for(temp_contact = (xodtemplate_contact *)skiplist_get_first(xobject_skiplists[X_CONTACT_SKIPLIST], &ptr); temp_contact != NULL; temp_contact = (xodtemplate_contact *)skiplist_get_next(&ptr)) { - if((result = xodtemplate_register_contact(temp_contact)) == ERROR) + for(temp_contact = (xodtemplate_contact *)skiplist_get_first(xobject_skiplists[CONTACT_SKIPLIST], &ptr); temp_contact != NULL; temp_contact = (xodtemplate_contact *)skiplist_get_next(&ptr)) { + if(xodtemplate_register_contact(temp_contact) == ERROR) return ERROR; } + timing_point("%u contacts registered\n", num_objects.contacts); /* register hosts */ - /*for(temp_host=xodtemplate_host_list;temp_host!=NULL;temp_host=temp_host->next){*/ ptr = NULL; - for(temp_host = (xodtemplate_host *)skiplist_get_first(xobject_skiplists[X_HOST_SKIPLIST], &ptr); temp_host != NULL; temp_host = (xodtemplate_host *)skiplist_get_next(&ptr)) { - if((result = xodtemplate_register_host(temp_host)) == ERROR) + for(temp_host = (xodtemplate_host *)skiplist_get_first(xobject_skiplists[HOST_SKIPLIST], &ptr); temp_host != NULL; temp_host = (xodtemplate_host *)skiplist_get_next(&ptr)) { + if(xodtemplate_register_host(temp_host) == ERROR) return ERROR; } + timing_point("%u hosts registered\n", num_objects.hosts); /* register services */ - /*for(temp_service=xodtemplate_service_list;temp_service!=NULL;temp_service=temp_service->next){*/ ptr = NULL; - for(temp_service = (xodtemplate_service *)skiplist_get_first(xobject_skiplists[X_SERVICE_SKIPLIST], &ptr); temp_service != NULL; temp_service = (xodtemplate_service *)skiplist_get_next(&ptr)) { - - if((result = xodtemplate_register_service(temp_service)) == ERROR) + for(temp_service = (xodtemplate_service *)skiplist_get_first(xobject_skiplists[SERVICE_SKIPLIST], &ptr); temp_service != NULL; temp_service = (xodtemplate_service *)skiplist_get_next(&ptr)) { + if(xodtemplate_register_service(temp_service) == ERROR) return ERROR; } + timing_point("%u services registered\n", num_objects.services); - /* register service dependencies */ - /*for(temp_servicedependency=xodtemplate_servicedependency_list;temp_servicedependency!=NULL;temp_servicedependency=temp_servicedependency->next){*/ - ptr = NULL; - for(temp_servicedependency = (xodtemplate_servicedependency *)skiplist_get_first(xobject_skiplists[X_SERVICEDEPENDENCY_SKIPLIST], &ptr); temp_servicedependency != NULL; temp_servicedependency = (xodtemplate_servicedependency *)skiplist_get_next(&ptr)) { - if((result = xodtemplate_register_servicedependency(temp_servicedependency)) == ERROR) + /* groups and objects are registered, so join them up */ + /* register contactgroup members */ + ptr = NULL; tot_members = 0; + for(temp_contactgroup = (xodtemplate_contactgroup *)skiplist_get_first(xobject_skiplists[CONTACTGROUP_SKIPLIST], &ptr); temp_contactgroup != NULL; temp_contactgroup = (xodtemplate_contactgroup *)skiplist_get_next(&ptr)) { + if((mcount = xodtemplate_register_contactgroup_members(temp_contactgroup)) < 0) + return ERROR; + tot_members += mcount; + } + timing_point("%u contactgroup memberships registered\n", tot_members); + + /* register hostgroup members */ + ptr = NULL; tot_members = 0; + for(temp_hostgroup = (xodtemplate_hostgroup *)skiplist_get_first(xobject_skiplists[HOSTGROUP_SKIPLIST], &ptr); temp_hostgroup != NULL; temp_hostgroup = (xodtemplate_hostgroup *)skiplist_get_next(&ptr)) { + if((mcount = xodtemplate_register_hostgroup_members(temp_hostgroup)) < 0) + return ERROR; + tot_members += mcount; + } + timing_point("%u hostgroup memberships registered\n", tot_members); + + /* register servicegroup members */ + ptr = NULL; tot_members = 0; + for(temp_servicegroup = (xodtemplate_servicegroup *)skiplist_get_first(xobject_skiplists[SERVICEGROUP_SKIPLIST], &ptr); temp_servicegroup != NULL; temp_servicegroup = (xodtemplate_servicegroup *)skiplist_get_next(&ptr)) { + if((mcount = xodtemplate_register_servicegroup_members(temp_servicegroup)) < 0) + return ERROR; + tot_members += mcount; + } + timing_point("%u servicegroup memberships registered\n", tot_members); + + /* + * These aren't in skiplists at all, but it's safe to destroy + * them as we go along, since all dupes are at the head of the list + */ + if(xodtemplate_servicedependency_list) { + parent_map = bitmap_create(xodcount.services); + if(!parent_map) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Failed to create parent bitmap for service dependencies\n"); + return ERROR; + } + for(sd = xodtemplate_servicedependency_list; sd; sd = next_sd) { + next_sd = sd->next; +#ifdef NSCGI + if(xodtemplate_register_servicedependency(sd) == ERROR) + return ERROR; +#else + if(xodtemplate_register_and_destroy_servicedependency(sd) == ERROR) + return ERROR; +#endif + } + bitmap_destroy(parent_map); + parent_map = NULL; + } + timing_point("%u unique / %u total servicedependencies registered\n", + num_objects.servicedependencies, xodcount.servicedependencies); + + for(se = xodtemplate_serviceescalation_list; se; se = next_se) { + next_se = se->next; + if(xodtemplate_register_and_destroy_serviceescalation(se) == ERROR) return ERROR; } + timing_point("%u serviceescalations registered\n", num_objects.serviceescalations); - /* register service escalations */ - /*for(temp_serviceescalation=xodtemplate_serviceescalation_list;temp_serviceescalation!=NULL;temp_serviceescalation=temp_serviceescalation->next){*/ - ptr = NULL; - for(temp_serviceescalation = (xodtemplate_serviceescalation *)skiplist_get_first(xobject_skiplists[X_SERVICEESCALATION_SKIPLIST], &ptr); temp_serviceescalation != NULL; temp_serviceescalation = (xodtemplate_serviceescalation *)skiplist_get_next(&ptr)) { - if((result = xodtemplate_register_serviceescalation(temp_serviceescalation)) == ERROR) - return ERROR; - } - - /* register host dependencies */ - /*for(temp_hostdependency=xodtemplate_hostdependency_list;temp_hostdependency!=NULL;temp_hostdependency=temp_hostdependency->next){*/ - ptr = NULL; - for(temp_hostdependency = (xodtemplate_hostdependency *)skiplist_get_first(xobject_skiplists[X_HOSTDEPENDENCY_SKIPLIST], &ptr); temp_hostdependency != NULL; temp_hostdependency = (xodtemplate_hostdependency *)skiplist_get_next(&ptr)) { - if((result = xodtemplate_register_hostdependency(temp_hostdependency)) == ERROR) - return ERROR; - } - - /* register host escalations */ - /*for(temp_hostescalation=xodtemplate_hostescalation_list;temp_hostescalation!=NULL;temp_hostescalation=temp_hostescalation->next){*/ - ptr = NULL; - for(temp_hostescalation = (xodtemplate_hostescalation *)skiplist_get_first(xobject_skiplists[X_HOSTESCALATION_SKIPLIST], &ptr); temp_hostescalation != NULL; temp_hostescalation = (xodtemplate_hostescalation *)skiplist_get_next(&ptr)) { - if((result = xodtemplate_register_hostescalation(temp_hostescalation)) == ERROR) + for(hd = xodtemplate_hostdependency_list; hd; hd = next_hd) { + next_hd = hd->next; +#ifdef NSCGI + if(xodtemplate_register_hostdependency(hd) == ERROR) + return ERROR; +#else + if(xodtemplate_register_and_destroy_hostdependency(hd) == ERROR) + return ERROR; +#endif + } + timing_point("%u unique / %u total hostdependencies registered\n", + num_objects.hostdependencies, xodcount.hostdependencies); + + for(he = xodtemplate_hostescalation_list; he; he = next_he) { + next_he = he->next; + if(xodtemplate_register_and_destroy_hostescalation(he) == ERROR) return ERROR; } + timing_point("%u hostescalations registered\n", num_objects.hostescalations); return OK; } @@ -8681,12 +7413,9 @@ int xodtemplate_register_command(xodtemplate_command *this_command) { } - /* registers a contactgroup definition */ int xodtemplate_register_contactgroup(xodtemplate_contactgroup *this_contactgroup) { contactgroup *new_contactgroup = NULL; - contactsmember *new_contactsmember = NULL; - char *contact_name = NULL; /* bail out if we shouldn't register this object */ if(this_contactgroup->register_object == FALSE) @@ -8701,18 +7430,6 @@ int xodtemplate_register_contactgroup(xodtemplate_contactgroup *this_contactgrou return ERROR; } - /* Need to check for NULL because strtok could use a NULL value to check the previous string's token value */ - if(this_contactgroup->members != NULL) { - for(contact_name = strtok(this_contactgroup->members, ","); contact_name != NULL; contact_name = strtok(NULL, ",")) { - strip(contact_name); - new_contactsmember = add_contact_to_contactgroup(new_contactgroup, contact_name); - if(new_contactsmember == NULL) { - logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not add contact '%s' to contactgroup (config file '%s', starting on line %d)\n", contact_name, xodtemplate_config_file_name(this_contactgroup->_config_file), this_contactgroup->_start_line); - return ERROR; - } - } - } - return OK; } @@ -8721,8 +7438,6 @@ int xodtemplate_register_contactgroup(xodtemplate_contactgroup *this_contactgrou /* registers a hostgroup definition */ int xodtemplate_register_hostgroup(xodtemplate_hostgroup *this_hostgroup) { hostgroup *new_hostgroup = NULL; - hostsmember *new_hostsmember = NULL; - char *host_name = NULL; /* bail out if we shouldn't register this object */ if(this_hostgroup->register_object == FALSE) @@ -8737,28 +7452,12 @@ int xodtemplate_register_hostgroup(xodtemplate_hostgroup *this_hostgroup) { return ERROR; } - if(this_hostgroup->members != NULL) { - for(host_name = strtok(this_hostgroup->members, ","); host_name != NULL; host_name = strtok(NULL, ",")) { - strip(host_name); - new_hostsmember = add_host_to_hostgroup(new_hostgroup, host_name); - if(new_hostsmember == NULL) { - logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not add host '%s' to hostgroup (config file '%s', starting on line %d)\n", host_name, xodtemplate_config_file_name(this_hostgroup->_config_file), this_hostgroup->_start_line); - return ERROR; - } - } - } - return OK; } - - /* registers a servicegroup definition */ int xodtemplate_register_servicegroup(xodtemplate_servicegroup *this_servicegroup) { servicegroup *new_servicegroup = NULL; - servicesmember *new_servicesmember = NULL; - char *host_name = NULL; - char *svc_description = NULL; /* bail out if we shouldn't register this object */ if(this_servicegroup->register_object == FALSE) @@ -8773,29 +7472,10 @@ int xodtemplate_register_servicegroup(xodtemplate_servicegroup *this_servicegrou return ERROR; } - if(this_servicegroup->members != NULL) { - for(host_name = strtok(this_servicegroup->members, ","); host_name != NULL; host_name = strtok(NULL, ",")) { - strip(host_name); - svc_description = strtok(NULL, ","); - if(svc_description == NULL) { - logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Missing service name in servicegroup definition (config file '%s', starting on line %d)\n", xodtemplate_config_file_name(this_servicegroup->_config_file), this_servicegroup->_start_line); - return ERROR; - } - strip(svc_description); - - new_servicesmember = add_service_to_servicegroup(new_servicegroup, host_name, svc_description); - if(new_servicesmember == NULL) { - logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not add service '%s' on host '%s' to servicegroup (config file '%s', starting on line %d)\n", svc_description, host_name, xodtemplate_config_file_name(this_servicegroup->_config_file), this_servicegroup->_start_line); - return ERROR; - } - } - } - return OK; } - /* registers a servicedependency definition */ int xodtemplate_register_servicedependency(xodtemplate_servicedependency *this_servicedependency) { servicedependency *new_servicedependency = NULL; @@ -8805,15 +7485,16 @@ int xodtemplate_register_servicedependency(xodtemplate_servicedependency *this_s return OK; /* throw a warning on servicedeps that have no options */ - if(this_servicedependency->have_notification_dependency_options == FALSE && this_servicedependency->have_execution_dependency_options == FALSE) { + if(this_servicedependency->have_notification_failure_options == FALSE && this_servicedependency->have_execution_failure_options == FALSE) { logit(NSLOG_CONFIG_WARNING, TRUE, "Warning: Ignoring lame service dependency (config file '%s', line %d)\n", xodtemplate_config_file_name(this_servicedependency->_config_file), this_servicedependency->_start_line); return OK; } /* add the servicedependency */ - if(this_servicedependency->have_execution_dependency_options == TRUE) { + if(this_servicedependency->have_execution_failure_options == TRUE) { + xodcount.servicedependencies++; - new_servicedependency = add_service_dependency(this_servicedependency->dependent_host_name, this_servicedependency->dependent_service_description, this_servicedependency->host_name, this_servicedependency->service_description, EXECUTION_DEPENDENCY, this_servicedependency->inherits_parent, this_servicedependency->fail_execute_on_ok, this_servicedependency->fail_execute_on_warning, this_servicedependency->fail_execute_on_unknown, this_servicedependency->fail_execute_on_critical, this_servicedependency->fail_execute_on_pending, this_servicedependency->dependency_period); + new_servicedependency = add_service_dependency(this_servicedependency->dependent_host_name, this_servicedependency->dependent_service_description, this_servicedependency->host_name, this_servicedependency->service_description, EXECUTION_DEPENDENCY, this_servicedependency->inherits_parent, this_servicedependency->execution_failure_options, this_servicedependency->dependency_period); /* return with an error if we couldn't add the servicedependency */ if(new_servicedependency == NULL) { @@ -8821,9 +7502,10 @@ int xodtemplate_register_servicedependency(xodtemplate_servicedependency *this_s return ERROR; } } - if(this_servicedependency->have_notification_dependency_options == TRUE) { + if(this_servicedependency->have_notification_failure_options == TRUE) { + xodcount.servicedependencies++; - new_servicedependency = add_service_dependency(this_servicedependency->dependent_host_name, this_servicedependency->dependent_service_description, this_servicedependency->host_name, this_servicedependency->service_description, NOTIFICATION_DEPENDENCY, this_servicedependency->inherits_parent, this_servicedependency->fail_notify_on_ok, this_servicedependency->fail_notify_on_warning, this_servicedependency->fail_notify_on_unknown, this_servicedependency->fail_notify_on_critical, this_servicedependency->fail_notify_on_pending, this_servicedependency->dependency_period); + new_servicedependency = add_service_dependency(this_servicedependency->dependent_host_name, this_servicedependency->dependent_service_description, this_servicedependency->host_name, this_servicedependency->service_description, NOTIFICATION_DEPENDENCY, this_servicedependency->inherits_parent, this_servicedependency->notification_failure_options, this_servicedependency->dependency_period); /* return with an error if we couldn't add the servicedependency */ if(new_servicedependency == NULL) { @@ -8851,14 +7533,11 @@ int xodtemplate_register_serviceescalation(xodtemplate_serviceescalation *this_s /* default options if none specified */ if(this_serviceescalation->have_escalation_options == FALSE) { - this_serviceescalation->escalate_on_warning = TRUE; - this_serviceescalation->escalate_on_unknown = TRUE; - this_serviceescalation->escalate_on_critical = TRUE; - this_serviceescalation->escalate_on_recovery = TRUE; + this_serviceescalation->escalation_options = OPT_ALL; } /* add the serviceescalation */ - new_serviceescalation = add_serviceescalation(this_serviceescalation->host_name, this_serviceescalation->service_description, this_serviceescalation->first_notification, this_serviceescalation->last_notification, this_serviceescalation->notification_interval, this_serviceescalation->escalation_period, this_serviceescalation->escalate_on_warning, this_serviceescalation->escalate_on_unknown, this_serviceescalation->escalate_on_critical, this_serviceescalation->escalate_on_recovery); + new_serviceescalation = add_serviceescalation(this_serviceescalation->host_name, this_serviceescalation->service_description, this_serviceescalation->first_notification, this_serviceescalation->last_notification, this_serviceescalation->notification_interval, this_serviceescalation->escalation_period, this_serviceescalation->escalation_options); /* return with an error if we couldn't add the serviceescalation */ if(new_serviceescalation == NULL) { @@ -8869,7 +7548,7 @@ int xodtemplate_register_serviceescalation(xodtemplate_serviceescalation *this_s /* add the contact groups */ if(this_serviceescalation->contact_groups != NULL) { - for(contact_group = strtok(this_serviceescalation->contact_groups, ","); contact_group != NULL; contact_group = strtok(NULL, ", ")) { + for(contact_group = strtok(this_serviceescalation->contact_groups, ","); contact_group != NULL; contact_group = strtok(NULL, ",")) { strip(contact_group); new_contactgroupsmember = add_contactgroup_to_serviceescalation(new_serviceescalation, contact_group); @@ -8883,7 +7562,7 @@ int xodtemplate_register_serviceescalation(xodtemplate_serviceescalation *this_s /* add the contacts */ if(this_serviceescalation->contacts != NULL) { - for(contact_name = strtok(this_serviceescalation->contacts, ","); contact_name != NULL; contact_name = strtok(NULL, ", ")) { + for(contact_name = strtok(this_serviceescalation->contacts, ","); contact_name != NULL; contact_name = strtok(NULL, ",")) { strip(contact_name); new_contactsmember = add_contact_to_serviceescalation(new_serviceescalation, contact_name); @@ -8911,7 +7590,7 @@ int xodtemplate_register_contact(xodtemplate_contact *this_contact) { return OK; /* add the contact */ - new_contact = add_contact(this_contact->contact_name, this_contact->alias, this_contact->email, this_contact->pager, this_contact->address, this_contact->service_notification_period, this_contact->host_notification_period, this_contact->notify_on_service_recovery, this_contact->notify_on_service_critical, this_contact->notify_on_service_warning, this_contact->notify_on_service_unknown, this_contact->notify_on_service_flapping, this_contact->notify_on_service_downtime, this_contact->notify_on_host_recovery, this_contact->notify_on_host_down, this_contact->notify_on_host_unreachable, this_contact->notify_on_host_flapping, this_contact->notify_on_host_downtime, this_contact->host_notifications_enabled, this_contact->service_notifications_enabled, this_contact->can_submit_commands, this_contact->retain_status_information, this_contact->retain_nonstatus_information); + new_contact = add_contact(this_contact->contact_name, this_contact->alias, this_contact->email, this_contact->pager, this_contact->address, this_contact->service_notification_period, this_contact->host_notification_period, this_contact->service_notification_options, this_contact->host_notification_options, this_contact->host_notifications_enabled, this_contact->service_notifications_enabled, this_contact->can_submit_commands, this_contact->retain_status_information, this_contact->retain_nonstatus_information, this_contact->minimum_value); /* return with an error if we couldn't add the contact */ if(new_contact == NULL) { @@ -8971,14 +7650,8 @@ int xodtemplate_register_host(xodtemplate_host *this_host) { if(this_host->register_object == FALSE) return OK; - /* if host has no alias or address, use host name - added 3/11/05 */ - if(this_host->alias == NULL && this_host->host_name != NULL) - this_host->alias = (char *)strdup(this_host->host_name); - if(this_host->address == NULL && this_host->host_name != NULL) - this_host->address = (char *)strdup(this_host->host_name); - /* add the host definition */ - new_host = add_host(this_host->host_name, this_host->display_name, this_host->alias, (this_host->address == NULL) ? this_host->host_name : this_host->address, this_host->check_period, this_host->initial_state, this_host->check_interval, this_host->retry_interval, this_host->max_check_attempts, this_host->notify_on_recovery, this_host->notify_on_down, this_host->notify_on_unreachable, this_host->notify_on_flapping, this_host->notify_on_downtime, this_host->notification_interval, this_host->first_notification_delay, this_host->notification_period, this_host->notifications_enabled, this_host->check_command, this_host->active_checks_enabled, this_host->passive_checks_enabled, this_host->event_handler, this_host->event_handler_enabled, this_host->flap_detection_enabled, this_host->low_flap_threshold, this_host->high_flap_threshold, this_host->flap_detection_on_up, this_host->flap_detection_on_down, this_host->flap_detection_on_unreachable, this_host->stalk_on_up, this_host->stalk_on_down, this_host->stalk_on_unreachable, this_host->process_perf_data, this_host->failure_prediction_enabled, this_host->failure_prediction_options, this_host->check_freshness, this_host->freshness_threshold, this_host->notes, this_host->notes_url, this_host->action_url, this_host->icon_image, this_host->icon_image_alt, this_host->vrml_image, this_host->statusmap_image, this_host->x_2d, this_host->y_2d, this_host->have_2d_coords, this_host->x_3d, this_host->y_3d, this_host->z_3d, this_host->have_3d_coords, TRUE, this_host->retain_status_information, this_host->retain_nonstatus_information, this_host->obsess_over_host); + new_host = add_host(this_host->host_name, this_host->display_name, this_host->alias, this_host->address, this_host->check_period, this_host->initial_state, this_host->check_interval, this_host->retry_interval, this_host->max_check_attempts, this_host->notification_options, this_host->notification_interval, this_host->first_notification_delay, this_host->notification_period, this_host->notifications_enabled, this_host->check_command, this_host->active_checks_enabled, this_host->passive_checks_enabled, this_host->event_handler, this_host->event_handler_enabled, this_host->flap_detection_enabled, this_host->low_flap_threshold, this_host->high_flap_threshold, this_host->flap_detection_options, this_host->stalking_options, this_host->process_perf_data, this_host->check_freshness, this_host->freshness_threshold, this_host->notes, this_host->notes_url, this_host->action_url, this_host->icon_image, this_host->icon_image_alt, this_host->vrml_image, this_host->statusmap_image, this_host->x_2d, this_host->y_2d, this_host->have_2d_coords, this_host->x_3d, this_host->y_3d, this_host->z_3d, this_host->have_3d_coords, TRUE, this_host->retain_status_information, this_host->retain_nonstatus_information, this_host->obsess, this_host->hourly_value); /* return with an error if we couldn't add the host */ @@ -9055,7 +7728,7 @@ int xodtemplate_register_service(xodtemplate_service *this_service) { return OK; /* add the service */ - new_service = add_service(this_service->host_name, this_service->service_description, this_service->display_name, this_service->check_period, this_service->initial_state, this_service->max_check_attempts, this_service->parallelize_check, this_service->passive_checks_enabled, this_service->check_interval, this_service->retry_interval, this_service->notification_interval, this_service->first_notification_delay, this_service->notification_period, this_service->notify_on_recovery, this_service->notify_on_unknown, this_service->notify_on_warning, this_service->notify_on_critical, this_service->notify_on_flapping, this_service->notify_on_downtime, this_service->notifications_enabled, this_service->is_volatile, this_service->event_handler, this_service->event_handler_enabled, this_service->check_command, this_service->active_checks_enabled, this_service->flap_detection_enabled, this_service->low_flap_threshold, this_service->high_flap_threshold, this_service->flap_detection_on_ok, this_service->flap_detection_on_warning, this_service->flap_detection_on_unknown, this_service->flap_detection_on_critical, this_service->stalk_on_ok, this_service->stalk_on_warning, this_service->stalk_on_unknown, this_service->stalk_on_critical, this_service->process_perf_data, this_service->failure_prediction_enabled, this_service->failure_prediction_options, this_service->check_freshness, this_service->freshness_threshold, this_service->notes, this_service->notes_url, this_service->action_url, this_service->icon_image, this_service->icon_image_alt, this_service->retain_status_information, this_service->retain_nonstatus_information, this_service->obsess_over_service); + new_service = add_service(this_service->host_name, this_service->service_description, this_service->display_name, this_service->check_period, this_service->initial_state, this_service->max_check_attempts, this_service->parallelize_check, this_service->passive_checks_enabled, this_service->check_interval, this_service->retry_interval, this_service->notification_interval, this_service->first_notification_delay, this_service->notification_period, this_service->notification_options, this_service->notifications_enabled, this_service->is_volatile, this_service->event_handler, this_service->event_handler_enabled, this_service->check_command, this_service->active_checks_enabled, this_service->flap_detection_enabled, this_service->low_flap_threshold, this_service->high_flap_threshold, this_service->flap_detection_options, this_service->stalking_options, this_service->process_perf_data, this_service->check_freshness, this_service->freshness_threshold, this_service->notes, this_service->notes_url, this_service->action_url, this_service->icon_image, this_service->icon_image_alt, this_service->retain_status_information, this_service->retain_nonstatus_information, this_service->obsess, this_service->hourly_value); /* return with an error if we couldn't add the service */ if(new_service == NULL) { @@ -9063,6 +7736,49 @@ int xodtemplate_register_service(xodtemplate_service *this_service) { return ERROR; } + /* add all service parents */ + if(this_service->parents != NULL) { + servicesmember *new_servicesmember; + char *comma = strchr(this_service->parents, ','); + + if(!comma) { /* same-host single-service parent */ + new_servicesmember = add_parent_service_to_service(new_service, new_service->host_name, this_service->parents); + if(new_servicesmember == NULL) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not add same-host service parent '%s' to service (config file '%s', starting on line %d)\n", + this_service->parents, + xodtemplate_config_file_name(this_service->_config_file), + this_service->_start_line); + return ERROR; + } + } + else { + /* Multiple parents, so let's do this the hard way */ + objectlist *list = NULL, *next; + bitmap_clear(service_map); + if(xodtemplate_expand_services(&list, service_map, NULL, this_service->parents, this_service->_config_file, this_service->_start_line) != OK) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Failed to expand service parents (config file '%s', starting at line %d)\n", + xodtemplate_config_file_name(this_service->_config_file), + this_service->_start_line); + return ERROR; + } + for(; list; list = next) { + xodtemplate_service *parent = (xodtemplate_service *)list->object_ptr; + next = list->next; + free(list); + new_servicesmember = add_parent_service_to_service(new_service, parent->host_name, parent->service_description); + if(new_servicesmember == NULL) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not add service '%s' on host '%s' as parent to service '%s' on host '%s' (config file '%s', starting on line %d)\n", + parent->host_name, parent->service_description, + new_service->host_name, new_service->description, + xodtemplate_config_file_name(this_service->_config_file), + this_service->_start_line); + free_objectlist(&next); + return ERROR; + } + } + } + } + /* add all contact groups to the service */ if(this_service->contact_groups != NULL) { @@ -9116,9 +7832,10 @@ int xodtemplate_register_hostdependency(xodtemplate_hostdependency *this_hostdep return OK; /* add the host execution dependency */ - if(this_hostdependency->have_execution_dependency_options == TRUE) { + if(this_hostdependency->have_execution_failure_options == TRUE) { + xodcount.hostdependencies++; - new_hostdependency = add_host_dependency(this_hostdependency->dependent_host_name, this_hostdependency->host_name, EXECUTION_DEPENDENCY, this_hostdependency->inherits_parent, this_hostdependency->fail_execute_on_up, this_hostdependency->fail_execute_on_down, this_hostdependency->fail_execute_on_unreachable, this_hostdependency->fail_execute_on_pending, this_hostdependency->dependency_period); + new_hostdependency = add_host_dependency(this_hostdependency->dependent_host_name, this_hostdependency->host_name, EXECUTION_DEPENDENCY, this_hostdependency->inherits_parent, this_hostdependency->execution_failure_options, this_hostdependency->dependency_period); /* return with an error if we couldn't add the hostdependency */ if(new_hostdependency == NULL) { @@ -9128,9 +7845,10 @@ int xodtemplate_register_hostdependency(xodtemplate_hostdependency *this_hostdep } /* add the host notification dependency */ - if(this_hostdependency->have_notification_dependency_options == TRUE) { + if(this_hostdependency->have_notification_failure_options == TRUE) { + xodcount.hostdependencies++; - new_hostdependency = add_host_dependency(this_hostdependency->dependent_host_name, this_hostdependency->host_name, NOTIFICATION_DEPENDENCY, this_hostdependency->inherits_parent, this_hostdependency->fail_notify_on_up, this_hostdependency->fail_notify_on_down, this_hostdependency->fail_notify_on_unreachable, this_hostdependency->fail_notify_on_pending, this_hostdependency->dependency_period); + new_hostdependency = add_host_dependency(this_hostdependency->dependent_host_name, this_hostdependency->host_name, NOTIFICATION_DEPENDENCY, this_hostdependency->inherits_parent, this_hostdependency->notification_failure_options, this_hostdependency->dependency_period); /* return with an error if we couldn't add the hostdependency */ if(new_hostdependency == NULL) { @@ -9158,13 +7876,11 @@ int xodtemplate_register_hostescalation(xodtemplate_hostescalation *this_hostesc /* default options if none specified */ if(this_hostescalation->have_escalation_options == FALSE) { - this_hostescalation->escalate_on_down = TRUE; - this_hostescalation->escalate_on_unreachable = TRUE; - this_hostescalation->escalate_on_recovery = TRUE; + this_hostescalation->escalation_options = OPT_ALL; } /* add the hostescalation */ - new_hostescalation = add_hostescalation(this_hostescalation->host_name, this_hostescalation->first_notification, this_hostescalation->last_notification, this_hostescalation->notification_interval, this_hostescalation->escalation_period, this_hostescalation->escalate_on_down, this_hostescalation->escalate_on_unreachable, this_hostescalation->escalate_on_recovery); + new_hostescalation = add_hostescalation(this_hostescalation->host_name, this_hostescalation->first_notification, this_hostescalation->last_notification, this_hostescalation->notification_interval, this_hostescalation->escalation_period, this_hostescalation->escalation_options); /* return with an error if we couldn't add the hostescalation */ if(new_hostescalation == NULL) { @@ -9189,7 +7905,7 @@ int xodtemplate_register_hostescalation(xodtemplate_hostescalation *this_hostesc /* add the contacts */ if(this_hostescalation->contacts != NULL) { - for(contact_name = strtok(this_hostescalation->contacts, ","); contact_name != NULL; contact_name = strtok(NULL, ", ")) { + for(contact_name = strtok(this_hostescalation->contacts, ","); contact_name != NULL; contact_name = strtok(NULL, ",")) { strip(contact_name); new_contactsmember = add_contact_to_hostescalation(new_hostescalation, contact_name); @@ -9206,817 +7922,12 @@ int xodtemplate_register_hostescalation(xodtemplate_hostescalation *this_hostesc -/******************************************************************/ -/********************** SORTING FUNCTIONS *************************/ -/******************************************************************/ - -#ifdef NSCORE - -/* sorts all objects by name */ -int xodtemplate_sort_objects(void) { - - /* NOTE: with skiplists, we no longer need to sort things manually... */ - return OK; - - /* sort timeperiods */ - if(xodtemplate_sort_timeperiods() == ERROR) - return ERROR; - - /* sort commands */ - if(xodtemplate_sort_commands() == ERROR) - return ERROR; - - /* sort contactgroups */ - if(xodtemplate_sort_contactgroups() == ERROR) - return ERROR; - - /* sort hostgroups */ - if(xodtemplate_sort_hostgroups() == ERROR) - return ERROR; - - /* sort servicegroups */ - if(xodtemplate_sort_servicegroups() == ERROR) - return ERROR; - - /* sort contacts */ - if(xodtemplate_sort_contacts() == ERROR) - return ERROR; - - /* sort hosts */ - if(xodtemplate_sort_hosts() == ERROR) - return ERROR; - - /* sort services */ - if(xodtemplate_sort_services() == ERROR) - return ERROR; - - /* sort service dependencies */ - if(xodtemplate_sort_servicedependencies() == ERROR) - return ERROR; - - /* sort service escalations */ - if(xodtemplate_sort_serviceescalations() == ERROR) - return ERROR; - - /* sort host dependencies */ - if(xodtemplate_sort_hostdependencies() == ERROR) - return ERROR; - - /* sort hostescalations */ - if(xodtemplate_sort_hostescalations() == ERROR) - return ERROR; - - /* sort host extended info */ - /* NOT NEEDED */ - - /* sort service extended info */ - /* NOT NEEDED */ - - return OK; - } - - -/* used to compare two strings (object names) */ -int xodtemplate_compare_strings1(char *string1, char *string2) { - - if(string1 == NULL && string2 == NULL) - return 0; - else if(string1 == NULL) - return -1; - else if(string2 == NULL) - return 1; - else - return strcmp(string1, string2); - } - - -/* used to compare two sets of strings (dually-named objects, i.e. services) */ -int xodtemplate_compare_strings2(char *string1a, char *string1b, char *string2a, char *string2b) { - int result; - - if((result = xodtemplate_compare_strings1(string1a, string2a)) == 0) - result = xodtemplate_compare_strings1(string1b, string2b); - - return result; - } - - -/* sort timeperiods by name */ -int xodtemplate_sort_timeperiods() { - xodtemplate_timeperiod *new_timeperiod_list = NULL; - xodtemplate_timeperiod *temp_timeperiod = NULL; - xodtemplate_timeperiod *last_timeperiod = NULL; - xodtemplate_timeperiod *temp_timeperiod_orig = NULL; - xodtemplate_timeperiod *next_timeperiod_orig = NULL; - - /* sort all existing timeperiods */ - for(temp_timeperiod_orig = xodtemplate_timeperiod_list; temp_timeperiod_orig != NULL; temp_timeperiod_orig = next_timeperiod_orig) { - - next_timeperiod_orig = temp_timeperiod_orig->next; - - /* add timeperiod to new list, sorted by timeperiod name */ - last_timeperiod = new_timeperiod_list; - for(temp_timeperiod = new_timeperiod_list; temp_timeperiod != NULL; temp_timeperiod = temp_timeperiod->next) { - - if(xodtemplate_compare_strings1(temp_timeperiod_orig->timeperiod_name, temp_timeperiod->timeperiod_name) <= 0) - break; - else - last_timeperiod = temp_timeperiod; - } - - /* first item added to new sorted list */ - if(new_timeperiod_list == NULL) { - temp_timeperiod_orig->next = NULL; - new_timeperiod_list = temp_timeperiod_orig; - } - - /* item goes at head of new sorted list */ - else if(temp_timeperiod == new_timeperiod_list) { - temp_timeperiod_orig->next = new_timeperiod_list; - new_timeperiod_list = temp_timeperiod_orig; - } - - /* item goes in middle or at end of new sorted list */ - else { - temp_timeperiod_orig->next = temp_timeperiod; - last_timeperiod->next = temp_timeperiod_orig; - } - } - - /* list is now sorted */ - xodtemplate_timeperiod_list = new_timeperiod_list; - - return OK; - } - - -/* sort commands by name */ -int xodtemplate_sort_commands() { - xodtemplate_command *new_command_list = NULL; - xodtemplate_command *temp_command = NULL; - xodtemplate_command *last_command = NULL; - xodtemplate_command *temp_command_orig = NULL; - xodtemplate_command *next_command_orig = NULL; - - /* sort all existing commands */ - for(temp_command_orig = xodtemplate_command_list; temp_command_orig != NULL; temp_command_orig = next_command_orig) { - - next_command_orig = temp_command_orig->next; - - /* add command to new list, sorted by command name */ - last_command = new_command_list; - for(temp_command = new_command_list; temp_command != NULL; temp_command = temp_command->next) { - - if(xodtemplate_compare_strings1(temp_command_orig->command_name, temp_command->command_name) <= 0) - break; - else - last_command = temp_command; - } - - /* first item added to new sorted list */ - if(new_command_list == NULL) { - temp_command_orig->next = NULL; - new_command_list = temp_command_orig; - } - - /* item goes at head of new sorted list */ - else if(temp_command == new_command_list) { - temp_command_orig->next = new_command_list; - new_command_list = temp_command_orig; - } - - /* item goes in middle or at end of new sorted list */ - else { - temp_command_orig->next = temp_command; - last_command->next = temp_command_orig; - } - } - - /* list is now sorted */ - xodtemplate_command_list = new_command_list; - - return OK; - } - - -/* sort contactgroups by name */ -int xodtemplate_sort_contactgroups() { - xodtemplate_contactgroup *new_contactgroup_list = NULL; - xodtemplate_contactgroup *temp_contactgroup = NULL; - xodtemplate_contactgroup *last_contactgroup = NULL; - xodtemplate_contactgroup *temp_contactgroup_orig = NULL; - xodtemplate_contactgroup *next_contactgroup_orig = NULL; - - /* sort all existing contactgroups */ - for(temp_contactgroup_orig = xodtemplate_contactgroup_list; temp_contactgroup_orig != NULL; temp_contactgroup_orig = next_contactgroup_orig) { - - next_contactgroup_orig = temp_contactgroup_orig->next; - - /* add contactgroup to new list, sorted by contactgroup name */ - last_contactgroup = new_contactgroup_list; - for(temp_contactgroup = new_contactgroup_list; temp_contactgroup != NULL; temp_contactgroup = temp_contactgroup->next) { - - if(xodtemplate_compare_strings1(temp_contactgroup_orig->contactgroup_name, temp_contactgroup->contactgroup_name) <= 0) - break; - else - last_contactgroup = temp_contactgroup; - } - - /* first item added to new sorted list */ - if(new_contactgroup_list == NULL) { - temp_contactgroup_orig->next = NULL; - new_contactgroup_list = temp_contactgroup_orig; - } - - /* item goes at head of new sorted list */ - else if(temp_contactgroup == new_contactgroup_list) { - temp_contactgroup_orig->next = new_contactgroup_list; - new_contactgroup_list = temp_contactgroup_orig; - } - - /* item goes in middle or at end of new sorted list */ - else { - temp_contactgroup_orig->next = temp_contactgroup; - last_contactgroup->next = temp_contactgroup_orig; - } - } - - /* list is now sorted */ - xodtemplate_contactgroup_list = new_contactgroup_list; - - return OK; - } - - -/* sort hostgroups by name */ -int xodtemplate_sort_hostgroups() { - xodtemplate_hostgroup *new_hostgroup_list = NULL; - xodtemplate_hostgroup *temp_hostgroup = NULL; - xodtemplate_hostgroup *last_hostgroup = NULL; - xodtemplate_hostgroup *temp_hostgroup_orig = NULL; - xodtemplate_hostgroup *next_hostgroup_orig = NULL; - - /* sort all existing hostgroups */ - for(temp_hostgroup_orig = xodtemplate_hostgroup_list; temp_hostgroup_orig != NULL; temp_hostgroup_orig = next_hostgroup_orig) { - - next_hostgroup_orig = temp_hostgroup_orig->next; - - /* add hostgroup to new list, sorted by hostgroup name */ - last_hostgroup = new_hostgroup_list; - for(temp_hostgroup = new_hostgroup_list; temp_hostgroup != NULL; temp_hostgroup = temp_hostgroup->next) { - - if(xodtemplate_compare_strings1(temp_hostgroup_orig->hostgroup_name, temp_hostgroup->hostgroup_name) <= 0) - break; - else - last_hostgroup = temp_hostgroup; - } - - /* first item added to new sorted list */ - if(new_hostgroup_list == NULL) { - temp_hostgroup_orig->next = NULL; - new_hostgroup_list = temp_hostgroup_orig; - } - - /* item goes at head of new sorted list */ - else if(temp_hostgroup == new_hostgroup_list) { - temp_hostgroup_orig->next = new_hostgroup_list; - new_hostgroup_list = temp_hostgroup_orig; - } - - /* item goes in middle or at end of new sorted list */ - else { - temp_hostgroup_orig->next = temp_hostgroup; - last_hostgroup->next = temp_hostgroup_orig; - } - } - - /* list is now sorted */ - xodtemplate_hostgroup_list = new_hostgroup_list; - - return OK; - } - - -/* sort servicegroups by name */ -int xodtemplate_sort_servicegroups() { - xodtemplate_servicegroup *new_servicegroup_list = NULL; - xodtemplate_servicegroup *temp_servicegroup = NULL; - xodtemplate_servicegroup *last_servicegroup = NULL; - xodtemplate_servicegroup *temp_servicegroup_orig = NULL; - xodtemplate_servicegroup *next_servicegroup_orig = NULL; - - /* sort all existing servicegroups */ - for(temp_servicegroup_orig = xodtemplate_servicegroup_list; temp_servicegroup_orig != NULL; temp_servicegroup_orig = next_servicegroup_orig) { - - next_servicegroup_orig = temp_servicegroup_orig->next; - - /* add servicegroup to new list, sorted by servicegroup name */ - last_servicegroup = new_servicegroup_list; - for(temp_servicegroup = new_servicegroup_list; temp_servicegroup != NULL; temp_servicegroup = temp_servicegroup->next) { - - if(xodtemplate_compare_strings1(temp_servicegroup_orig->servicegroup_name, temp_servicegroup->servicegroup_name) <= 0) - break; - else - last_servicegroup = temp_servicegroup; - } - - /* first item added to new sorted list */ - if(new_servicegroup_list == NULL) { - temp_servicegroup_orig->next = NULL; - new_servicegroup_list = temp_servicegroup_orig; - } - - /* item goes at head of new sorted list */ - else if(temp_servicegroup == new_servicegroup_list) { - temp_servicegroup_orig->next = new_servicegroup_list; - new_servicegroup_list = temp_servicegroup_orig; - } - - /* item goes in middle or at end of new sorted list */ - else { - temp_servicegroup_orig->next = temp_servicegroup; - last_servicegroup->next = temp_servicegroup_orig; - } - } - - /* list is now sorted */ - xodtemplate_servicegroup_list = new_servicegroup_list; - - return OK; - } - - -/* sort contacts by name */ -int xodtemplate_sort_contacts() { - xodtemplate_contact *new_contact_list = NULL; - xodtemplate_contact *temp_contact = NULL; - xodtemplate_contact *last_contact = NULL; - xodtemplate_contact *temp_contact_orig = NULL; - xodtemplate_contact *next_contact_orig = NULL; - - /* sort all existing contacts */ - for(temp_contact_orig = xodtemplate_contact_list; temp_contact_orig != NULL; temp_contact_orig = next_contact_orig) { - - next_contact_orig = temp_contact_orig->next; - - /* add contact to new list, sorted by contact name */ - last_contact = new_contact_list; - for(temp_contact = new_contact_list; temp_contact != NULL; temp_contact = temp_contact->next) { - - if(xodtemplate_compare_strings1(temp_contact_orig->contact_name, temp_contact->contact_name) <= 0) - break; - else - last_contact = temp_contact; - } - - /* first item added to new sorted list */ - if(new_contact_list == NULL) { - temp_contact_orig->next = NULL; - new_contact_list = temp_contact_orig; - } - - /* item goes at head of new sorted list */ - else if(temp_contact == new_contact_list) { - temp_contact_orig->next = new_contact_list; - new_contact_list = temp_contact_orig; - } - - /* item goes in middle or at end of new sorted list */ - else { - temp_contact_orig->next = temp_contact; - last_contact->next = temp_contact_orig; - } - } - - /* list is now sorted */ - xodtemplate_contact_list = new_contact_list; - - return OK; - } - - -int xodtemplate_compare_host(void *arg1, void *arg2) { - xodtemplate_host *h1 = NULL; - xodtemplate_host *h2 = NULL; - int x = 0; - - h1 = (xodtemplate_host *)arg1; - h2 = (xodtemplate_host *)arg2; - - if(h1 == NULL && h2 == NULL) - return 0; - if(h1 == NULL) - return 1; - if(h2 == NULL) - return -1; - - x = strcmp((h1->host_name == NULL) ? "" : h1->host_name, (h2->host_name == NULL) ? "" : h2->host_name); - - return x; - } - - - -/* sort hosts by name */ -int xodtemplate_sort_hosts() { -#ifdef NEWSTUFF - xodtemplate_host *temp_host = NULL; - - /* initialize a new skip list */ - if((xodtemplate_host_skiplist = skiplist_new(15, 0.5, FALSE, xodtemplate_compare_host)) == NULL) - return ERROR; - - /* add all hosts to skip list */ - for(temp_host = xodtemplate_host_list; temp_host != NULL; temp_host = temp_host->next) - skiplist_insert(xodtemplate_host_skiplist, temp_host); - /*printf("SKIPLIST ITEMS: %lu\n",xodtemplate_host_skiplist->items);*/ - - /* now move items from skiplist to linked list... */ - /* TODO */ -#endif - - xodtemplate_host *new_host_list = NULL; - xodtemplate_host *temp_host = NULL; - xodtemplate_host *last_host = NULL; - xodtemplate_host *temp_host_orig = NULL; - xodtemplate_host *next_host_orig = NULL; - - /* sort all existing hosts */ - for(temp_host_orig = xodtemplate_host_list; temp_host_orig != NULL; temp_host_orig = next_host_orig) { - - next_host_orig = temp_host_orig->next; - - /* add host to new list, sorted by host name */ - last_host = new_host_list; - for(temp_host = new_host_list; temp_host != NULL; temp_host = temp_host->next) { - - if(xodtemplate_compare_strings1(temp_host_orig->host_name, temp_host->host_name) <= 0) - break; - else - last_host = temp_host; - } - - /* first item added to new sorted list */ - if(new_host_list == NULL) { - temp_host_orig->next = NULL; - new_host_list = temp_host_orig; - } - - /* item goes at head of new sorted list */ - else if(temp_host == new_host_list) { - temp_host_orig->next = new_host_list; - new_host_list = temp_host_orig; - } - - /* item goes in middle or at end of new sorted list */ - else { - temp_host_orig->next = temp_host; - last_host->next = temp_host_orig; - } - } - - /* list is now sorted */ - xodtemplate_host_list = new_host_list; - - return OK; - } - - -int xodtemplate_compare_service(void *arg1, void *arg2) { - xodtemplate_service *s1 = NULL; - xodtemplate_service *s2 = NULL; - int x = 0; - - s1 = (xodtemplate_service *)arg1; - s2 = (xodtemplate_service *)arg2; - - if(s1 == NULL && s2 == NULL) - return 0; - if(s1 == NULL) - return 1; - if(s2 == NULL) - return -1; - - x = strcmp((s1->host_name == NULL) ? "" : s1->host_name, (s2->host_name == NULL) ? "" : s2->host_name); - if(x == 0) - x = strcmp((s1->service_description == NULL) ? "" : s1->service_description, (s2->service_description == NULL) ? "" : s2->service_description); - - return x; - } - - -/* sort services by name */ -int xodtemplate_sort_services() { -#ifdef NEWSTUFF - xodtemplate_service *temp_service = NULL; - - /* initialize a new skip list */ - if((xodtemplate_service_skiplist = skiplist_new(15, 0.5, FALSE, xodtemplate_compare_service)) == NULL) - return ERROR; - - /* add all services to skip list */ - for(temp_service = xodtemplate_service_list; temp_service != NULL; temp_service = temp_service->next) - skiplist_insert(xodtemplate_service_skiplist, temp_service); - /*printf("SKIPLIST ITEMS: %lu\n",xodtemplate_service_skiplist->items);*/ - - /* now move items to linked list... */ - /* TODO */ -#endif - - xodtemplate_service *new_service_list = NULL; - xodtemplate_service *temp_service = NULL; - xodtemplate_service *last_service = NULL; - xodtemplate_service *temp_service_orig = NULL; - xodtemplate_service *next_service_orig = NULL; - - /* sort all existing services */ - for(temp_service_orig = xodtemplate_service_list; temp_service_orig != NULL; temp_service_orig = next_service_orig) { - - next_service_orig = temp_service_orig->next; - - /* add service to new list, sorted by host name then service description */ - last_service = new_service_list; - for(temp_service = new_service_list; temp_service != NULL; temp_service = temp_service->next) { - - if(xodtemplate_compare_strings2(temp_service_orig->host_name, temp_service_orig->service_description, temp_service->host_name, temp_service->service_description) <= 0) - break; - else - last_service = temp_service; - } - - /* first item added to new sorted list */ - if(new_service_list == NULL) { - temp_service_orig->next = NULL; - new_service_list = temp_service_orig; - } - - /* item goes at head of new sorted list */ - else if(temp_service == new_service_list) { - temp_service_orig->next = new_service_list; - new_service_list = temp_service_orig; - } - - /* item goes in middle or at end of new sorted list */ - else { - temp_service_orig->next = temp_service; - last_service->next = temp_service_orig; - } - } - - /* list is now sorted */ - xodtemplate_service_list = new_service_list; - - return OK; - } - - -/* sort servicedependencies by name */ -int xodtemplate_sort_servicedependencies() { - xodtemplate_servicedependency *new_servicedependency_list = NULL; - xodtemplate_servicedependency *temp_servicedependency = NULL; - xodtemplate_servicedependency *last_servicedependency = NULL; - xodtemplate_servicedependency *temp_servicedependency_orig = NULL; - xodtemplate_servicedependency *next_servicedependency_orig = NULL; - - /* sort all existing servicedependencies */ - for(temp_servicedependency_orig = xodtemplate_servicedependency_list; temp_servicedependency_orig != NULL; temp_servicedependency_orig = next_servicedependency_orig) { - - next_servicedependency_orig = temp_servicedependency_orig->next; - - /* add servicedependency to new list, sorted by host name then service description */ - last_servicedependency = new_servicedependency_list; - for(temp_servicedependency = new_servicedependency_list; temp_servicedependency != NULL; temp_servicedependency = temp_servicedependency->next) { - - if(xodtemplate_compare_strings2(temp_servicedependency_orig->host_name, temp_servicedependency_orig->service_description, temp_servicedependency->host_name, temp_servicedependency->service_description) <= 0) - break; - else - last_servicedependency = temp_servicedependency; - } - - /* first item added to new sorted list */ - if(new_servicedependency_list == NULL) { - temp_servicedependency_orig->next = NULL; - new_servicedependency_list = temp_servicedependency_orig; - } - - /* item goes at head of new sorted list */ - else if(temp_servicedependency == new_servicedependency_list) { - temp_servicedependency_orig->next = new_servicedependency_list; - new_servicedependency_list = temp_servicedependency_orig; - } - - /* item goes in middle or at end of new sorted list */ - else { - temp_servicedependency_orig->next = temp_servicedependency; - last_servicedependency->next = temp_servicedependency_orig; - } - } - - /* list is now sorted */ - xodtemplate_servicedependency_list = new_servicedependency_list; - - return OK; - } - - -/* sort serviceescalations by name */ -int xodtemplate_sort_serviceescalations() { - xodtemplate_serviceescalation *new_serviceescalation_list = NULL; - xodtemplate_serviceescalation *temp_serviceescalation = NULL; - xodtemplate_serviceescalation *last_serviceescalation = NULL; - xodtemplate_serviceescalation *temp_serviceescalation_orig = NULL; - xodtemplate_serviceescalation *next_serviceescalation_orig = NULL; - - /* sort all existing serviceescalations */ - for(temp_serviceescalation_orig = xodtemplate_serviceescalation_list; temp_serviceescalation_orig != NULL; temp_serviceescalation_orig = next_serviceescalation_orig) { - - next_serviceescalation_orig = temp_serviceescalation_orig->next; - - /* add serviceescalation to new list, sorted by host name then service description */ - last_serviceescalation = new_serviceescalation_list; - for(temp_serviceescalation = new_serviceescalation_list; temp_serviceescalation != NULL; temp_serviceescalation = temp_serviceescalation->next) { - - if(xodtemplate_compare_strings2(temp_serviceescalation_orig->host_name, temp_serviceescalation_orig->service_description, temp_serviceescalation->host_name, temp_serviceescalation->service_description) <= 0) - break; - else - last_serviceescalation = temp_serviceescalation; - } - - /* first item added to new sorted list */ - if(new_serviceescalation_list == NULL) { - temp_serviceescalation_orig->next = NULL; - new_serviceescalation_list = temp_serviceescalation_orig; - } - - /* item goes at head of new sorted list */ - else if(temp_serviceescalation == new_serviceescalation_list) { - temp_serviceescalation_orig->next = new_serviceescalation_list; - new_serviceescalation_list = temp_serviceescalation_orig; - } - - /* item goes in middle or at end of new sorted list */ - else { - temp_serviceescalation_orig->next = temp_serviceescalation; - last_serviceescalation->next = temp_serviceescalation_orig; - } - } - - /* list is now sorted */ - xodtemplate_serviceescalation_list = new_serviceescalation_list; - - return OK; - } - - -/* sort hostescalations by name */ -int xodtemplate_sort_hostescalations() { - xodtemplate_hostescalation *new_hostescalation_list = NULL; - xodtemplate_hostescalation *temp_hostescalation = NULL; - xodtemplate_hostescalation *last_hostescalation = NULL; - xodtemplate_hostescalation *temp_hostescalation_orig = NULL; - xodtemplate_hostescalation *next_hostescalation_orig = NULL; - - /* sort all existing hostescalations */ - for(temp_hostescalation_orig = xodtemplate_hostescalation_list; temp_hostescalation_orig != NULL; temp_hostescalation_orig = next_hostescalation_orig) { - - next_hostescalation_orig = temp_hostescalation_orig->next; - - /* add hostescalation to new list, sorted by host name then hostescalation description */ - last_hostescalation = new_hostescalation_list; - for(temp_hostescalation = new_hostescalation_list; temp_hostescalation != NULL; temp_hostescalation = temp_hostescalation->next) { - - if(xodtemplate_compare_strings1(temp_hostescalation_orig->host_name, temp_hostescalation->host_name) <= 0) - break; - else - last_hostescalation = temp_hostescalation; - } - - /* first item added to new sorted list */ - if(new_hostescalation_list == NULL) { - temp_hostescalation_orig->next = NULL; - new_hostescalation_list = temp_hostescalation_orig; - } - - /* item goes at head of new sorted list */ - else if(temp_hostescalation == new_hostescalation_list) { - temp_hostescalation_orig->next = new_hostescalation_list; - new_hostescalation_list = temp_hostescalation_orig; - } - - /* item goes in middle or at end of new sorted list */ - else { - temp_hostescalation_orig->next = temp_hostescalation; - last_hostescalation->next = temp_hostescalation_orig; - } - } - - /* list is now sorted */ - xodtemplate_hostescalation_list = new_hostescalation_list; - - return OK; - } - - -/* sort hostdependencies by name */ -int xodtemplate_sort_hostdependencies() { - xodtemplate_hostdependency *new_hostdependency_list = NULL; - xodtemplate_hostdependency *temp_hostdependency = NULL; - xodtemplate_hostdependency *last_hostdependency = NULL; - xodtemplate_hostdependency *temp_hostdependency_orig = NULL; - xodtemplate_hostdependency *next_hostdependency_orig = NULL; - - /* sort all existing hostdependencys */ - for(temp_hostdependency_orig = xodtemplate_hostdependency_list; temp_hostdependency_orig != NULL; temp_hostdependency_orig = next_hostdependency_orig) { - - next_hostdependency_orig = temp_hostdependency_orig->next; - - /* add hostdependency to new list, sorted by host name then hostdependency description */ - last_hostdependency = new_hostdependency_list; - for(temp_hostdependency = new_hostdependency_list; temp_hostdependency != NULL; temp_hostdependency = temp_hostdependency->next) { - - if(xodtemplate_compare_strings1(temp_hostdependency_orig->host_name, temp_hostdependency->host_name) <= 0) - break; - else - last_hostdependency = temp_hostdependency; - } - - /* first item added to new sorted list */ - if(new_hostdependency_list == NULL) { - temp_hostdependency_orig->next = NULL; - new_hostdependency_list = temp_hostdependency_orig; - } - - /* item goes at head of new sorted list */ - else if(temp_hostdependency == new_hostdependency_list) { - temp_hostdependency_orig->next = new_hostdependency_list; - new_hostdependency_list = temp_hostdependency_orig; - } - - /* item goes in middle or at end of new sorted list */ - else { - temp_hostdependency_orig->next = temp_hostdependency; - last_hostdependency->next = temp_hostdependency_orig; - } - } - - /* list is now sorted */ - xodtemplate_hostdependency_list = new_hostdependency_list; - - return OK; - } - -#endif - - - - /******************************************************************/ /*********************** MERGE FUNCTIONS **************************/ /******************************************************************/ #ifdef NSCORE -/* merge extinfo definitions */ -int xodtemplate_merge_extinfo_ojects(void) { - xodtemplate_hostextinfo *temp_hostextinfo = NULL; - xodtemplate_serviceextinfo *temp_serviceextinfo = NULL; - xodtemplate_host *temp_host = NULL; - xodtemplate_service *temp_service = NULL; - - /* merge service extinfo definitions */ - for(temp_serviceextinfo = xodtemplate_serviceextinfo_list; temp_serviceextinfo != NULL; temp_serviceextinfo = temp_serviceextinfo->next) { - - /* make sure we have everything */ - if(temp_serviceextinfo->host_name == NULL || temp_serviceextinfo->service_description == NULL) - continue; - - /* find the service */ - if((temp_service = xodtemplate_find_real_service(temp_serviceextinfo->host_name, temp_serviceextinfo->service_description)) == NULL) - continue; - - /* merge the definitions */ - xodtemplate_merge_service_extinfo_object(temp_service, temp_serviceextinfo); - } - - /* merge host extinfo definitions */ - for(temp_hostextinfo = xodtemplate_hostextinfo_list; temp_hostextinfo != NULL; temp_hostextinfo = temp_hostextinfo->next) { - - /* make sure we have everything */ - if(temp_hostextinfo->host_name == NULL) - continue; - - /* find the host */ - if((temp_host = xodtemplate_find_real_host(temp_hostextinfo->host_name)) == NULL) - continue; - - /* merge the definitions */ - xodtemplate_merge_host_extinfo_object(temp_host, temp_hostextinfo); - } - - return OK; - } - - /* merges a service extinfo definition */ int xodtemplate_merge_service_extinfo_object(xodtemplate_service *this_service, xodtemplate_serviceextinfo *this_serviceextinfo) { @@ -10077,708 +7988,6 @@ int xodtemplate_merge_host_extinfo_object(xodtemplate_host *this_host, xodtempla #endif - -/******************************************************************/ -/*********************** CACHE FUNCTIONS **************************/ -/******************************************************************/ - -#ifdef NSCORE - -/* writes cached object definitions for use by web interface */ -int xodtemplate_cache_objects(char *cache_file) { - FILE *fp = NULL; - register int x = 0; - char *days[7] = {"sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"}; - char *months[12] = {"january", "february", "march", "april", "may", "june", "july", "august", "september", "october", "november", "december"}; - xodtemplate_timeperiod *temp_timeperiod = NULL; - xodtemplate_daterange *temp_daterange = NULL; - xodtemplate_command *temp_command = NULL; - xodtemplate_contactgroup *temp_contactgroup = NULL; - xodtemplate_hostgroup *temp_hostgroup = NULL; - xodtemplate_servicegroup *temp_servicegroup = NULL; - xodtemplate_contact *temp_contact = NULL; - xodtemplate_host *temp_host = NULL; - xodtemplate_service *temp_service = NULL; - xodtemplate_servicedependency *temp_servicedependency = NULL; - xodtemplate_serviceescalation *temp_serviceescalation = NULL; - xodtemplate_hostdependency *temp_hostdependency = NULL; - xodtemplate_hostescalation *temp_hostescalation = NULL; - xodtemplate_customvariablesmember *temp_customvariablesmember = NULL; - time_t current_time = 0L; - void *ptr = NULL; - - - time(¤t_time); - - /* open the cache file for writing */ - fp = fopen(cache_file, "w"); - if(fp == NULL) { - logit(NSLOG_CONFIG_WARNING, TRUE, "Warning: Could not open object cache file '%s' for writing!\n", cache_file); - return ERROR; - } - - /* write header to cache file */ - fprintf(fp, "########################################\n"); - fprintf(fp, "# NAGIOS OBJECT CACHE 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"); - fprintf(fp, "# Created: %s", ctime(¤t_time)); - fprintf(fp, "########################################\n\n"); - - - /* cache timeperiods */ - /*for(temp_timeperiod=xodtemplate_timeperiod_list;temp_timeperiod!=NULL;temp_timeperiod=temp_timeperiod->next){*/ - ptr = NULL; - for(temp_timeperiod = (xodtemplate_timeperiod *)skiplist_get_first(xobject_skiplists[X_TIMEPERIOD_SKIPLIST], &ptr); temp_timeperiod != NULL; temp_timeperiod = (xodtemplate_timeperiod *)skiplist_get_next(&ptr)) { - - if(temp_timeperiod->register_object == FALSE) - continue; - fprintf(fp, "define timeperiod {\n"); - if(temp_timeperiod->timeperiod_name) - fprintf(fp, "\ttimeperiod_name\t%s\n", temp_timeperiod->timeperiod_name); - if(temp_timeperiod->alias) - fprintf(fp, "\talias\t%s\n", temp_timeperiod->alias); - for(x = 0; x < DATERANGE_TYPES; x++) { - for(temp_daterange = temp_timeperiod->exceptions[x]; temp_daterange != NULL; temp_daterange = temp_daterange->next) { - - /* skip null entries */ - if(temp_daterange->timeranges == NULL || !strcmp(temp_daterange->timeranges, XODTEMPLATE_NULL)) - continue; - - switch(temp_daterange->type) { - case DATERANGE_CALENDAR_DATE: - fprintf(fp, "\t%d-%02d-%02d", temp_daterange->syear, temp_daterange->smon + 1, temp_daterange->smday); - if((temp_daterange->smday != temp_daterange->emday) || (temp_daterange->smon != temp_daterange->emon) || (temp_daterange->syear != temp_daterange->eyear)) - fprintf(fp, " - %d-%02d-%02d", temp_daterange->eyear, temp_daterange->emon + 1, temp_daterange->emday); - if(temp_daterange->skip_interval > 1) - fprintf(fp, " / %d", temp_daterange->skip_interval); - break; - case DATERANGE_MONTH_DATE: - fprintf(fp, "\t%s %d", months[temp_daterange->smon], temp_daterange->smday); - if((temp_daterange->smon != temp_daterange->emon) || (temp_daterange->smday != temp_daterange->emday)) { - fprintf(fp, " - %s %d", months[temp_daterange->emon], temp_daterange->emday); - if(temp_daterange->skip_interval > 1) - fprintf(fp, " / %d", temp_daterange->skip_interval); - } - break; - case DATERANGE_MONTH_DAY: - fprintf(fp, "\tday %d", temp_daterange->smday); - if(temp_daterange->smday != temp_daterange->emday) { - fprintf(fp, " - %d", temp_daterange->emday); - if(temp_daterange->skip_interval > 1) - fprintf(fp, " / %d", temp_daterange->skip_interval); - } - break; - case DATERANGE_MONTH_WEEK_DAY: - fprintf(fp, "\t%s %d %s", days[temp_daterange->swday], temp_daterange->swday_offset, months[temp_daterange->smon]); - if((temp_daterange->smon != temp_daterange->emon) || (temp_daterange->swday != temp_daterange->ewday) || (temp_daterange->swday_offset != temp_daterange->ewday_offset)) { - fprintf(fp, " - %s %d %s", days[temp_daterange->ewday], temp_daterange->ewday_offset, months[temp_daterange->emon]); - if(temp_daterange->skip_interval > 1) - fprintf(fp, " / %d", temp_daterange->skip_interval); - } - break; - case DATERANGE_WEEK_DAY: - fprintf(fp, "\t%s %d", days[temp_daterange->swday], temp_daterange->swday_offset); - if((temp_daterange->swday != temp_daterange->ewday) || (temp_daterange->swday_offset != temp_daterange->ewday_offset)) { - fprintf(fp, " - %s %d", days[temp_daterange->ewday], temp_daterange->ewday_offset); - if(temp_daterange->skip_interval > 1) - fprintf(fp, " / %d", temp_daterange->skip_interval); - } - break; - default: - break; - } - - fprintf(fp, "\t%s\n", temp_daterange->timeranges); - } - } - for(x = 0; x < 7; x++) { - /* skip null entries */ - if(temp_timeperiod->timeranges[x] == NULL || !strcmp(temp_timeperiod->timeranges[x], XODTEMPLATE_NULL)) - continue; - - fprintf(fp, "\t%s\t%s\n", days[x], temp_timeperiod->timeranges[x]); - } - if(temp_timeperiod->exclusions) - fprintf(fp, "\texclude\t%s\n", temp_timeperiod->exclusions); - fprintf(fp, "\t}\n\n"); - } - - /* cache commands */ - /*for(temp_command=xodtemplate_command_list;temp_command!=NULL;temp_command=temp_command->next){*/ - ptr = NULL; - for(temp_command = (xodtemplate_command *)skiplist_get_first(xobject_skiplists[X_COMMAND_SKIPLIST], &ptr); temp_command != NULL; temp_command = (xodtemplate_command *)skiplist_get_next(&ptr)) { - if(temp_command->register_object == FALSE) - continue; - fprintf(fp, "define command {\n"); - if(temp_command->command_name) - fprintf(fp, "\tcommand_name\t%s\n", temp_command->command_name); - if(temp_command->command_line) - fprintf(fp, "\tcommand_line\t%s\n", temp_command->command_line); - fprintf(fp, "\t}\n\n"); - } - - /* cache contactgroups */ - /*for(temp_contactgroup=xodtemplate_contactgroup_list;temp_contactgroup!=NULL;temp_contactgroup=temp_contactgroup->next){*/ - ptr = NULL; - for(temp_contactgroup = (xodtemplate_contactgroup *)skiplist_get_first(xobject_skiplists[X_CONTACTGROUP_SKIPLIST], &ptr); temp_contactgroup != NULL; temp_contactgroup = (xodtemplate_contactgroup *)skiplist_get_next(&ptr)) { - if(temp_contactgroup->register_object == FALSE) - continue; - fprintf(fp, "define contactgroup {\n"); - if(temp_contactgroup->contactgroup_name) - fprintf(fp, "\tcontactgroup_name\t%s\n", temp_contactgroup->contactgroup_name); - if(temp_contactgroup->alias) - fprintf(fp, "\talias\t%s\n", temp_contactgroup->alias); - if(temp_contactgroup->members) - fprintf(fp, "\tmembers\t%s\n", temp_contactgroup->members); - fprintf(fp, "\t}\n\n"); - } - - /* cache hostgroups */ - /*for(temp_hostgroup=xodtemplate_hostgroup_list;temp_hostgroup!=NULL;temp_hostgroup=temp_hostgroup->next){*/ - ptr = NULL; - for(temp_hostgroup = (xodtemplate_hostgroup *)skiplist_get_first(xobject_skiplists[X_HOSTGROUP_SKIPLIST], &ptr); temp_hostgroup != NULL; temp_hostgroup = (xodtemplate_hostgroup *)skiplist_get_next(&ptr)) { - if(temp_hostgroup->register_object == FALSE) - continue; - fprintf(fp, "define hostgroup {\n"); - if(temp_hostgroup->hostgroup_name) - fprintf(fp, "\thostgroup_name\t%s\n", temp_hostgroup->hostgroup_name); - if(temp_hostgroup->alias) - fprintf(fp, "\talias\t%s\n", temp_hostgroup->alias); - if(temp_hostgroup->members) - fprintf(fp, "\tmembers\t%s\n", temp_hostgroup->members); - if(temp_hostgroup->notes) - fprintf(fp, "\tnotes\t%s\n", temp_hostgroup->notes); - if(temp_hostgroup->notes_url) - fprintf(fp, "\tnotes_url\t%s\n", temp_hostgroup->notes_url); - if(temp_hostgroup->action_url) - fprintf(fp, "\taction_url\t%s\n", temp_hostgroup->action_url); - fprintf(fp, "\t}\n\n"); - } - - /* cache servicegroups */ - /*for(temp_servicegroup=xodtemplate_servicegroup_list;temp_servicegroup!=NULL;temp_servicegroup=temp_servicegroup->next){*/ - ptr = NULL; - for(temp_servicegroup = (xodtemplate_servicegroup *)skiplist_get_first(xobject_skiplists[X_SERVICEGROUP_SKIPLIST], &ptr); temp_servicegroup != NULL; temp_servicegroup = (xodtemplate_servicegroup *)skiplist_get_next(&ptr)) { - if(temp_servicegroup->register_object == FALSE) - continue; - fprintf(fp, "define servicegroup {\n"); - if(temp_servicegroup->servicegroup_name) - fprintf(fp, "\tservicegroup_name\t%s\n", temp_servicegroup->servicegroup_name); - if(temp_servicegroup->alias) - fprintf(fp, "\talias\t%s\n", temp_servicegroup->alias); - if(temp_servicegroup->members) - fprintf(fp, "\tmembers\t%s\n", temp_servicegroup->members); - if(temp_servicegroup->notes) - fprintf(fp, "\tnotes\t%s\n", temp_servicegroup->notes); - if(temp_servicegroup->notes_url) - fprintf(fp, "\tnotes_url\t%s\n", temp_servicegroup->notes_url); - if(temp_servicegroup->action_url) - fprintf(fp, "\taction_url\t%s\n", temp_servicegroup->action_url); - fprintf(fp, "\t}\n\n"); - } - - /* cache contacts */ - /*for(temp_contact=xodtemplate_contact_list;temp_contact!=NULL;temp_contact=temp_contact->next){*/ - ptr = NULL; - for(temp_contact = (xodtemplate_contact *)skiplist_get_first(xobject_skiplists[X_CONTACT_SKIPLIST], &ptr); temp_contact != NULL; temp_contact = (xodtemplate_contact *)skiplist_get_next(&ptr)) { - if(temp_contact->register_object == FALSE) - continue; - fprintf(fp, "define contact {\n"); - if(temp_contact->contact_name) - fprintf(fp, "\tcontact_name\t%s\n", temp_contact->contact_name); - if(temp_contact->alias) - fprintf(fp, "\talias\t%s\n", temp_contact->alias); - if(temp_contact->service_notification_period) - fprintf(fp, "\tservice_notification_period\t%s\n", temp_contact->service_notification_period); - if(temp_contact->host_notification_period) - fprintf(fp, "\thost_notification_period\t%s\n", temp_contact->host_notification_period); - fprintf(fp, "\tservice_notification_options\t"); - x = 0; - if(temp_contact->notify_on_service_warning == TRUE) - fprintf(fp, "%sw", (x++ > 0) ? "," : ""); - if(temp_contact->notify_on_service_unknown == TRUE) - fprintf(fp, "%su", (x++ > 0) ? "," : ""); - if(temp_contact->notify_on_service_critical == TRUE) - fprintf(fp, "%sc", (x++ > 0) ? "," : ""); - if(temp_contact->notify_on_service_recovery == TRUE) - fprintf(fp, "%sr", (x++ > 0) ? "," : ""); - if(temp_contact->notify_on_service_flapping == TRUE) - fprintf(fp, "%sf", (x++ > 0) ? "," : ""); - if(temp_contact->notify_on_service_downtime == TRUE) - fprintf(fp, "%ss", (x++ > 0) ? "," : ""); - if(x == 0) - fprintf(fp, "n"); - fprintf(fp, "\n"); - fprintf(fp, "\thost_notification_options\t"); - x = 0; - if(temp_contact->notify_on_host_down == TRUE) - fprintf(fp, "%sd", (x++ > 0) ? "," : ""); - if(temp_contact->notify_on_host_unreachable == TRUE) - fprintf(fp, "%su", (x++ > 0) ? "," : ""); - if(temp_contact->notify_on_host_recovery == TRUE) - fprintf(fp, "%sr", (x++ > 0) ? "," : ""); - if(temp_contact->notify_on_host_flapping == TRUE) - fprintf(fp, "%sf", (x++ > 0) ? "," : ""); - if(temp_contact->notify_on_host_downtime == TRUE) - fprintf(fp, "%ss", (x++ > 0) ? "," : ""); - if(x == 0) - fprintf(fp, "n"); - fprintf(fp, "\n"); - if(temp_contact->service_notification_commands) - fprintf(fp, "\tservice_notification_commands\t%s\n", temp_contact->service_notification_commands); - if(temp_contact->host_notification_commands) - fprintf(fp, "\thost_notification_commands\t%s\n", temp_contact->host_notification_commands); - if(temp_contact->email) - fprintf(fp, "\temail\t%s\n", temp_contact->email); - if(temp_contact->pager) - fprintf(fp, "\tpager\t%s\n", temp_contact->pager); - for(x = 0; x < MAX_XODTEMPLATE_CONTACT_ADDRESSES; x++) { - if(temp_contact->address[x]) - fprintf(fp, "\taddress%d\t%s\n", x + 1, temp_contact->address[x]); - } - fprintf(fp, "\thost_notifications_enabled\t%d\n", temp_contact->host_notifications_enabled); - fprintf(fp, "\tservice_notifications_enabled\t%d\n", temp_contact->service_notifications_enabled); - fprintf(fp, "\tcan_submit_commands\t%d\n", temp_contact->can_submit_commands); - fprintf(fp, "\tretain_status_information\t%d\n", temp_contact->retain_status_information); - fprintf(fp, "\tretain_nonstatus_information\t%d\n", temp_contact->retain_nonstatus_information); - - /* 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\t%s\n", temp_customvariablesmember->variable_name, (temp_customvariablesmember->variable_value == NULL) ? XODTEMPLATE_NULL : temp_customvariablesmember->variable_value); - } - - - fprintf(fp, "\t}\n\n"); - } - - /* cache hosts */ - /*for(temp_host=xodtemplate_host_list;temp_host!=NULL;temp_host=temp_host->next){*/ - ptr = NULL; - for(temp_host = (xodtemplate_host *)skiplist_get_first(xobject_skiplists[X_HOST_SKIPLIST], &ptr); temp_host != NULL; temp_host = (xodtemplate_host *)skiplist_get_next(&ptr)) { - if(temp_host->register_object == FALSE) - continue; - fprintf(fp, "define host {\n"); - if(temp_host->host_name) - fprintf(fp, "\thost_name\t%s\n", temp_host->host_name); - if(temp_host->display_name) - fprintf(fp, "\tdisplay_name\t%s\n", temp_host->display_name); - if(temp_host->alias) - fprintf(fp, "\talias\t%s\n", temp_host->alias); - if(temp_host->address) - fprintf(fp, "\taddress\t%s\n", temp_host->address); - if(temp_host->parents) - fprintf(fp, "\tparents\t%s\n", temp_host->parents); - if(temp_host->check_period) - fprintf(fp, "\tcheck_period\t%s\n", temp_host->check_period); - if(temp_host->check_command) - fprintf(fp, "\tcheck_command\t%s\n", temp_host->check_command); - if(temp_host->event_handler) - fprintf(fp, "\tevent_handler\t%s\n", temp_host->event_handler); - if(temp_host->contacts) - fprintf(fp, "\tcontacts\t%s\n", temp_host->contacts); - if(temp_host->contact_groups) - fprintf(fp, "\tcontact_groups\t%s\n", temp_host->contact_groups); - if(temp_host->notification_period) - fprintf(fp, "\tnotification_period\t%s\n", temp_host->notification_period); - if(temp_host->failure_prediction_options) - fprintf(fp, "\tfailure_prediction_options\t%s\n", temp_host->failure_prediction_options); - fprintf(fp, "\tinitial_state\t"); - if(temp_host->initial_state == HOST_DOWN) - fprintf(fp, "d\n"); - else if(temp_host->initial_state == HOST_UNREACHABLE) - fprintf(fp, "u\n"); - else - fprintf(fp, "o\n"); - fprintf(fp, "\tcheck_interval\t%f\n", temp_host->check_interval); - fprintf(fp, "\tretry_interval\t%f\n", temp_host->retry_interval); - fprintf(fp, "\tmax_check_attempts\t%d\n", temp_host->max_check_attempts); - fprintf(fp, "\tactive_checks_enabled\t%d\n", temp_host->active_checks_enabled); - fprintf(fp, "\tpassive_checks_enabled\t%d\n", temp_host->passive_checks_enabled); - fprintf(fp, "\tobsess_over_host\t%d\n", temp_host->obsess_over_host); - fprintf(fp, "\tevent_handler_enabled\t%d\n", temp_host->event_handler_enabled); - fprintf(fp, "\tlow_flap_threshold\t%f\n", temp_host->low_flap_threshold); - fprintf(fp, "\thigh_flap_threshold\t%f\n", temp_host->high_flap_threshold); - fprintf(fp, "\tflap_detection_enabled\t%d\n", temp_host->flap_detection_enabled); - fprintf(fp, "\tflap_detection_options\t"); - x = 0; - if(temp_host->flap_detection_on_up == TRUE) - fprintf(fp, "%so", (x++ > 0) ? "," : ""); - if(temp_host->flap_detection_on_down == TRUE) - fprintf(fp, "%sd", (x++ > 0) ? "," : ""); - if(temp_host->flap_detection_on_unreachable == TRUE) - fprintf(fp, "%su", (x++ > 0) ? "," : ""); - if(x == 0) - fprintf(fp, "n"); - fprintf(fp, "\n"); - fprintf(fp, "\tfreshness_threshold\t%d\n", temp_host->freshness_threshold); - fprintf(fp, "\tcheck_freshness\t%d\n", temp_host->check_freshness); - fprintf(fp, "\tnotification_options\t"); - x = 0; - if(temp_host->notify_on_down == TRUE) - fprintf(fp, "%sd", (x++ > 0) ? "," : ""); - if(temp_host->notify_on_unreachable == TRUE) - fprintf(fp, "%su", (x++ > 0) ? "," : ""); - if(temp_host->notify_on_recovery == TRUE) - fprintf(fp, "%sr", (x++ > 0) ? "," : ""); - if(temp_host->notify_on_flapping == TRUE) - fprintf(fp, "%sf", (x++ > 0) ? "," : ""); - if(temp_host->notify_on_downtime == TRUE) - fprintf(fp, "%ss", (x++ > 0) ? "," : ""); - if(x == 0) - fprintf(fp, "n"); - fprintf(fp, "\n"); - fprintf(fp, "\tnotifications_enabled\t%d\n", temp_host->notifications_enabled); - fprintf(fp, "\tnotification_interval\t%f\n", temp_host->notification_interval); - fprintf(fp, "\tfirst_notification_delay\t%f\n", temp_host->first_notification_delay); - fprintf(fp, "\tstalking_options\t"); - x = 0; - if(temp_host->stalk_on_up == TRUE) - fprintf(fp, "%so", (x++ > 0) ? "," : ""); - if(temp_host->stalk_on_down == TRUE) - fprintf(fp, "%sd", (x++ > 0) ? "," : ""); - if(temp_host->stalk_on_unreachable == TRUE) - fprintf(fp, "%su", (x++ > 0) ? "," : ""); - if(x == 0) - fprintf(fp, "n"); - fprintf(fp, "\n"); - fprintf(fp, "\tprocess_perf_data\t%d\n", temp_host->process_perf_data); - fprintf(fp, "\tfailure_prediction_enabled\t%d\n", temp_host->failure_prediction_enabled); - if(temp_host->icon_image) - fprintf(fp, "\ticon_image\t%s\n", temp_host->icon_image); - if(temp_host->icon_image_alt) - fprintf(fp, "\ticon_image_alt\t%s\n", temp_host->icon_image_alt); - if(temp_host->vrml_image) - fprintf(fp, "\tvrml_image\t%s\n", temp_host->vrml_image); - if(temp_host->statusmap_image) - fprintf(fp, "\tstatusmap_image\t%s\n", temp_host->statusmap_image); - if(temp_host->have_2d_coords == TRUE) - fprintf(fp, "\t2d_coords\t%d,%d\n", temp_host->x_2d, temp_host->y_2d); - if(temp_host->have_3d_coords == TRUE) - fprintf(fp, "\t3d_coords\t%f,%f,%f\n", temp_host->x_3d, temp_host->y_3d, temp_host->z_3d); - if(temp_host->notes) - fprintf(fp, "\tnotes\t%s\n", temp_host->notes); - if(temp_host->notes_url) - fprintf(fp, "\tnotes_url\t%s\n", temp_host->notes_url); - if(temp_host->action_url) - fprintf(fp, "\taction_url\t%s\n", temp_host->action_url); - fprintf(fp, "\tretain_status_information\t%d\n", temp_host->retain_status_information); - fprintf(fp, "\tretain_nonstatus_information\t%d\n", temp_host->retain_nonstatus_information); - - /* 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\t%s\n", temp_customvariablesmember->variable_name, (temp_customvariablesmember->variable_value == NULL) ? XODTEMPLATE_NULL : temp_customvariablesmember->variable_value); - } - - - fprintf(fp, "\t}\n\n"); - } - - /* cache services */ - /*for(temp_service=xodtemplate_service_list;temp_service!=NULL;temp_service=temp_service->next){*/ - ptr = NULL; - for(temp_service = (xodtemplate_service *)skiplist_get_first(xobject_skiplists[X_SERVICE_SKIPLIST], &ptr); temp_service != NULL; temp_service = (xodtemplate_service *)skiplist_get_next(&ptr)) { - if(temp_service->register_object == FALSE) - continue; - fprintf(fp, "define service {\n"); - if(temp_service->host_name) - fprintf(fp, "\thost_name\t%s\n", temp_service->host_name); - if(temp_service->service_description) - fprintf(fp, "\tservice_description\t%s\n", temp_service->service_description); - if(temp_service->display_name) - fprintf(fp, "\tdisplay_name\t%s\n", temp_service->display_name); - if(temp_service->check_period) - fprintf(fp, "\tcheck_period\t%s\n", temp_service->check_period); - if(temp_service->check_command) - fprintf(fp, "\tcheck_command\t%s\n", temp_service->check_command); - if(temp_service->event_handler) - fprintf(fp, "\tevent_handler\t%s\n", temp_service->event_handler); - if(temp_service->contacts) - fprintf(fp, "\tcontacts\t%s\n", temp_service->contacts); - if(temp_service->contact_groups) - fprintf(fp, "\tcontact_groups\t%s\n", temp_service->contact_groups); - if(temp_service->notification_period) - fprintf(fp, "\tnotification_period\t%s\n", temp_service->notification_period); - if(temp_service->failure_prediction_options) - fprintf(fp, "\tfailure_prediction_options\t%s\n", temp_service->failure_prediction_options); - fprintf(fp, "\tinitial_state\t"); - if(temp_service->initial_state == STATE_WARNING) - fprintf(fp, "w\n"); - else if(temp_service->initial_state == STATE_UNKNOWN) - fprintf(fp, "u\n"); - else if(temp_service->initial_state == STATE_CRITICAL) - fprintf(fp, "c\n"); - else - fprintf(fp, "o\n"); - fprintf(fp, "\tcheck_interval\t%f\n", temp_service->check_interval); - fprintf(fp, "\tretry_interval\t%f\n", temp_service->retry_interval); - fprintf(fp, "\tmax_check_attempts\t%d\n", temp_service->max_check_attempts); - fprintf(fp, "\tis_volatile\t%d\n", temp_service->is_volatile); - fprintf(fp, "\tparallelize_check\t%d\n", temp_service->parallelize_check); - fprintf(fp, "\tactive_checks_enabled\t%d\n", temp_service->active_checks_enabled); - fprintf(fp, "\tpassive_checks_enabled\t%d\n", temp_service->passive_checks_enabled); - fprintf(fp, "\tobsess_over_service\t%d\n", temp_service->obsess_over_service); - fprintf(fp, "\tevent_handler_enabled\t%d\n", temp_service->event_handler_enabled); - fprintf(fp, "\tlow_flap_threshold\t%f\n", temp_service->low_flap_threshold); - fprintf(fp, "\thigh_flap_threshold\t%f\n", temp_service->high_flap_threshold); - fprintf(fp, "\tflap_detection_enabled\t%d\n", temp_service->flap_detection_enabled); - fprintf(fp, "\tflap_detection_options\t"); - x = 0; - if(temp_service->flap_detection_on_ok == TRUE) - fprintf(fp, "%so", (x++ > 0) ? "," : ""); - if(temp_service->flap_detection_on_warning == TRUE) - fprintf(fp, "%sw", (x++ > 0) ? "," : ""); - if(temp_service->flap_detection_on_unknown == TRUE) - fprintf(fp, "%su", (x++ > 0) ? "," : ""); - if(temp_service->flap_detection_on_critical == TRUE) - fprintf(fp, "%sc", (x++ > 0) ? "," : ""); - if(x == 0) - fprintf(fp, "n"); - fprintf(fp, "\n"); - fprintf(fp, "\tfreshness_threshold\t%d\n", temp_service->freshness_threshold); - fprintf(fp, "\tcheck_freshness\t%d\n", temp_service->check_freshness); - fprintf(fp, "\tnotification_options\t"); - x = 0; - if(temp_service->notify_on_unknown == TRUE) - fprintf(fp, "%su", (x++ > 0) ? "," : ""); - if(temp_service->notify_on_warning == TRUE) - fprintf(fp, "%sw", (x++ > 0) ? "," : ""); - if(temp_service->notify_on_critical == TRUE) - fprintf(fp, "%sc", (x++ > 0) ? "," : ""); - if(temp_service->notify_on_recovery == TRUE) - fprintf(fp, "%sr", (x++ > 0) ? "," : ""); - if(temp_service->notify_on_flapping == TRUE) - fprintf(fp, "%sf", (x++ > 0) ? "," : ""); - if(temp_service->notify_on_downtime == TRUE) - fprintf(fp, "%ss", (x++ > 0) ? "," : ""); - if(x == 0) - fprintf(fp, "n"); - fprintf(fp, "\n"); - fprintf(fp, "\tnotifications_enabled\t%d\n", temp_service->notifications_enabled); - fprintf(fp, "\tnotification_interval\t%f\n", temp_service->notification_interval); - fprintf(fp, "\tfirst_notification_delay\t%f\n", temp_service->first_notification_delay); - fprintf(fp, "\tstalking_options\t"); - x = 0; - if(temp_service->stalk_on_ok == TRUE) - fprintf(fp, "%so", (x++ > 0) ? "," : ""); - if(temp_service->stalk_on_unknown == TRUE) - fprintf(fp, "%su", (x++ > 0) ? "," : ""); - if(temp_service->stalk_on_warning == TRUE) - fprintf(fp, "%sw", (x++ > 0) ? "," : ""); - if(temp_service->stalk_on_critical == TRUE) - fprintf(fp, "%sc", (x++ > 0) ? "," : ""); - if(x == 0) - fprintf(fp, "n"); - fprintf(fp, "\n"); - fprintf(fp, "\tprocess_perf_data\t%d\n", temp_service->process_perf_data); - fprintf(fp, "\tfailure_prediction_enabled\t%d\n", temp_service->failure_prediction_enabled); - if(temp_service->icon_image) - fprintf(fp, "\ticon_image\t%s\n", temp_service->icon_image); - if(temp_service->icon_image_alt) - fprintf(fp, "\ticon_image_alt\t%s\n", temp_service->icon_image_alt); - if(temp_service->notes) - fprintf(fp, "\tnotes\t%s\n", temp_service->notes); - if(temp_service->notes_url) - fprintf(fp, "\tnotes_url\t%s\n", temp_service->notes_url); - if(temp_service->action_url) - fprintf(fp, "\taction_url\t%s\n", temp_service->action_url); - fprintf(fp, "\tretain_status_information\t%d\n", temp_service->retain_status_information); - fprintf(fp, "\tretain_nonstatus_information\t%d\n", temp_service->retain_nonstatus_information); - - /* 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\t%s\n", temp_customvariablesmember->variable_name, (temp_customvariablesmember->variable_value == NULL) ? XODTEMPLATE_NULL : temp_customvariablesmember->variable_value); - } - - fprintf(fp, "\t}\n\n"); - } - - /* cache service dependencies */ - /*for(temp_servicedependency=xodtemplate_servicedependency_list;temp_servicedependency!=NULL;temp_servicedependency=temp_servicedependency->next){*/ - ptr = NULL; - for(temp_servicedependency = (xodtemplate_servicedependency *)skiplist_get_first(xobject_skiplists[X_SERVICEDEPENDENCY_SKIPLIST], &ptr); temp_servicedependency != NULL; temp_servicedependency = (xodtemplate_servicedependency *)skiplist_get_next(&ptr)) { - if(temp_servicedependency->register_object == FALSE) - continue; - fprintf(fp, "define servicedependency {\n"); - if(temp_servicedependency->host_name) - fprintf(fp, "\thost_name\t%s\n", temp_servicedependency->host_name); - if(temp_servicedependency->service_description) - fprintf(fp, "\tservice_description\t%s\n", temp_servicedependency->service_description); - if(temp_servicedependency->dependent_host_name) - fprintf(fp, "\tdependent_host_name\t%s\n", temp_servicedependency->dependent_host_name); - if(temp_servicedependency->dependent_service_description) - fprintf(fp, "\tdependent_service_description\t%s\n", temp_servicedependency->dependent_service_description); - if(temp_servicedependency->dependency_period) - fprintf(fp, "\tdependency_period\t%s\n", temp_servicedependency->dependency_period); - fprintf(fp, "\tinherits_parent\t%d\n", temp_servicedependency->inherits_parent); - if(temp_servicedependency->have_notification_dependency_options == TRUE) { - fprintf(fp, "\tnotification_failure_options\t"); - x = 0; - if(temp_servicedependency->fail_notify_on_ok == TRUE) - fprintf(fp, "%so", (x++ > 0) ? "," : ""); - if(temp_servicedependency->fail_notify_on_unknown == TRUE) - fprintf(fp, "%su", (x++ > 0) ? "," : ""); - if(temp_servicedependency->fail_notify_on_warning == TRUE) - fprintf(fp, "%sw", (x++ > 0) ? "," : ""); - if(temp_servicedependency->fail_notify_on_critical == TRUE) - fprintf(fp, "%sc", (x++ > 0) ? "," : ""); - if(temp_servicedependency->fail_notify_on_pending == TRUE) - fprintf(fp, "%sp", (x++ > 0) ? "," : ""); - if(x == 0) - fprintf(fp, "n"); - fprintf(fp, "\n"); - } - if(temp_servicedependency->have_execution_dependency_options == TRUE) { - fprintf(fp, "\texecution_failure_options\t"); - x = 0; - if(temp_servicedependency->fail_execute_on_ok == TRUE) - fprintf(fp, "%so", (x++ > 0) ? "," : ""); - if(temp_servicedependency->fail_execute_on_unknown == TRUE) - fprintf(fp, "%su", (x++ > 0) ? "," : ""); - if(temp_servicedependency->fail_execute_on_warning == TRUE) - fprintf(fp, "%sw", (x++ > 0) ? "," : ""); - if(temp_servicedependency->fail_execute_on_critical == TRUE) - fprintf(fp, "%sc", (x++ > 0) ? "," : ""); - if(temp_servicedependency->fail_execute_on_pending == TRUE) - fprintf(fp, "%sp", (x++ > 0) ? "," : ""); - if(x == 0) - fprintf(fp, "n"); - fprintf(fp, "\n"); - } - fprintf(fp, "\t}\n\n"); - } - - /* cache service escalations */ - /*for(temp_serviceescalation=xodtemplate_serviceescalation_list;temp_serviceescalation!=NULL;temp_serviceescalation=temp_serviceescalation->next){*/ - ptr = NULL; - for(temp_serviceescalation = (xodtemplate_serviceescalation *)skiplist_get_first(xobject_skiplists[X_SERVICEESCALATION_SKIPLIST], &ptr); temp_serviceescalation != NULL; temp_serviceescalation = (xodtemplate_serviceescalation *)skiplist_get_next(&ptr)) { - if(temp_serviceescalation->register_object == FALSE) - continue; - fprintf(fp, "define serviceescalation {\n"); - if(temp_serviceescalation->host_name) - fprintf(fp, "\thost_name\t%s\n", temp_serviceescalation->host_name); - if(temp_serviceescalation->service_description) - fprintf(fp, "\tservice_description\t%s\n", temp_serviceescalation->service_description); - fprintf(fp, "\tfirst_notification\t%d\n", temp_serviceescalation->first_notification); - fprintf(fp, "\tlast_notification\t%d\n", temp_serviceescalation->last_notification); - fprintf(fp, "\tnotification_interval\t%f\n", temp_serviceescalation->notification_interval); - if(temp_serviceescalation->escalation_period) - fprintf(fp, "\tescalation_period\t%s\n", temp_serviceescalation->escalation_period); - if(temp_serviceescalation->have_escalation_options == TRUE) { - fprintf(fp, "\tescalation_options\t"); - x = 0; - if(temp_serviceescalation->escalate_on_warning == TRUE) - fprintf(fp, "%sw", (x++ > 0) ? "," : ""); - if(temp_serviceescalation->escalate_on_unknown == TRUE) - fprintf(fp, "%su", (x++ > 0) ? "," : ""); - if(temp_serviceescalation->escalate_on_critical == TRUE) - fprintf(fp, "%sc", (x++ > 0) ? "," : ""); - if(temp_serviceescalation->escalate_on_recovery == TRUE) - fprintf(fp, "%sr", (x++ > 0) ? "," : ""); - if(x == 0) - fprintf(fp, "n"); - fprintf(fp, "\n"); - } - if(temp_serviceescalation->contacts) - fprintf(fp, "\tcontacts\t%s\n", temp_serviceescalation->contacts); - if(temp_serviceescalation->contact_groups) - fprintf(fp, "\tcontact_groups\t%s\n", temp_serviceescalation->contact_groups); - fprintf(fp, "\t}\n\n"); - } - - /* cache host dependencies */ - /*for(temp_hostdependency=xodtemplate_hostdependency_list;temp_hostdependency!=NULL;temp_hostdependency=temp_hostdependency->next){*/ - ptr = NULL; - for(temp_hostdependency = (xodtemplate_hostdependency *)skiplist_get_first(xobject_skiplists[X_HOSTDEPENDENCY_SKIPLIST], &ptr); temp_hostdependency != NULL; temp_hostdependency = (xodtemplate_hostdependency *)skiplist_get_next(&ptr)) { - if(temp_hostdependency->register_object == FALSE) - continue; - fprintf(fp, "define hostdependency {\n"); - if(temp_hostdependency->host_name) - fprintf(fp, "\thost_name\t%s\n", temp_hostdependency->host_name); - if(temp_hostdependency->dependent_host_name) - fprintf(fp, "\tdependent_host_name\t%s\n", temp_hostdependency->dependent_host_name); - if(temp_hostdependency->dependency_period) - fprintf(fp, "\tdependency_period\t%s\n", temp_hostdependency->dependency_period); - fprintf(fp, "\tinherits_parent\t%d\n", temp_hostdependency->inherits_parent); - if(temp_hostdependency->have_notification_dependency_options == TRUE) { - fprintf(fp, "\tnotification_failure_options\t"); - x = 0; - if(temp_hostdependency->fail_notify_on_up == TRUE) - fprintf(fp, "%so", (x++ > 0) ? "," : ""); - if(temp_hostdependency->fail_notify_on_down == TRUE) - fprintf(fp, "%sd", (x++ > 0) ? "," : ""); - if(temp_hostdependency->fail_notify_on_unreachable == TRUE) - fprintf(fp, "%su", (x++ > 0) ? "," : ""); - if(temp_hostdependency->fail_notify_on_pending == TRUE) - fprintf(fp, "%sp", (x++ > 0) ? "," : ""); - if(x == 0) - fprintf(fp, "n"); - fprintf(fp, "\n"); - } - if(temp_hostdependency->have_execution_dependency_options == TRUE) { - fprintf(fp, "\texecution_failure_options\t"); - x = 0; - if(temp_hostdependency->fail_execute_on_up == TRUE) - fprintf(fp, "%so", (x++ > 0) ? "," : ""); - if(temp_hostdependency->fail_execute_on_down == TRUE) - fprintf(fp, "%sd", (x++ > 0) ? "," : ""); - if(temp_hostdependency->fail_execute_on_unreachable == TRUE) - fprintf(fp, "%su", (x++ > 0) ? "," : ""); - if(temp_hostdependency->fail_execute_on_pending == TRUE) - fprintf(fp, "%sp", (x++ > 0) ? "," : ""); - if(x == 0) - fprintf(fp, "n"); - fprintf(fp, "\n"); - } - fprintf(fp, "\t}\n\n"); - } - - /* cache host escalations */ - /*for(temp_hostescalation=xodtemplate_hostescalation_list;temp_hostescalation!=NULL;temp_hostescalation=temp_hostescalation->next){*/ - ptr = NULL; - for(temp_hostescalation = (xodtemplate_hostescalation *)skiplist_get_first(xobject_skiplists[X_HOSTESCALATION_SKIPLIST], &ptr); temp_hostescalation != NULL; temp_hostescalation = (xodtemplate_hostescalation *)skiplist_get_next(&ptr)) { - if(temp_hostescalation->register_object == FALSE) - continue; - fprintf(fp, "define hostescalation {\n"); - if(temp_hostescalation->host_name) - fprintf(fp, "\thost_name\t%s\n", temp_hostescalation->host_name); - fprintf(fp, "\tfirst_notification\t%d\n", temp_hostescalation->first_notification); - fprintf(fp, "\tlast_notification\t%d\n", temp_hostescalation->last_notification); - fprintf(fp, "\tnotification_interval\t%f\n", temp_hostescalation->notification_interval); - if(temp_hostescalation->escalation_period) - fprintf(fp, "\tescalation_period\t%s\n", temp_hostescalation->escalation_period); - if(temp_hostescalation->have_escalation_options == TRUE) { - fprintf(fp, "\tescalation_options\t"); - x = 0; - if(temp_hostescalation->escalate_on_down == TRUE) - fprintf(fp, "%sd", (x++ > 0) ? "," : ""); - if(temp_hostescalation->escalate_on_unreachable == TRUE) - fprintf(fp, "%su", (x++ > 0) ? "," : ""); - if(temp_hostescalation->escalate_on_recovery == TRUE) - fprintf(fp, "%sr", (x++ > 0) ? "," : ""); - if(x == 0) - fprintf(fp, "n"); - fprintf(fp, "\n"); - } - if(temp_hostescalation->contacts) - fprintf(fp, "\tcontacts\t%s\n", temp_hostescalation->contacts); - if(temp_hostescalation->contact_groups) - fprintf(fp, "\tcontact_groups\t%s\n", temp_hostescalation->contact_groups); - fprintf(fp, "\t}\n\n"); - } - - fclose(fp); - - return OK; - } - -#endif - /******************************************************************/ /******************** SKIPLIST FUNCTIONS **************************/ /******************************************************************/ @@ -10791,36 +8000,33 @@ int xodtemplate_init_xobject_skiplists(void) { xobject_skiplists[x] = NULL; } - xobject_template_skiplists[X_HOST_SKIPLIST] = skiplist_new(16, 0.5, FALSE, FALSE, xodtemplate_skiplist_compare_host_template); - xobject_template_skiplists[X_SERVICE_SKIPLIST] = skiplist_new(16, 0.5, FALSE, FALSE, xodtemplate_skiplist_compare_service_template); - xobject_template_skiplists[X_COMMAND_SKIPLIST] = skiplist_new(10, 0.5, FALSE, FALSE, xodtemplate_skiplist_compare_command_template); - xobject_template_skiplists[X_TIMEPERIOD_SKIPLIST] = skiplist_new(10, 0.5, FALSE, FALSE, xodtemplate_skiplist_compare_timeperiod_template); - xobject_template_skiplists[X_CONTACT_SKIPLIST] = skiplist_new(10, 0.5, FALSE, FALSE, xodtemplate_skiplist_compare_contact_template); - xobject_template_skiplists[X_CONTACTGROUP_SKIPLIST] = skiplist_new(10, 0.5, FALSE, FALSE, xodtemplate_skiplist_compare_contactgroup_template); - xobject_template_skiplists[X_HOSTGROUP_SKIPLIST] = skiplist_new(10, 0.5, FALSE, FALSE, xodtemplate_skiplist_compare_hostgroup_template); - xobject_template_skiplists[X_SERVICEGROUP_SKIPLIST] = skiplist_new(10, 0.5, FALSE, FALSE, xodtemplate_skiplist_compare_servicegroup_template); - xobject_template_skiplists[X_HOSTDEPENDENCY_SKIPLIST] = skiplist_new(16, 0.5, FALSE, FALSE, xodtemplate_skiplist_compare_hostdependency_template); - xobject_template_skiplists[X_SERVICEDEPENDENCY_SKIPLIST] = skiplist_new(16, 0.5, FALSE, FALSE, xodtemplate_skiplist_compare_servicedependency_template); - xobject_template_skiplists[X_HOSTESCALATION_SKIPLIST] = skiplist_new(16, 0.5, FALSE, FALSE, xodtemplate_skiplist_compare_hostescalation_template); - xobject_template_skiplists[X_SERVICEESCALATION_SKIPLIST] = skiplist_new(16, 0.5, FALSE, FALSE, xodtemplate_skiplist_compare_serviceescalation_template); - xobject_template_skiplists[X_HOSTEXTINFO_SKIPLIST] = skiplist_new(16, 0.5, FALSE, FALSE, xodtemplate_skiplist_compare_hostextinfo_template); - xobject_template_skiplists[X_SERVICEEXTINFO_SKIPLIST] = skiplist_new(16, 0.5, FALSE, FALSE, xodtemplate_skiplist_compare_serviceextinfo_template); - - xobject_skiplists[X_HOST_SKIPLIST] = skiplist_new(16, 0.5, FALSE, FALSE, xodtemplate_skiplist_compare_host); - xobject_skiplists[X_SERVICE_SKIPLIST] = skiplist_new(16, 0.5, FALSE, FALSE, xodtemplate_skiplist_compare_service); - xobject_skiplists[X_COMMAND_SKIPLIST] = skiplist_new(16, 0.5, FALSE, FALSE, xodtemplate_skiplist_compare_command); - xobject_skiplists[X_TIMEPERIOD_SKIPLIST] = skiplist_new(16, 0.5, FALSE, FALSE, xodtemplate_skiplist_compare_timeperiod); - xobject_skiplists[X_CONTACT_SKIPLIST] = skiplist_new(10, 0.5, FALSE, FALSE, xodtemplate_skiplist_compare_contact); - xobject_skiplists[X_CONTACTGROUP_SKIPLIST] = skiplist_new(10, 0.5, FALSE, FALSE, xodtemplate_skiplist_compare_contactgroup); - xobject_skiplists[X_HOSTGROUP_SKIPLIST] = skiplist_new(10, 0.5, FALSE, FALSE, xodtemplate_skiplist_compare_hostgroup); - xobject_skiplists[X_SERVICEGROUP_SKIPLIST] = skiplist_new(10, 0.5, FALSE, FALSE, xodtemplate_skiplist_compare_servicegroup); - /* allow dups in the following lists... */ - xobject_skiplists[X_HOSTDEPENDENCY_SKIPLIST] = skiplist_new(16, 0.5, TRUE, FALSE, xodtemplate_skiplist_compare_hostdependency); - xobject_skiplists[X_SERVICEDEPENDENCY_SKIPLIST] = skiplist_new(16, 0.5, TRUE, FALSE, xodtemplate_skiplist_compare_servicedependency); - xobject_skiplists[X_HOSTESCALATION_SKIPLIST] = skiplist_new(16, 0.5, TRUE, FALSE, xodtemplate_skiplist_compare_hostescalation); - xobject_skiplists[X_SERVICEESCALATION_SKIPLIST] = skiplist_new(16, 0.5, TRUE, FALSE, xodtemplate_skiplist_compare_serviceescalation); - /* host and service extinfo entries don't need to be added to a list... */ + xobject_template_skiplists[HOST_SKIPLIST] = skiplist_new(16, 0.5, FALSE, FALSE, xodtemplate_skiplist_compare_host_template); + xobject_template_skiplists[SERVICE_SKIPLIST] = skiplist_new(16, 0.5, FALSE, FALSE, xodtemplate_skiplist_compare_service_template); + xobject_template_skiplists[COMMAND_SKIPLIST] = skiplist_new(10, 0.5, FALSE, FALSE, xodtemplate_skiplist_compare_command_template); + xobject_template_skiplists[TIMEPERIOD_SKIPLIST] = skiplist_new(10, 0.5, FALSE, FALSE, xodtemplate_skiplist_compare_timeperiod_template); + xobject_template_skiplists[CONTACT_SKIPLIST] = skiplist_new(10, 0.5, FALSE, FALSE, xodtemplate_skiplist_compare_contact_template); + xobject_template_skiplists[CONTACTGROUP_SKIPLIST] = skiplist_new(10, 0.5, FALSE, FALSE, xodtemplate_skiplist_compare_contactgroup_template); + xobject_template_skiplists[HOSTGROUP_SKIPLIST] = skiplist_new(10, 0.5, FALSE, FALSE, xodtemplate_skiplist_compare_hostgroup_template); + xobject_template_skiplists[SERVICEGROUP_SKIPLIST] = skiplist_new(10, 0.5, FALSE, FALSE, xodtemplate_skiplist_compare_servicegroup_template); + xobject_template_skiplists[HOSTDEPENDENCY_SKIPLIST] = skiplist_new(16, 0.5, FALSE, FALSE, xodtemplate_skiplist_compare_hostdependency_template); + xobject_template_skiplists[SERVICEDEPENDENCY_SKIPLIST] = skiplist_new(16, 0.5, FALSE, FALSE, xodtemplate_skiplist_compare_servicedependency_template); + xobject_template_skiplists[HOSTESCALATION_SKIPLIST] = skiplist_new(16, 0.5, FALSE, FALSE, xodtemplate_skiplist_compare_hostescalation_template); + xobject_template_skiplists[SERVICEESCALATION_SKIPLIST] = skiplist_new(16, 0.5, FALSE, FALSE, xodtemplate_skiplist_compare_serviceescalation_template); + xobject_template_skiplists[HOSTEXTINFO_SKIPLIST] = skiplist_new(16, 0.5, FALSE, FALSE, xodtemplate_skiplist_compare_hostextinfo_template); + xobject_template_skiplists[SERVICEEXTINFO_SKIPLIST] = skiplist_new(16, 0.5, FALSE, FALSE, xodtemplate_skiplist_compare_serviceextinfo_template); + xobject_skiplists[HOST_SKIPLIST] = skiplist_new(16, 0.5, FALSE, FALSE, xodtemplate_skiplist_compare_host); + xobject_skiplists[SERVICE_SKIPLIST] = skiplist_new(16, 0.5, FALSE, FALSE, xodtemplate_skiplist_compare_service); + xobject_skiplists[COMMAND_SKIPLIST] = skiplist_new(16, 0.5, FALSE, FALSE, xodtemplate_skiplist_compare_command); + xobject_skiplists[TIMEPERIOD_SKIPLIST] = skiplist_new(16, 0.5, FALSE, FALSE, xodtemplate_skiplist_compare_timeperiod); + xobject_skiplists[CONTACT_SKIPLIST] = skiplist_new(10, 0.5, FALSE, FALSE, xodtemplate_skiplist_compare_contact); + xobject_skiplists[CONTACTGROUP_SKIPLIST] = skiplist_new(10, 0.5, FALSE, FALSE, xodtemplate_skiplist_compare_contactgroup); + xobject_skiplists[HOSTGROUP_SKIPLIST] = skiplist_new(10, 0.5, FALSE, FALSE, xodtemplate_skiplist_compare_hostgroup); + xobject_skiplists[SERVICEGROUP_SKIPLIST] = skiplist_new(10, 0.5, FALSE, FALSE, xodtemplate_skiplist_compare_servicegroup); + /* + * host and service extinfo, dependencies, and escalations don't + * need to be sorted, so we avoid creating skiplists for them. + */ return OK; } @@ -10838,36 +8044,6 @@ int xodtemplate_free_xobject_skiplists(void) { } -int xodtemplate_skiplist_compare_text(const char *val1a, const char *val1b, const char *val2a, const char *val2b) { - int result = 0; - - /* check first name */ - if(val1a == NULL && val2a == NULL) - result = 0; - else if(val1a == NULL) - result = 1; - else if(val2a == NULL) - result = -1; - else - result = strcmp(val1a, val2a); - - /* check second name if necessary */ - if(result == 0) { - if(val1b == NULL && val2b == NULL) - result = 0; - else if(val1b == NULL) - result = 1; - else if(val2b == NULL) - result = -1; - else - result = strcmp(val1b, val2b); - } - - return result; - } - - - int xodtemplate_skiplist_compare_host_template(void *a, void *b) { xodtemplate_host *oa = NULL; xodtemplate_host *ob = NULL; @@ -11381,24 +8557,12 @@ int xodtemplate_free_memory(void) { xodtemplate_hostgroup *next_hostgroup = NULL; xodtemplate_servicegroup *this_servicegroup = NULL; xodtemplate_servicegroup *next_servicegroup = NULL; - xodtemplate_servicedependency *this_servicedependency = NULL; - xodtemplate_servicedependency *next_servicedependency = NULL; - xodtemplate_serviceescalation *this_serviceescalation = NULL; - xodtemplate_serviceescalation *next_serviceescalation = NULL; xodtemplate_contact *this_contact = NULL; xodtemplate_contact *next_contact = NULL; xodtemplate_host *this_host = NULL; xodtemplate_host *next_host = NULL; xodtemplate_service *this_service = NULL; xodtemplate_service *next_service = NULL; - xodtemplate_hostdependency *this_hostdependency = NULL; - xodtemplate_hostdependency *next_hostdependency = NULL; - xodtemplate_hostescalation *this_hostescalation = NULL; - xodtemplate_hostescalation *next_hostescalation = NULL; - xodtemplate_hostextinfo *this_hostextinfo = NULL; - xodtemplate_hostextinfo *next_hostextinfo = NULL; - xodtemplate_serviceextinfo *this_serviceextinfo = NULL; - xodtemplate_serviceextinfo *next_serviceextinfo = NULL; xodtemplate_customvariablesmember *this_customvariablesmember = NULL; xodtemplate_customvariablesmember *next_customvariablesmember = NULL; register int x = 0; @@ -11409,8 +8573,10 @@ int xodtemplate_free_memory(void) { next_timeperiod = this_timeperiod->next; my_free(this_timeperiod->template); my_free(this_timeperiod->name); - my_free(this_timeperiod->timeperiod_name); - my_free(this_timeperiod->alias); + if (!this_timeperiod->register_object) { + my_free(this_timeperiod->timeperiod_name); + my_free(this_timeperiod->alias); + } for(x = 0; x < 7; x++) my_free(this_timeperiod->timeranges[x]); for(x = 0; x < DATERANGE_TYPES; x++) { @@ -11431,8 +8597,10 @@ int xodtemplate_free_memory(void) { next_command = this_command->next; my_free(this_command->template); my_free(this_command->name); - my_free(this_command->command_name); - my_free(this_command->command_line); + if (!this_command->register_object) { + my_free(this_command->command_name); + my_free(this_command->command_line); + } my_free(this_command); } xodtemplate_command_list = NULL; @@ -11443,10 +8611,15 @@ int xodtemplate_free_memory(void) { next_contactgroup = this_contactgroup->next; my_free(this_contactgroup->template); my_free(this_contactgroup->name); - my_free(this_contactgroup->contactgroup_name); - my_free(this_contactgroup->alias); my_free(this_contactgroup->members); my_free(this_contactgroup->contactgroup_members); + bitmap_destroy(this_contactgroup->member_map); + free_objectlist(&this_contactgroup->member_list); + free_objectlist(&this_contactgroup->group_list); + if (!this_contactgroup->register_object) { + my_free(this_contactgroup->contactgroup_name); + my_free(this_contactgroup->alias); + } my_free(this_contactgroup); } xodtemplate_contactgroup_list = NULL; @@ -11457,13 +8630,18 @@ int xodtemplate_free_memory(void) { next_hostgroup = this_hostgroup->next; my_free(this_hostgroup->template); my_free(this_hostgroup->name); - my_free(this_hostgroup->hostgroup_name); - my_free(this_hostgroup->alias); my_free(this_hostgroup->members); my_free(this_hostgroup->hostgroup_members); - my_free(this_hostgroup->notes); - my_free(this_hostgroup->notes_url); - my_free(this_hostgroup->action_url); + bitmap_destroy(this_hostgroup->member_map); + free_objectlist(&this_hostgroup->member_list); + free_objectlist(&this_hostgroup->group_list); + if (!this_hostgroup->register_object) { + my_free(this_hostgroup->hostgroup_name); + my_free(this_hostgroup->alias); + my_free(this_hostgroup->notes); + my_free(this_hostgroup->notes_url); + my_free(this_hostgroup->action_url); + } my_free(this_hostgroup); } xodtemplate_hostgroup_list = NULL; @@ -11472,59 +8650,28 @@ int xodtemplate_free_memory(void) { /* free memory allocated to servicegroup list */ for(this_servicegroup = xodtemplate_servicegroup_list; this_servicegroup != NULL; this_servicegroup = next_servicegroup) { next_servicegroup = this_servicegroup->next; - my_free(this_servicegroup->template); - my_free(this_servicegroup->name); - my_free(this_servicegroup->servicegroup_name); - my_free(this_servicegroup->alias); my_free(this_servicegroup->members); my_free(this_servicegroup->servicegroup_members); - my_free(this_servicegroup->notes); - my_free(this_servicegroup->notes_url); - my_free(this_servicegroup->action_url); + bitmap_destroy(this_servicegroup->member_map); + free_objectlist(&this_servicegroup->member_list); + free_objectlist(&this_servicegroup->group_list); + my_free(this_servicegroup->template); + my_free(this_servicegroup->name); + if (!this_servicegroup->register_object) { + my_free(this_servicegroup->servicegroup_name); + my_free(this_servicegroup->alias); + my_free(this_servicegroup->notes); + my_free(this_servicegroup->notes_url); + my_free(this_servicegroup->action_url); + } my_free(this_servicegroup); } xodtemplate_servicegroup_list = NULL; xodtemplate_servicegroup_list_tail = NULL; - /* free memory allocated to servicedependency list */ - for(this_servicedependency = xodtemplate_servicedependency_list; this_servicedependency != NULL; this_servicedependency = next_servicedependency) { - next_servicedependency = this_servicedependency->next; - my_free(this_servicedependency->template); - my_free(this_servicedependency->name); - my_free(this_servicedependency->servicegroup_name); - my_free(this_servicedependency->hostgroup_name); - my_free(this_servicedependency->host_name); - my_free(this_servicedependency->service_description); - my_free(this_servicedependency->dependent_servicegroup_name); - my_free(this_servicedependency->dependent_hostgroup_name); - my_free(this_servicedependency->dependent_host_name); - my_free(this_servicedependency->dependent_service_description); - my_free(this_servicedependency->dependency_period); - my_free(this_servicedependency); - } - xodtemplate_servicedependency_list = NULL; - xodtemplate_servicedependency_list_tail = NULL; - - /* free memory allocated to serviceescalation list */ - for(this_serviceescalation = xodtemplate_serviceescalation_list; this_serviceescalation != NULL; this_serviceescalation = next_serviceescalation) { - next_serviceescalation = this_serviceescalation->next; - my_free(this_serviceescalation->template); - my_free(this_serviceescalation->name); - my_free(this_serviceescalation->servicegroup_name); - my_free(this_serviceescalation->hostgroup_name); - my_free(this_serviceescalation->host_name); - my_free(this_serviceescalation->service_description); - my_free(this_serviceescalation->escalation_period); - my_free(this_serviceescalation->contact_groups); - my_free(this_serviceescalation->contacts); - my_free(this_serviceescalation); - } - xodtemplate_serviceescalation_list = NULL; - xodtemplate_serviceescalation_list_tail = NULL; - /* free memory allocated to contact list */ for(this_contact = xodtemplate_contact_list; this_contact != NULL; this_contact = next_contact) { - + next_contact = this_contact->next; /* free custom variables */ this_customvariablesmember = this_contact->custom_variables; while(this_customvariablesmember != NULL) { @@ -11534,21 +8681,21 @@ int xodtemplate_free_memory(void) { my_free(this_customvariablesmember); this_customvariablesmember = next_customvariablesmember; } - - next_contact = this_contact->next; my_free(this_contact->template); my_free(this_contact->name); - my_free(this_contact->contact_name); - my_free(this_contact->alias); my_free(this_contact->contact_groups); - my_free(this_contact->email); - my_free(this_contact->pager); - for(x = 0; x < MAX_XODTEMPLATE_CONTACT_ADDRESSES; x++) - my_free(this_contact->address[x]); my_free(this_contact->service_notification_period); my_free(this_contact->service_notification_commands); my_free(this_contact->host_notification_period); my_free(this_contact->host_notification_commands); + if (!this_contact->register_object) { + my_free(this_contact->contact_name); + my_free(this_contact->alias); + my_free(this_contact->email); + my_free(this_contact->pager); + for (x = 0; x < MAX_XODTEMPLATE_CONTACT_ADDRESSES; x++) + my_free(this_contact->address[x]); + } my_free(this_contact); } xodtemplate_contact_list = NULL; @@ -11556,7 +8703,7 @@ int xodtemplate_free_memory(void) { /* free memory allocated to host list */ for(this_host = xodtemplate_host_list; this_host != NULL; this_host = next_host) { - + next_host = this_host->next; /* free custom variables */ this_customvariablesmember = this_host->custom_variables; while(this_customvariablesmember != NULL) { @@ -11567,29 +8714,29 @@ int xodtemplate_free_memory(void) { this_customvariablesmember = next_customvariablesmember; } - next_host = this_host->next; my_free(this_host->template); my_free(this_host->name); - my_free(this_host->host_name); - my_free(this_host->alias); - my_free(this_host->display_name); - my_free(this_host->address); my_free(this_host->parents); my_free(this_host->host_groups); - my_free(this_host->check_command); my_free(this_host->check_period); - my_free(this_host->event_handler); my_free(this_host->contact_groups); my_free(this_host->contacts); my_free(this_host->notification_period); - my_free(this_host->failure_prediction_options); - my_free(this_host->notes); - my_free(this_host->notes_url); - my_free(this_host->action_url); - my_free(this_host->icon_image); - my_free(this_host->icon_image_alt); - my_free(this_host->vrml_image); - my_free(this_host->statusmap_image); + if (!this_host->register_object) { + my_free(this_host->host_name); + my_free(this_host->alias); + my_free(this_host->display_name); + my_free(this_host->address); + my_free(this_host->check_command); + my_free(this_host->event_handler); + my_free(this_host->notes); + my_free(this_host->notes_url); + my_free(this_host->action_url); + my_free(this_host->icon_image); + my_free(this_host->icon_image_alt); + my_free(this_host->statusmap_image); + my_free(this_host->vrml_image); + } my_free(this_host); } xodtemplate_host_list = NULL; @@ -11597,106 +8744,49 @@ int xodtemplate_free_memory(void) { /* free memory allocated to service list */ for(this_service = xodtemplate_service_list; this_service != NULL; this_service = next_service) { - - /* free custom variables */ - this_customvariablesmember = this_service->custom_variables; - while(this_customvariablesmember != NULL) { - next_customvariablesmember = this_customvariablesmember->next; - my_free(this_customvariablesmember->variable_name); - my_free(this_customvariablesmember->variable_value); - my_free(this_customvariablesmember); - this_customvariablesmember = next_customvariablesmember; - } - next_service = this_service->next; - my_free(this_service->template); - my_free(this_service->name); - my_free(this_service->display_name); - my_free(this_service->hostgroup_name); - my_free(this_service->host_name); - my_free(this_service->service_description); - my_free(this_service->service_groups); - my_free(this_service->check_command); - my_free(this_service->check_period); - my_free(this_service->event_handler); - my_free(this_service->notification_period); my_free(this_service->contact_groups); my_free(this_service->contacts); - my_free(this_service->failure_prediction_options); - my_free(this_service->notes); - my_free(this_service->notes_url); - my_free(this_service->action_url); - my_free(this_service->icon_image); - my_free(this_service->icon_image_alt); + my_free(this_service->service_groups); + + if(this_service->is_copy == FALSE || !this_service->register_object) { + /* free custom variables */ + this_customvariablesmember = this_service->custom_variables; + while(this_customvariablesmember != NULL) { + next_customvariablesmember = this_customvariablesmember->next; + my_free(this_customvariablesmember->variable_name); + my_free(this_customvariablesmember->variable_value); + my_free(this_customvariablesmember); + this_customvariablesmember = next_customvariablesmember; + } + + my_free(this_service->template); + my_free(this_service->name); + my_free(this_service->parents); + my_free(this_service->display_name); + my_free(this_service->check_command); + my_free(this_service->check_period); + my_free(this_service->event_handler); + my_free(this_service->notification_period); + my_free(this_service->notes); + my_free(this_service->notes_url); + my_free(this_service->action_url); + my_free(this_service->icon_image); + my_free(this_service->icon_image_alt); + my_free(this_service->hostgroup_name); + my_free(this_service->service_description); + } my_free(this_service); } xodtemplate_service_list = NULL; xodtemplate_service_list_tail = NULL; - /* free memory allocated to hostdependency list */ - for(this_hostdependency = xodtemplate_hostdependency_list; this_hostdependency != NULL; this_hostdependency = next_hostdependency) { - next_hostdependency = this_hostdependency->next; - my_free(this_hostdependency->template); - my_free(this_hostdependency->name); - my_free(this_hostdependency->hostgroup_name); - my_free(this_hostdependency->dependent_hostgroup_name); - my_free(this_hostdependency->host_name); - my_free(this_hostdependency->dependent_host_name); - my_free(this_hostdependency->dependency_period); - my_free(this_hostdependency); - } - xodtemplate_hostdependency_list = NULL; - xodtemplate_hostdependency_list_tail = NULL; - - /* free memory allocated to hostescalation list */ - for(this_hostescalation = xodtemplate_hostescalation_list; this_hostescalation != NULL; this_hostescalation = next_hostescalation) { - next_hostescalation = this_hostescalation->next; - my_free(this_hostescalation->template); - my_free(this_hostescalation->name); - my_free(this_hostescalation->hostgroup_name); - my_free(this_hostescalation->host_name); - my_free(this_hostescalation->escalation_period); - my_free(this_hostescalation->contact_groups); - my_free(this_hostescalation->contacts); - my_free(this_hostescalation); - } - xodtemplate_hostescalation_list = NULL; - xodtemplate_hostescalation_list_tail = NULL; - - /* free memory allocated to hostextinfo list */ - for(this_hostextinfo = xodtemplate_hostextinfo_list; this_hostextinfo != NULL; this_hostextinfo = next_hostextinfo) { - next_hostextinfo = this_hostextinfo->next; - my_free(this_hostextinfo->template); - my_free(this_hostextinfo->name); - my_free(this_hostextinfo->host_name); - my_free(this_hostextinfo->hostgroup_name); - my_free(this_hostextinfo->notes); - my_free(this_hostextinfo->notes_url); - my_free(this_hostextinfo->action_url); - my_free(this_hostextinfo->icon_image); - my_free(this_hostextinfo->icon_image_alt); - my_free(this_hostextinfo->vrml_image); - my_free(this_hostextinfo->statusmap_image); - my_free(this_hostextinfo); - } + /* + * extinfo objects are free()'d while they're parsed, as are + * dependencies and escalations + */ xodtemplate_hostextinfo_list = NULL; xodtemplate_hostextinfo_list_tail = NULL; - - /* free memory allocated to serviceextinfo list */ - for(this_serviceextinfo = xodtemplate_serviceextinfo_list; this_serviceextinfo != NULL; this_serviceextinfo = next_serviceextinfo) { - next_serviceextinfo = this_serviceextinfo->next; - my_free(this_serviceextinfo->template); - my_free(this_serviceextinfo->name); - my_free(this_serviceextinfo->host_name); - my_free(this_serviceextinfo->hostgroup_name); - my_free(this_serviceextinfo->service_description); - my_free(this_serviceextinfo->notes); - my_free(this_serviceextinfo->notes_url); - my_free(this_serviceextinfo->action_url); - my_free(this_serviceextinfo->icon_image); - my_free(this_serviceextinfo->icon_image_alt); - my_free(this_serviceextinfo); - } xodtemplate_serviceextinfo_list = NULL; xodtemplate_serviceextinfo_list_tail = NULL; @@ -11715,7 +8805,6 @@ int xodtemplate_free_memory(void) { -#ifdef NSCORE /* adds a member to a list */ int xodtemplate_add_member_to_memberlist(xodtemplate_memberlist **list, char *name1, char *name2) { xodtemplate_memberlist *temp_item = NULL; @@ -11818,188 +8907,15 @@ void xodtemplate_remove_memberlist_item(xodtemplate_memberlist *item, xodtemplat return; } -#endif /******************************************************************/ /********************** UTILITY FUNCTIONS *************************/ /******************************************************************/ -#ifdef NSCORE - -/* expands a comma-delimited list of contactgroups and/or contacts to member contact names */ -xodtemplate_memberlist *xodtemplate_expand_contactgroups_and_contacts(char *contactgroups, char *contacts, int _config_file, int _start_line) { - xodtemplate_memberlist *temp_list = NULL; - xodtemplate_memberlist *reject_list = NULL; - xodtemplate_memberlist *list_ptr = NULL; - xodtemplate_memberlist *reject_ptr = NULL; - int result = OK; - - /* process list of contactgroups... */ - if(contactgroups != NULL) { - - /* expand contactgroups */ - result = xodtemplate_expand_contactgroups(&temp_list, &reject_list, contactgroups, _config_file, _start_line); - if(result != OK) { - xodtemplate_free_memberlist(&temp_list); - xodtemplate_free_memberlist(&reject_list); - return NULL; - } - } - - /* process contact names */ - if(contacts != NULL) { - - /* expand contacts */ - result = xodtemplate_expand_contacts(&temp_list, &reject_list, contacts, _config_file, _start_line); - if(result != OK) { - xodtemplate_free_memberlist(&temp_list); - xodtemplate_free_memberlist(&reject_list); - return NULL; - } - } - - /* remove rejects (if any) from the list (no duplicate entries exist in either list) */ - /* NOTE: rejects from this list also affect contacts generated from processing contactgroup names (see above) */ - for(reject_ptr = reject_list; reject_ptr != NULL; reject_ptr = reject_ptr->next) { - for(list_ptr = temp_list; list_ptr != NULL; list_ptr = list_ptr->next) { - if(!strcmp(reject_ptr->name1, list_ptr->name1)) { - xodtemplate_remove_memberlist_item(list_ptr, &temp_list); - break; - } - } - } - xodtemplate_free_memberlist(&reject_list); - reject_list = NULL; - - return temp_list; - } - - - -/* expands contactgroups */ -int xodtemplate_expand_contactgroups(xodtemplate_memberlist **list, xodtemplate_memberlist **reject_list, char *contactgroups, int _config_file, int _start_line) { - char *contactgroup_names = NULL; - char *temp_ptr = NULL; - xodtemplate_contactgroup *temp_contactgroup = NULL; - regex_t preg; - int found_match = TRUE; - int reject_item = FALSE; - int use_regexp = FALSE; - - if(list == NULL || contactgroups == NULL) - return ERROR; - - /* allocate memory for contactgroup name list */ - if((contactgroup_names = (char *)strdup(contactgroups)) == NULL) - return ERROR; - - for(temp_ptr = strtok(contactgroup_names, ","); temp_ptr; temp_ptr = strtok(NULL, ",")) { - - found_match = FALSE; - reject_item = FALSE; - - /* strip trailing spaces */ - strip(temp_ptr); - - /* should we use regular expression matching? */ - if(use_regexp_matches == TRUE && (use_true_regexp_matching == TRUE || strstr(temp_ptr, "*") || strstr(temp_ptr, "?") || strstr(temp_ptr, "+") || strstr(temp_ptr, "\\."))) - use_regexp = TRUE; - else - use_regexp = FALSE; - - /* use regular expression matching */ - if(use_regexp == TRUE) { - - /* compile regular expression */ - if(regcomp(&preg, temp_ptr, REG_EXTENDED)) { - my_free(contactgroup_names); - return ERROR; - } - - /* test match against all contactgroup names */ - for(temp_contactgroup = xodtemplate_contactgroup_list; temp_contactgroup != NULL; temp_contactgroup = temp_contactgroup->next) { - - if(temp_contactgroup->contactgroup_name == NULL) - continue; - - /* skip this contactgroup if it did not match the expression */ - if(regexec(&preg, temp_contactgroup->contactgroup_name, 0, NULL, 0)) - continue; - - found_match = TRUE; - - /* dont' add contactgroups that shouldn't be registered */ - if(temp_contactgroup->register_object == FALSE) - continue; - - /* add contactgroup members to list */ - xodtemplate_add_contactgroup_members_to_memberlist(list, temp_contactgroup, _config_file, _start_line); - } - - /* free memory allocated to compiled regexp */ - regfree(&preg); - } - - /* use standard matching... */ - else { - - /* return a list of all contactgroups */ - if(!strcmp(temp_ptr, "*")) { - - found_match = TRUE; - - for(temp_contactgroup = xodtemplate_contactgroup_list; temp_contactgroup != NULL; temp_contactgroup = temp_contactgroup->next) { - - /* dont' add contactgroups that shouldn't be registered */ - if(temp_contactgroup->register_object == FALSE) - continue; - - /* add contactgroup to list */ - xodtemplate_add_contactgroup_members_to_memberlist(list, temp_contactgroup, _config_file, _start_line); - } - } - - /* else this is just a single contactgroup... */ - else { - - /* this contactgroup should be excluded (rejected) */ - if(temp_ptr[0] == '!') { - reject_item = TRUE; - temp_ptr++; - } - - /* find the contactgroup */ - temp_contactgroup = xodtemplate_find_real_contactgroup(temp_ptr); - if(temp_contactgroup != NULL) { - - found_match = TRUE; - - /* add contactgroup members to proper list */ - xodtemplate_add_contactgroup_members_to_memberlist((reject_item == TRUE) ? reject_list : list, temp_contactgroup, _config_file, _start_line); - } - } - } - - if(found_match == FALSE) { - logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not find any contactgroup matching '%s' (config file '%s', starting on line %d)\n", temp_ptr, xodtemplate_config_file_name(_config_file), _start_line); - break; - } - } - - /* free memory */ - my_free(contactgroup_names); - - if(found_match == FALSE) - return ERROR; - - return OK; - } - - /* expands contacts */ -int xodtemplate_expand_contacts(xodtemplate_memberlist **list, xodtemplate_memberlist **reject_list, char *contacts, int _config_file, int _start_line) { +int xodtemplate_expand_contacts(objectlist **ret, bitmap *reject_map, char *contacts, int _config_file, int _start_line) { char *contact_names = NULL; char *temp_ptr = NULL; xodtemplate_contact *temp_contact = NULL; @@ -12008,9 +8924,11 @@ int xodtemplate_expand_contacts(xodtemplate_memberlist **list, xodtemplate_membe int reject_item = FALSE; int use_regexp = FALSE; - if(list == NULL || contacts == NULL) + if(ret == NULL || contacts == NULL) return ERROR; + *ret = NULL; + if((contact_names = (char *)strdup(contacts)) == NULL) return ERROR; @@ -12053,7 +8971,7 @@ int xodtemplate_expand_contacts(xodtemplate_memberlist **list, xodtemplate_membe continue; /* add contact to list */ - xodtemplate_add_member_to_memberlist(list, temp_contact->contact_name, NULL); + add_object_to_objectlist(ret, temp_contact); } /* free memory allocated to compiled regexp */ @@ -12078,7 +8996,7 @@ int xodtemplate_expand_contacts(xodtemplate_memberlist **list, xodtemplate_membe continue; /* add contact to list */ - xodtemplate_add_member_to_memberlist(list, temp_contact->contact_name, NULL); + add_object_to_objectlist(ret, temp_contact); } } @@ -12098,7 +9016,12 @@ int xodtemplate_expand_contacts(xodtemplate_memberlist **list, xodtemplate_membe found_match = TRUE; /* add contact to list */ - xodtemplate_add_member_to_memberlist((reject_item == TRUE) ? reject_list : list, temp_ptr, NULL); + if(reject_item) { + bitmap_set(reject_map, temp_contact->id); + } + else { + add_object_to_objectlist(ret, temp_contact); + } } } } @@ -12119,108 +9042,81 @@ int xodtemplate_expand_contacts(xodtemplate_memberlist **list, xodtemplate_membe } +#ifdef NSCORE -/* adds members of a contactgroups to the list of expanded (accepted) or rejected contacts */ -int xodtemplate_add_contactgroup_members_to_memberlist(xodtemplate_memberlist **list, xodtemplate_contactgroup *temp_contactgroup, int _config_file, int _start_line) { - char *group_members = NULL; - char *member_name = NULL; - char *member_ptr = NULL; +/* + * expands a comma-delimited list of hostgroups and/or hosts to + * an objectlist of hosts. This cannot be called until hostgroups + * have been recombobulated. + */ +objectlist *xodtemplate_expand_hostgroups_and_hosts(char *hostgroups, char *hosts, int _config_file, int _start_line) { + objectlist *ret = NULL, *glist = NULL, *hlist, *list = NULL, *next; + bitmap *reject; + int result; - if(list == NULL || temp_contactgroup == NULL) - return ERROR; - - /* if we have no members, just return. Empty contactgroups are ok */ - if(temp_contactgroup->members == NULL) { - return OK; + reject = bitmap_create(xodcount.hosts); + if(!reject) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Unable to create reject map for expanding hosts and hostgroups\n"); + return NULL; } - /* save a copy of the members */ - if((group_members = (char *)strdup(temp_contactgroup->members)) == NULL) - return ERROR; - - /* process all contacts that belong to the contactgroup */ - /* NOTE: members of the group have already have been expanded by xodtemplate_recombobulate_contactgroups(), so we don't need to do it here */ - member_ptr = group_members; - for(member_name = my_strsep(&member_ptr, ","); member_name != NULL; member_name = my_strsep(&member_ptr, ",")) { - - /* strip trailing spaces from member name */ - strip(member_name); - - /* add contact to the list */ - xodtemplate_add_member_to_memberlist(list, member_name, NULL); + /* + * process host names first. If they're explicitly added we must obey + */ + if(hosts != NULL) { + /* expand hosts */ + result = xodtemplate_expand_hosts(&ret, reject, hosts, _config_file, _start_line); + if(result != OK) { + free_objectlist(&glist); + free_objectlist(&ret); + bitmap_destroy(reject); + return NULL; + } } - my_free(group_members); - - return OK; - } - - - -/* expands a comma-delimited list of hostgroups and/or hosts to member host names */ -xodtemplate_memberlist *xodtemplate_expand_hostgroups_and_hosts(char *hostgroups, char *hosts, int _config_file, int _start_line) { - xodtemplate_memberlist *temp_list = NULL; - xodtemplate_memberlist *reject_list = NULL; - xodtemplate_memberlist *list_ptr = NULL; - xodtemplate_memberlist *reject_ptr = NULL; - int result = OK; - /* process list of hostgroups... */ if(hostgroups != NULL) { - /* expand host */ - result = xodtemplate_expand_hostgroups(&temp_list, &reject_list, hostgroups, _config_file, _start_line); + result = xodtemplate_expand_hostgroups(&glist, reject, hostgroups, _config_file, _start_line); if(result != OK) { - xodtemplate_free_memberlist(&temp_list); - xodtemplate_free_memberlist(&reject_list); + logit(NSLOG_CONFIG_ERROR, TRUE, "Failed to expand hostgroups '%s' to something sensible\n", hostgroups); + free_objectlist(&glist); + bitmap_destroy(reject); return NULL; } } - /* process host names */ - if(hosts != NULL) { - - /* expand hosts */ - result = xodtemplate_expand_hosts(&temp_list, &reject_list, hosts, _config_file, _start_line); - if(result != OK) { - xodtemplate_free_memberlist(&temp_list); - xodtemplate_free_memberlist(&reject_list); - return NULL; - } + /* + * add hostgroup hosts to ret, taking care not to add any that are + * in the rejected list + */ + for(list = glist; list; list = next) { + xodtemplate_hostgroup *hg = (xodtemplate_hostgroup *)list->object_ptr; + next = list->next; + free(list); /* free it as we go along */ + for(hlist = hg->member_list; hlist; hlist = hlist->next) { + xodtemplate_host *h = (xodtemplate_host *)hlist->object_ptr; + if(bitmap_isset(reject, h->id)) + continue; + add_object_to_objectlist(&ret, h); } + } + bitmap_destroy(reject); -#ifdef TESTING - printf("->PRIOR TO CLEANUP\n"); - printf(" REJECT LIST:\n"); - for(list_ptr = reject_list; list_ptr != NULL; list_ptr = list_ptr->next) { - printf(" '%s'\n", list_ptr->name1); - } - printf(" ACCEPT LIST:\n"); - for(list_ptr = temp_list; list_ptr != NULL; list_ptr = list_ptr->next) { - printf(" '%s'\n", list_ptr->name1); - } -#endif - - /* remove rejects (if any) from the list (no duplicate entries exist in either list) */ - /* NOTE: rejects from this list also affect hosts generated from processing hostgroup names (see above) */ - for(reject_ptr = reject_list; reject_ptr != NULL; reject_ptr = reject_ptr->next) { - for(list_ptr = temp_list; list_ptr != NULL; list_ptr = list_ptr->next) { - if(!strcmp(reject_ptr->name1, list_ptr->name1)) { - xodtemplate_remove_memberlist_item(list_ptr, &temp_list); - break; - } - } - } - xodtemplate_free_memberlist(&reject_list); - reject_list = NULL; - - return temp_list; + return ret; } +#endif - -/* expands hostgroups */ -int xodtemplate_expand_hostgroups(xodtemplate_memberlist **list, xodtemplate_memberlist **reject_list, char *hostgroups, int _config_file, int _start_line) { +/* + * expands hostgroups. + * list will be populated with all selected hostgroups on success + * and set to NULL on errors. + * reject_map marks rejected *hosts* from rejected hostgroups + * This can only be called after hostgroups are recombobulated. + * returns ERROR on error and OK on success. + */ +int xodtemplate_expand_hostgroups(objectlist **list, bitmap *reject_map, char *hostgroups, int _config_file, int _start_line) { char *hostgroup_names = NULL; char *temp_ptr = NULL; xodtemplate_hostgroup *temp_hostgroup = NULL; @@ -12232,6 +9128,8 @@ int xodtemplate_expand_hostgroups(xodtemplate_memberlist **list, xodtemplate_mem if(list == NULL || hostgroups == NULL) return ERROR; + *list = NULL; + /* allocate memory for hostgroup name list */ if((hostgroup_names = (char *)strdup(hostgroups)) == NULL) return ERROR; @@ -12275,8 +9173,7 @@ int xodtemplate_expand_hostgroups(xodtemplate_memberlist **list, xodtemplate_mem if(temp_hostgroup->register_object == FALSE) continue; - /* add hostgroup members to list */ - xodtemplate_add_hostgroup_members_to_memberlist(list, temp_hostgroup, _config_file, _start_line); + add_object_to_objectlist(list, temp_hostgroup); } /* free memory allocated to compiled regexp */ @@ -12298,7 +9195,7 @@ int xodtemplate_expand_hostgroups(xodtemplate_memberlist **list, xodtemplate_mem continue; /* add hostgroup to list */ - xodtemplate_add_hostgroup_members_to_memberlist(list, temp_hostgroup, _config_file, _start_line); + add_object_to_objectlist(list, temp_hostgroup); } } @@ -12314,11 +9211,15 @@ int xodtemplate_expand_hostgroups(xodtemplate_memberlist **list, xodtemplate_mem /* find the hostgroup */ temp_hostgroup = xodtemplate_find_real_hostgroup(temp_ptr); if(temp_hostgroup != NULL) { - found_match = TRUE; - /* add hostgroup members to proper list */ - xodtemplate_add_hostgroup_members_to_memberlist((reject_item == TRUE) ? reject_list : list, temp_hostgroup, _config_file, _start_line); + if(reject_item) { + bitmap_unite(reject_map, temp_hostgroup->member_map); + } + else { + /* add hostgroup members to proper list */ + add_object_to_objectlist(list, temp_hostgroup); + } } } } @@ -12341,8 +9242,7 @@ int xodtemplate_expand_hostgroups(xodtemplate_memberlist **list, xodtemplate_mem /* expands hosts */ -int xodtemplate_expand_hosts(xodtemplate_memberlist **list, xodtemplate_memberlist **reject_list, char *hosts, int _config_file, int _start_line) { - char *host_names = NULL; +int xodtemplate_expand_hosts(objectlist **list, bitmap *reject_map, char *hosts, int _config_file, int _start_line) { char *temp_ptr = NULL; xodtemplate_host *temp_host = NULL; regex_t preg; @@ -12353,11 +9253,8 @@ int xodtemplate_expand_hosts(xodtemplate_memberlist **list, xodtemplate_memberli if(list == NULL || hosts == NULL) return ERROR; - if((host_names = (char *)strdup(hosts)) == NULL) - return ERROR; - /* expand each host name */ - for(temp_ptr = strtok(host_names, ","); temp_ptr; temp_ptr = strtok(NULL, ",")) { + for(temp_ptr = strtok(hosts, ","); temp_ptr; temp_ptr = strtok(NULL, ",")) { found_match = FALSE; reject_item = FALSE; @@ -12374,7 +9271,6 @@ int xodtemplate_expand_hosts(xodtemplate_memberlist **list, xodtemplate_memberli /* compile regular expression */ if(regcomp(&preg, temp_ptr, REG_EXTENDED)) { - my_free(host_names); return ERROR; } @@ -12395,7 +9291,7 @@ int xodtemplate_expand_hosts(xodtemplate_memberlist **list, xodtemplate_memberli continue; /* add host to list */ - xodtemplate_add_member_to_memberlist(list, temp_host->host_name, NULL); + add_object_to_objectlist(list, temp_host); } /* free memory allocated to compiled regexp */ @@ -12420,7 +9316,7 @@ int xodtemplate_expand_hosts(xodtemplate_memberlist **list, xodtemplate_memberli continue; /* add host to list */ - xodtemplate_add_member_to_memberlist(list, temp_host->host_name, NULL); + add_object_to_objectlist(list, temp_host); } } @@ -12440,7 +9336,12 @@ int xodtemplate_expand_hosts(xodtemplate_memberlist **list, xodtemplate_memberli found_match = TRUE; /* add host to list */ - xodtemplate_add_member_to_memberlist((reject_item == TRUE) ? reject_list : list, temp_ptr, NULL); + if(!reject_item) { + add_object_to_objectlist(list, temp_host); + } + else { + bitmap_set(reject_map, temp_host->id); + } } } } @@ -12451,9 +9352,6 @@ int xodtemplate_expand_hosts(xodtemplate_memberlist **list, xodtemplate_memberli } } - /* free memory */ - my_free(host_names); - if(found_match == FALSE) return ERROR; @@ -12461,94 +9359,13 @@ int xodtemplate_expand_hosts(xodtemplate_memberlist **list, xodtemplate_memberli } -/* adds members of a hostgroups to the list of expanded (accepted) or rejected hosts */ -int xodtemplate_add_hostgroup_members_to_memberlist(xodtemplate_memberlist **list, xodtemplate_hostgroup *temp_hostgroup, int _config_file, int _start_line) { - char *group_members = NULL; - char *member_name = NULL; - char *member_ptr = NULL; - - if(list == NULL || temp_hostgroup == NULL) - return ERROR; - - /* if we have no members, just return. Empty hostgroups are ok */ - if(temp_hostgroup->members == NULL) { - return OK; - } - - /* save a copy of the members */ - if((group_members = (char *)strdup(temp_hostgroup->members)) == NULL) - return ERROR; - - /* process all hosts that belong to the hostgroup */ - /* NOTE: members of the group have already have been expanded by xodtemplate_recombobulate_hostgroups(), so we don't need to do it here */ - member_ptr = group_members; - for(member_name = my_strsep(&member_ptr, ","); member_name != NULL; member_name = my_strsep(&member_ptr, ",")) { - - /* strip trailing spaces from member name */ - strip(member_name); - - /* add host to the list */ - xodtemplate_add_member_to_memberlist(list, member_name, NULL); - } - - my_free(group_members); - - return OK; - } - - - -/* expands a comma-delimited list of servicegroups and/or service descriptions */ -xodtemplate_memberlist *xodtemplate_expand_servicegroups_and_services(char *servicegroups, char *host_name, char *services, int _config_file, int _start_line) { - xodtemplate_memberlist *temp_list = NULL; - xodtemplate_memberlist *reject_list = NULL; - xodtemplate_memberlist *list_ptr = NULL; - xodtemplate_memberlist *reject_ptr = NULL; - int result = OK; - - /* process list of servicegroups... */ - if(servicegroups != NULL) { - - /* expand servicegroups */ - result = xodtemplate_expand_servicegroups(&temp_list, &reject_list, servicegroups, _config_file, _start_line); - if(result != OK) { - xodtemplate_free_memberlist(&temp_list); - xodtemplate_free_memberlist(&reject_list); - return NULL; - } - } - - /* process service names */ - if(host_name != NULL && services != NULL) { - - /* expand services */ - result = xodtemplate_expand_services(&temp_list, &reject_list, host_name, services, _config_file, _start_line); - if(result != OK) { - xodtemplate_free_memberlist(&temp_list); - xodtemplate_free_memberlist(&reject_list); - return NULL; - } - } - - /* remove rejects (if any) from the list (no duplicate entries exist in either list) */ - /* NOTE: rejects from this list also affect hosts generated from processing hostgroup names (see above) */ - for(reject_ptr = reject_list; reject_ptr != NULL; reject_ptr = reject_ptr->next) { - for(list_ptr = temp_list; list_ptr != NULL; list_ptr = list_ptr->next) { - if(!strcmp(reject_ptr->name1, list_ptr->name1) && !strcmp(reject_ptr->name2, list_ptr->name2)) { - xodtemplate_remove_memberlist_item(list_ptr, &temp_list); - break; - } - } - } - xodtemplate_free_memberlist(&reject_list); - reject_list = NULL; - - return temp_list; - } - - -/* expands servicegroups */ -int xodtemplate_expand_servicegroups(xodtemplate_memberlist **list, xodtemplate_memberlist **reject_list, char *servicegroups, int _config_file, int _start_line) { +/* + * expands servicegroups. + * list will hold all selected servicegroups. + * reject will map services from all rejected servicegroups + * This can only be called after servicegroups are recombobulated. + */ +int xodtemplate_expand_servicegroups(objectlist **list, bitmap *reject, char *servicegroups, int _config_file, int _start_line) { xodtemplate_servicegroup *temp_servicegroup = NULL; regex_t preg; char *servicegroup_names = NULL; @@ -12606,8 +9423,8 @@ int xodtemplate_expand_servicegroups(xodtemplate_memberlist **list, xodtemplate_ if(temp_servicegroup->register_object == FALSE) continue; - /* add servicegroup members to list */ - xodtemplate_add_servicegroup_members_to_memberlist(list, temp_servicegroup, _config_file, _start_line); + /* add servicegroup to list */ + add_object_to_objectlist(list, temp_servicegroup); } /* free memory allocated to compiled regexp */ @@ -12629,7 +9446,7 @@ int xodtemplate_expand_servicegroups(xodtemplate_memberlist **list, xodtemplate_ continue; /* add servicegroup to list */ - xodtemplate_add_servicegroup_members_to_memberlist(list, temp_servicegroup, _config_file, _start_line); + prepend_object_to_objectlist(list, temp_servicegroup); } } @@ -12648,7 +9465,10 @@ int xodtemplate_expand_servicegroups(xodtemplate_memberlist **list, xodtemplate_ found_match = TRUE; /* add servicegroup members to list */ - xodtemplate_add_servicegroup_members_to_memberlist((reject_item == TRUE) ? reject_list : list, temp_servicegroup, _config_file, _start_line); + if(reject_item) + bitmap_unite(reject, temp_servicegroup->member_map); + else + add_object_to_objectlist(list, temp_servicegroup); } } } @@ -12669,24 +9489,63 @@ int xodtemplate_expand_servicegroups(xodtemplate_memberlist **list, xodtemplate_ return OK; } - /* expands services (host name is not expanded) */ -int xodtemplate_expand_services(xodtemplate_memberlist **list, xodtemplate_memberlist **reject_list, char *host_name, char *services, int _config_file, int _start_line) { +int xodtemplate_expand_services(objectlist **list, bitmap *reject_map, char *host_name, char *services, int _config_file, int _start_line) { char *service_names = NULL; char *temp_ptr = NULL; xodtemplate_service *temp_service = NULL; +#ifndef NSCGI regex_t preg; regex_t preg2; - int found_match = TRUE; - int reject_item = FALSE; int use_regexp_host = FALSE; int use_regexp_service = FALSE; +#endif + int found_match = TRUE; + int reject_item = FALSE; if(list == NULL) return ERROR; + + /* + * One-step recursion for convenience. + * Useful for servicegroups' "members" directive + */ + if(host_name == NULL && services != NULL) { + char *scopy, *next_p, *p1, *p2; + + if (!(scopy = strdup(services))) + return ERROR; + for(next_p = p1 = scopy; next_p; p1 = next_p + 1) { + p2 = strchr(p1, ','); + if (!p2) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Service description missing from list '%s' (config file '%s', starting at line %d)\n", + services, xodtemplate_config_file_name(_config_file), _start_line); + free(scopy); + return ERROR; + } + *p2 = 0; + while(!*p2 || *p2 == ' ' || *p2 == '\t') + p2++; + while(*p1 == ',' || *p1 == ' ' || *p1 == '\t') + p1++; + next_p = strchr(p2 + 1, ','); + if(next_p) + *next_p = 0; + strip(p1); + strip(p2); + + /* now we have arguments we can handle safely, so do that */ + if(xodtemplate_expand_services(list, reject_map, p1, p2, _config_file, _start_line) != OK) { + free(scopy); + return ERROR; + } + } + free(scopy); + } if(host_name == NULL || services == NULL) return OK; +#ifndef NSCGI /* should we use regular expression matching for the host name? */ if(use_regexp_matches == TRUE && (use_true_regexp_matching == TRUE || strstr(host_name, "*") || strstr(host_name, "?") || strstr(host_name, "+") || strstr(host_name, "\\."))) use_regexp_host = TRUE; @@ -12696,10 +9555,13 @@ int xodtemplate_expand_services(xodtemplate_memberlist **list, xodtemplate_membe if(regcomp(&preg2, host_name, REG_EXTENDED)) return ERROR; } +#endif if((service_names = (char *)strdup(services)) == NULL) { +#ifndef NSCGI if(use_regexp_host == TRUE) regfree(&preg2); +#endif return ERROR; } @@ -12712,6 +9574,7 @@ int xodtemplate_expand_services(xodtemplate_memberlist **list, xodtemplate_membe /* strip trailing spaces */ strip(temp_ptr); +#ifndef NSCGI /* should we use regular expression matching for the service description? */ if(use_regexp_matches == TRUE && (use_true_regexp_matching == TRUE || strstr(temp_ptr, "*") || strstr(temp_ptr, "?") || strstr(temp_ptr, "+") || strstr(temp_ptr, "\\."))) use_regexp_service = TRUE; @@ -12764,7 +9627,7 @@ int xodtemplate_expand_services(xodtemplate_memberlist **list, xodtemplate_membe continue; /* add service to the list */ - xodtemplate_add_member_to_memberlist(list, host_name, temp_service->service_description); + add_object_to_objectlist(list, temp_service); } /* free memory allocated to compiled regexp */ @@ -12773,121 +9636,68 @@ int xodtemplate_expand_services(xodtemplate_memberlist **list, xodtemplate_membe } /* use standard matching... */ - else { - + else if(!strcmp(temp_ptr, "*")) { /* return a list of all services on the host */ - if(!strcmp(temp_ptr, "*")) { - found_match = TRUE; + found_match = TRUE; - for(temp_service = xodtemplate_service_list; temp_service != NULL; temp_service = temp_service->next) { + for(temp_service = xodtemplate_service_list; temp_service != NULL; temp_service = temp_service->next) { - if(temp_service->host_name == NULL || temp_service->service_description == NULL) - continue; + if(temp_service->host_name == NULL || temp_service->service_description == NULL) + continue; - if(strcmp(temp_service->host_name, host_name)) - continue; + if(strcmp(temp_service->host_name, host_name)) + continue; - /* dont' add services that shouldn't be registered */ - if(temp_service->register_object == FALSE) - continue; + /* dont' add services that shouldn't be registered */ + if(temp_service->register_object == FALSE) + continue; - /* add service to the list */ - xodtemplate_add_member_to_memberlist(list, host_name, temp_service->service_description); - } - } - - /* else this is just a single service... */ - else { - - /* this service should be excluded (rejected) */ - if(temp_ptr[0] == '!') { - reject_item = TRUE; - temp_ptr++; - } - - /* find the service */ - if((temp_service = xodtemplate_find_real_service(host_name, temp_ptr)) != NULL) { - - found_match = TRUE; - - /* add service to the list */ - xodtemplate_add_member_to_memberlist((reject_item == TRUE) ? reject_list : list, host_name, temp_service->service_description); - } + /* add service to the list */ + add_object_to_objectlist(list, temp_service); } } + /* else this is just a single service... */ + else { + + /* this service should be excluded (rejected) */ + if(temp_ptr[0] == '!') { + reject_item = TRUE; + temp_ptr++; + } + +#endif + /* find the service */ + if((temp_service = xodtemplate_find_real_service(host_name, temp_ptr)) != NULL) { + + found_match = TRUE; + + if(reject_item == TRUE) + bitmap_set(reject_map, temp_service->id); + else + add_object_to_objectlist(list, temp_service); + } +#ifndef NSCGI + } +#endif /* we didn't find a match */ if(found_match == FALSE && reject_item == FALSE) { logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not find a service matching host name '%s' and description '%s' (config file '%s', starting on line %d)\n", host_name, temp_ptr, xodtemplate_config_file_name(_config_file), _start_line); break; } } - +#ifndef NSCGI if(use_regexp_host == TRUE) regfree(&preg2); my_free(service_names); - +#endif if(found_match == FALSE && reject_item == FALSE) return ERROR; return OK; } - -/* adds members of a servicegroups to the list of expanded services */ -int xodtemplate_add_servicegroup_members_to_memberlist(xodtemplate_memberlist **list, xodtemplate_servicegroup *temp_servicegroup, int _config_file, int _start_line) { - char *group_members = NULL; - char *member_name = NULL; - char *host_name = NULL; - char *member_ptr = NULL; - - if(list == NULL || temp_servicegroup == NULL) - return ERROR; - - /* if we have no members, just return. Empty servicegroups are ok */ - if(temp_servicegroup->members == NULL) { - return OK; - } - - /* save a copy of the members */ - if((group_members = (char *)strdup(temp_servicegroup->members)) == NULL) - return ERROR; - - /* process all services that belong to the servicegroup */ - /* NOTE: members of the group have already have been expanded by xodtemplate_recombobulate_servicegroups(), so we don't need to do it here */ - member_ptr = group_members; - for(member_name = my_strsep(&member_ptr, ","); member_name != NULL; member_name = my_strsep(&member_ptr, ",")) { - - /* strip trailing spaces from member name */ - strip(member_name); - - /* host name */ - if(host_name == NULL) { - if((host_name = (char *)strdup(member_name)) == NULL) { - my_free(group_members); - return ERROR; - } - } - - /* service description */ - else { - - /* add service to the list */ - xodtemplate_add_member_to_memberlist(list, host_name, member_name); - - my_free(host_name); - } - } - - my_free(group_members); - - return OK; - } - - - - /* returns a comma-delimited list of hostgroup names */ char * xodtemplate_process_hostgroup_names(char *hostgroups, int _config_file, int _start_line) { xodtemplate_memberlist *temp_list = NULL; @@ -13041,7 +9851,7 @@ int xodtemplate_get_hostgroup_names(xodtemplate_memberlist **list, xodtemplate_m found_match = TRUE; - /* add hostgroup members to proper list */ + /* add hostgroup to proper list */ xodtemplate_add_member_to_memberlist((reject_item == TRUE) ? reject_list : list, temp_hostgroup->hostgroup_name, NULL); } } @@ -13414,14 +10224,14 @@ int xodtemplate_get_servicegroup_names(xodtemplate_memberlist **list, xodtemplat return OK; } -#ifdef NSCORE +#ifndef NSCGI /******************************************************************/ /****************** ADDITIVE INHERITANCE STUFF ********************/ /******************************************************************/ /* determines the value of an inherited string */ -int xodtemplate_get_inherited_string(int *have_template_value, char **template_value, int *have_this_value, char **this_value) { +int xodtemplate_get_inherited_string(char *have_template_value, char **template_value, char *have_this_value, char **this_value) { char *buf = NULL; /* template has a value we should use */ @@ -13583,8 +10393,5 @@ int xodtemplate_clean_additive_strings(void) { return OK; } -#endif #endif - - diff --git a/xdata/xodtemplate.h b/xdata/xodtemplate.h index 2bea581..a73662a 100644 --- a/xdata/xodtemplate.h +++ b/xdata/xodtemplate.h @@ -2,8 +2,6 @@ * * XODTEMPLATE.H - Template-based object configuration data header file * - * Copyright (c) 2001-2008 Ethan Galstad (egalstad@nagios.org) - * Last Modified: 02-17-2008 * * License: * @@ -23,8 +21,8 @@ *****************************************************************************/ -#ifndef _XODTEMPLATE_H -#define _XODTEMPLATE_H +#ifndef NAGIOS_XODTEMPLATE_H_INCLUDED +#define NAGIOS_XODTEMPLATE_H_INCLUDED @@ -45,34 +43,20 @@ #define XODTEMPLATE_HOSTGROUP 6 #define XODTEMPLATE_SERVICE 7 #define XODTEMPLATE_SERVICEDEPENDENCY 8 -#define XODTEMPLATE_HOSTGROUPESCALATION 9 /* no longer implemented */ -#define XODTEMPLATE_SERVICEESCALATION 10 -#define XODTEMPLATE_HOSTESCALATION 11 -#define XODTEMPLATE_HOSTDEPENDENCY 12 -#define XODTEMPLATE_HOSTEXTINFO 13 -#define XODTEMPLATE_SERVICEEXTINFO 14 -#define XODTEMPLATE_SERVICEGROUP 15 +#define XODTEMPLATE_SERVICEESCALATION 9 +#define XODTEMPLATE_HOSTESCALATION 10 +#define XODTEMPLATE_HOSTDEPENDENCY 11 +#define XODTEMPLATE_HOSTEXTINFO 12 +#define XODTEMPLATE_SERVICEEXTINFO 13 +#define XODTEMPLATE_SERVICEGROUP 14 /***************** SKIP LISTS ****************/ -#define NUM_XOBJECT_SKIPLISTS 15 - -#define X_HOST_SKIPLIST 1 -#define X_SERVICE_SKIPLIST 2 -#define X_COMMAND_SKIPLIST 3 -#define X_TIMEPERIOD_SKIPLIST 4 -#define X_CONTACT_SKIPLIST 5 -#define X_CONTACTGROUP_SKIPLIST 6 -#define X_HOSTGROUP_SKIPLIST 7 -#define X_SERVICEGROUP_SKIPLIST 8 -#define X_HOSTDEPENDENCY_SKIPLIST 9 -#define X_SERVICEDEPENDENCY_SKIPLIST 10 -#define X_HOSTESCALATION_SKIPLIST 11 -#define X_SERVICEESCALATION_SKIPLIST 12 -#define X_HOSTEXTINFO_SKIPLIST 13 -#define X_SERVICEEXTINFO_SKIPLIST 14 +#define HOSTEXTINFO_SKIPLIST (NUM_OBJECT_SKIPLISTS) +#define SERVICEEXTINFO_SKIPLIST (NUM_OBJECT_SKIPLISTS + 1) +#define NUM_XOBJECT_SKIPLISTS (NUM_OBJECT_SKIPLISTS + 2) /********** STRUCTURE DEFINITIONS **********/ @@ -117,8 +101,8 @@ typedef struct xodtemplate_timeperiod_struct { xodtemplate_daterange *exceptions[DATERANGE_TYPES]; char *exclusions; - int has_been_resolved; - int register_object; + unsigned has_been_resolved : 1; + unsigned register_object : 1; struct xodtemplate_timeperiod_struct *next; } xodtemplate_timeperiod; @@ -133,14 +117,15 @@ typedef struct xodtemplate_command_struct { char *command_name; char *command_line; - int has_been_resolved; - int register_object; + unsigned has_been_resolved : 1; + unsigned register_object : 1; struct xodtemplate_command_struct *next; } xodtemplate_command; /* CONTACT TEMPLATE STRUCTURE */ typedef struct xodtemplate_contact_struct { + unsigned int id; char *template; char *name; int _config_file; @@ -154,45 +139,38 @@ typedef struct xodtemplate_contact_struct { char *address[MAX_XODTEMPLATE_CONTACT_ADDRESSES]; char *host_notification_period; char *host_notification_commands; - int notify_on_host_down; - int notify_on_host_unreachable; - int notify_on_host_recovery; - int notify_on_host_flapping; - int notify_on_host_downtime; + int host_notification_options; char *service_notification_period; char *service_notification_commands; - int notify_on_service_unknown; - int notify_on_service_warning; - int notify_on_service_critical; - int notify_on_service_recovery; - int notify_on_service_flapping; - int notify_on_service_downtime; + int service_notification_options; int host_notifications_enabled; int service_notifications_enabled; int can_submit_commands; int retain_status_information; int retain_nonstatus_information; + unsigned int minimum_value; xodtemplate_customvariablesmember *custom_variables; - int have_contact_groups; - int have_email; - int have_pager; - int have_address[MAX_XODTEMPLATE_CONTACT_ADDRESSES]; - int have_host_notification_period; - int have_host_notification_commands; - int have_service_notification_period; - int have_service_notification_commands; + char have_contact_groups; + char have_email; + char have_pager; + char have_address[MAX_XODTEMPLATE_CONTACT_ADDRESSES]; + char have_host_notification_period; + char have_host_notification_commands; + char have_service_notification_period; + char have_service_notification_commands; - int have_host_notification_options; - int have_service_notification_options; - int have_host_notifications_enabled; - int have_service_notifications_enabled; - int have_can_submit_commands; - int have_retain_status_information; - int have_retain_nonstatus_information; + char have_host_notification_options; + char have_service_notification_options; + char have_host_notifications_enabled; + char have_service_notifications_enabled; + char have_can_submit_commands; + char have_retain_status_information; + char have_retain_nonstatus_information; + unsigned have_minimum_value : 1; - int has_been_resolved; - int register_object; + unsigned has_been_resolved : 1; + unsigned register_object : 1; struct xodtemplate_contact_struct *next; } xodtemplate_contact; @@ -208,18 +186,24 @@ typedef struct xodtemplate_contactgroup_struct { char *alias; char *members; char *contactgroup_members; + objectlist *member_list; + objectlist *group_list; + bitmap *member_map; + bitmap *reject_map; + int loop_status; - int have_members; - int have_contactgroup_members; + char have_members; + char have_contactgroup_members; - int has_been_resolved; - int register_object; + unsigned has_been_resolved : 1; + unsigned register_object : 1; struct xodtemplate_contactgroup_struct *next; } xodtemplate_contactgroup; /* HOST TEMPLATE STRUCTURE */ typedef struct xodtemplate_host_struct { + unsigned int id; char *template; char *name; int _config_file; @@ -233,13 +217,14 @@ typedef struct xodtemplate_host_struct { char *host_groups; char *check_command; char *check_period; + unsigned int hourly_value; int initial_state; double check_interval; double retry_interval; int max_check_attempts; int active_checks_enabled; int passive_checks_enabled; - int obsess_over_host; + int obsess; char *event_handler; int event_handler_enabled; int check_freshness; @@ -247,26 +232,16 @@ typedef struct xodtemplate_host_struct { float low_flap_threshold; float high_flap_threshold; int flap_detection_enabled; - int flap_detection_on_up; - int flap_detection_on_down; - int flap_detection_on_unreachable; + int flap_detection_options; char *contact_groups; char *contacts; - int notify_on_down; - int notify_on_unreachable; - int notify_on_recovery; - int notify_on_flapping; - int notify_on_downtime; + int notification_options; int notifications_enabled; char *notification_period; double notification_interval; double first_notification_delay; - int stalk_on_up; - int stalk_on_down; - int stalk_on_unreachable; + int stalking_options; int process_perf_data; - int failure_prediction_enabled; - char *failure_prediction_options; char *notes; char *notes_url; char *action_url; @@ -283,52 +258,53 @@ typedef struct xodtemplate_host_struct { int retain_nonstatus_information; xodtemplate_customvariablesmember *custom_variables; - int have_display_name; - int have_parents; - int have_host_groups; - int have_check_command; - int have_check_period; - int have_event_handler; - int have_contact_groups; - int have_contacts; - int have_notification_period; - int have_failure_prediction_options; - int have_notes; - int have_notes_url; - int have_action_url; - int have_icon_image; - int have_icon_image_alt; - int have_vrml_image; - int have_statusmap_image; + /* these can't be bitfields */ + char have_host_groups; + char have_contact_groups; + char have_contacts; + char have_parents; - int have_initial_state; - int have_check_interval; - int have_retry_interval; - int have_max_check_attempts; - int have_active_checks_enabled; - int have_passive_checks_enabled; - int have_obsess_over_host; - int have_event_handler_enabled; - int have_check_freshness; - int have_freshness_threshold; - int have_low_flap_threshold; - int have_high_flap_threshold; - int have_flap_detection_enabled; - int have_flap_detection_options; - int have_notification_options; - int have_notifications_enabled; - int have_notification_interval; - int have_first_notification_delay; - int have_stalking_options; - int have_process_perf_data; - int have_failure_prediction_enabled; - int have_2d_coords; - int have_3d_coords; - int have_retain_status_information; - int have_retain_nonstatus_information; + unsigned have_display_name : 1; + unsigned have_check_command : 1; + unsigned have_check_period : 1; + unsigned have_event_handler : 1; + unsigned have_notification_period : 1; + unsigned have_notes : 1; + unsigned have_notes_url : 1; + unsigned have_action_url : 1; + unsigned have_icon_image : 1; + unsigned have_icon_image_alt : 1; + unsigned have_vrml_image : 1; + unsigned have_statusmap_image : 1; - int has_been_resolved; - int register_object; + unsigned have_initial_state : 1; + unsigned have_check_interval : 1; + unsigned have_retry_interval : 1; + unsigned have_max_check_attempts : 1; + unsigned have_active_checks_enabled : 1; + unsigned have_passive_checks_enabled : 1; + unsigned have_obsess : 1; + unsigned have_event_handler_enabled : 1; + unsigned have_check_freshness : 1; + unsigned have_freshness_threshold : 1; + unsigned have_low_flap_threshold : 1; + unsigned have_high_flap_threshold : 1; + unsigned have_flap_detection_enabled : 1; + unsigned have_flap_detection_options : 1; + unsigned have_notification_options : 1; + unsigned have_notifications_enabled : 1; + unsigned have_notification_interval : 1; + unsigned have_first_notification_delay : 1; + unsigned have_stalking_options : 1; + unsigned have_process_perf_data : 1; + unsigned have_2d_coords : 1; + unsigned have_3d_coords : 1; + unsigned have_retain_status_information : 1; + unsigned have_retain_nonstatus_information : 1; + unsigned have_hourly_value : 1; + + unsigned has_been_resolved : 1; + unsigned register_object : 1; struct xodtemplate_host_struct *next; } xodtemplate_host; @@ -347,21 +323,27 @@ typedef struct xodtemplate_hostgroup_struct { char *notes; char *notes_url; char *action_url; + objectlist *member_list; + objectlist *group_list; + bitmap *member_map; + bitmap *reject_map; + int loop_status; - int have_members; - int have_hostgroup_members; - int have_notes; - int have_notes_url; - int have_action_url; + char have_members; + char have_hostgroup_members; + char have_notes; + char have_notes_url; + char have_action_url; - int has_been_resolved; - int register_object; + unsigned has_been_resolved : 1; + unsigned register_object : 1; struct xodtemplate_hostgroup_struct *next; } xodtemplate_hostgroup; /* SERVICE TEMPLATE STRUCTURE */ typedef struct xodtemplate_service_struct { + unsigned int id; char *template; char *name; int _config_file; @@ -370,6 +352,7 @@ typedef struct xodtemplate_service_struct { char *host_name; char *service_description; char *display_name; + char *parents; char *hostgroup_name; char *service_groups; char *check_command; @@ -378,11 +361,12 @@ typedef struct xodtemplate_service_struct { double check_interval; double retry_interval; char *check_period; + unsigned int hourly_value; int active_checks_enabled; int passive_checks_enabled; int parallelize_check; int is_volatile; - int obsess_over_service; + int obsess; char *event_handler; int event_handler_enabled; int check_freshness; @@ -390,29 +374,16 @@ typedef struct xodtemplate_service_struct { double low_flap_threshold; double high_flap_threshold; int flap_detection_enabled; - int flap_detection_on_ok; - int flap_detection_on_warning; - int flap_detection_on_unknown; - int flap_detection_on_critical; - int notify_on_unknown; - int notify_on_warning; - int notify_on_critical; - int notify_on_recovery; - int notify_on_flapping; - int notify_on_downtime; + int flap_detection_options; + int notification_options; int notifications_enabled; char *notification_period; double notification_interval; double first_notification_delay; char *contact_groups; char *contacts; - int stalk_on_ok; - int stalk_on_unknown; - int stalk_on_warning; - int stalk_on_critical; + int stalking_options; int process_perf_data; - int failure_prediction_enabled; - char *failure_prediction_options; char *notes; char *notes_url; char *action_url; @@ -422,54 +393,58 @@ typedef struct xodtemplate_service_struct { int retain_nonstatus_information; xodtemplate_customvariablesmember *custom_variables; - int have_host_name; - int have_service_description; - int have_display_name; - int have_hostgroup_name; - int have_service_groups; - int have_check_command; - int have_important_check_command; - int have_check_period; - int have_event_handler; - int have_notification_period; - int have_contact_groups; - int have_contacts; - int have_failure_prediction_options; - int have_notes; - int have_notes_url; - int have_action_url; - int have_icon_image; - int have_icon_image_alt; + /* these can't be bitfields */ + char have_parents; + char have_contact_groups; + char have_contacts; + char have_host_name; + char have_hostgroup_name; + char have_service_groups; - int have_initial_state; - int have_max_check_attempts; - int have_check_interval; - int have_retry_interval; - int have_active_checks_enabled; - int have_passive_checks_enabled; - int have_parallelize_check; - int have_is_volatile; - int have_obsess_over_service; - int have_event_handler_enabled; - int have_check_freshness; - int have_freshness_threshold; - int have_low_flap_threshold; - int have_high_flap_threshold; - int have_flap_detection_enabled; - int have_flap_detection_options; - int have_notification_options; - int have_notifications_enabled; - int have_notification_dependencies; - int have_notification_interval; - int have_first_notification_delay; - int have_stalking_options; - int have_process_perf_data; - int have_failure_prediction_enabled; - int have_retain_status_information; - int have_retain_nonstatus_information; + unsigned have_service_description : 1; + unsigned have_display_name : 1; + unsigned have_check_command : 1; + unsigned have_important_check_command : 1; + unsigned have_check_period : 1; + unsigned have_event_handler : 1; + unsigned have_notification_period : 1; + unsigned have_notes : 1; + unsigned have_notes_url : 1; + unsigned have_action_url : 1; + unsigned have_icon_image : 1; + unsigned have_icon_image_alt : 1; - int has_been_resolved; - int register_object; + unsigned have_initial_state : 1; + unsigned have_max_check_attempts : 1; + unsigned have_check_interval : 1; + unsigned have_retry_interval : 1; + unsigned have_active_checks_enabled : 1; + unsigned have_passive_checks_enabled : 1; + unsigned have_parallelize_check : 1; + unsigned have_is_volatile : 1; + unsigned have_obsess : 1; + unsigned have_event_handler_enabled : 1; + unsigned have_check_freshness : 1; + unsigned have_freshness_threshold : 1; + unsigned have_low_flap_threshold : 1; + unsigned have_high_flap_threshold : 1; + unsigned have_flap_detection_enabled : 1; + unsigned have_flap_detection_options : 1; + unsigned have_notification_options : 1; + unsigned have_notifications_enabled : 1; + unsigned have_notification_dependencies : 1; + unsigned have_notification_interval : 1; + unsigned have_first_notification_delay : 1; + unsigned have_stalking_options : 1; + unsigned have_process_perf_data : 1; + unsigned have_retain_status_information : 1; + unsigned have_retain_nonstatus_information : 1; + unsigned have_hourly_value : 1; + unsigned is_from_hostgroup : 1; + + unsigned is_copy : 1; + unsigned has_been_resolved : 1; + unsigned register_object : 1; struct xodtemplate_service_struct *next; } xodtemplate_service; @@ -488,15 +463,20 @@ typedef struct xodtemplate_servicegroup_struct { char *notes; char *notes_url; char *action_url; + objectlist *member_list; + objectlist *group_list; + bitmap *member_map; + bitmap *reject_map; + int loop_status; - int have_members; - int have_servicegroup_members; - int have_notes; - int have_notes_url; - int have_action_url; + char have_members; + char have_servicegroup_members; + char have_notes; + char have_notes_url; + char have_action_url; - int has_been_resolved; - int register_object; + unsigned has_been_resolved : 1; + unsigned register_object : 1; struct xodtemplate_servicegroup_struct *next; } xodtemplate_servicegroup; @@ -518,33 +498,26 @@ typedef struct xodtemplate_servicedependency_struct { char *dependent_hostgroup_name; char *dependency_period; int inherits_parent; - int fail_notify_on_ok; - int fail_notify_on_unknown; - int fail_notify_on_warning; - int fail_notify_on_critical; - int fail_notify_on_pending; - int fail_execute_on_ok; - int fail_execute_on_unknown; - int fail_execute_on_warning; - int fail_execute_on_critical; - int fail_execute_on_pending; + int notification_failure_options; + int execution_failure_options; - int have_host_name; - int have_service_description; - int have_dependent_host_name; - int have_dependent_service_description; - int have_servicegroup_name; - int have_hostgroup_name; - int have_dependent_servicegroup_name; - int have_dependent_hostgroup_name; - int have_dependency_period; + char have_host_name; + char have_service_description; + char have_dependent_host_name; + char have_dependent_service_description; + char have_servicegroup_name; + char have_hostgroup_name; + char have_dependent_servicegroup_name; + char have_dependent_hostgroup_name; + char have_dependency_period; - int have_inherits_parent; - int have_notification_dependency_options; - int have_execution_dependency_options; + char have_inherits_parent; + char have_notification_failure_options; + char have_execution_failure_options; - int has_been_resolved; - int register_object; + unsigned is_copy : 1; + unsigned has_been_resolved : 1; + unsigned register_object : 1; struct xodtemplate_servicedependency_struct *next; } xodtemplate_servicedependency; @@ -564,28 +537,26 @@ typedef struct xodtemplate_serviceescalation_struct { int last_notification; double notification_interval; char *escalation_period; - int escalate_on_warning; - int escalate_on_unknown; - int escalate_on_critical; - int escalate_on_recovery; + int escalation_options; char *contact_groups; char *contacts; - int have_host_name; - int have_service_description; - int have_servicegroup_name; - int have_hostgroup_name; - int have_escalation_period; - int have_contact_groups; - int have_contacts; + char have_host_name; + char have_service_description; + char have_servicegroup_name; + char have_hostgroup_name; + char have_escalation_period; + char have_contact_groups; + char have_contacts; - int have_first_notification; - int have_last_notification; - int have_notification_interval; - int have_escalation_options; + char have_first_notification; + char have_last_notification; + char have_notification_interval; + char have_escalation_options; - int has_been_resolved; - int register_object; + unsigned is_copy : 1; + unsigned has_been_resolved : 1; + unsigned register_object : 1; struct xodtemplate_serviceescalation_struct *next; } xodtemplate_serviceescalation; @@ -603,33 +574,29 @@ typedef struct xodtemplate_hostdependency_struct { char *dependent_hostgroup_name; char *dependency_period; int inherits_parent; - int fail_notify_on_up; - int fail_notify_on_down; - int fail_notify_on_unreachable; - int fail_notify_on_pending; - int fail_execute_on_up; - int fail_execute_on_down; - int fail_execute_on_unreachable; - int fail_execute_on_pending; + int notification_failure_options; + int execution_failure_options; - int have_host_name; - int have_dependent_host_name; - int have_hostgroup_name; - int have_dependent_hostgroup_name; - int have_dependency_period; + char have_host_name; + char have_dependent_host_name; + char have_hostgroup_name; + char have_dependent_hostgroup_name; + char have_dependency_period; - int have_inherits_parent; - int have_notification_dependency_options; - int have_execution_dependency_options; + char have_inherits_parent; + char have_notification_failure_options; + char have_execution_failure_options; - int has_been_resolved; - int register_object; + unsigned is_copy : 1; + unsigned has_been_resolved : 1; + unsigned register_object : 1; struct xodtemplate_hostdependency_struct *next; } xodtemplate_hostdependency; /* HOSTESCALATION TEMPLATE STRUCTURE */ typedef struct xodtemplate_hostescalation_struct { + unsigned int id; char *template; char *name; int _config_file; @@ -641,25 +608,24 @@ typedef struct xodtemplate_hostescalation_struct { int last_notification; double notification_interval; char *escalation_period; - int escalate_on_down; - int escalate_on_unreachable; - int escalate_on_recovery; + int escalation_options; char *contact_groups; char *contacts; - int have_host_name; - int have_hostgroup_name; - int have_escalation_period; - int have_contact_groups; - int have_contacts; + char have_host_name; + char have_hostgroup_name; + char have_escalation_period; + char have_contact_groups; + char have_contacts; - int have_first_notification; - int have_last_notification; - int have_notification_interval; - int have_escalation_options; + char have_first_notification; + char have_last_notification; + char have_notification_interval; + char have_escalation_options; - int has_been_resolved; - int register_object; + unsigned is_copy : 1; + unsigned has_been_resolved : 1; + unsigned register_object : 1; struct xodtemplate_hostescalation_struct *next; } xodtemplate_hostescalation; @@ -686,21 +652,21 @@ typedef struct xodtemplate_hostextinfo_struct { double y_3d; double z_3d; - int have_host_name; - int have_hostgroup_name; - int have_notes; - int have_notes_url; - int have_action_url; - int have_icon_image; - int have_icon_image_alt; - int have_vrml_image; - int have_statusmap_image; + char have_host_name; + char have_hostgroup_name; + char have_notes; + char have_notes_url; + char have_action_url; + char have_icon_image; + char have_icon_image_alt; + char have_vrml_image; + char have_statusmap_image; - int have_2d_coords; - int have_3d_coords; + char have_2d_coords; + char have_3d_coords; - int has_been_resolved; - int register_object; + unsigned has_been_resolved : 1; + unsigned register_object : 1; struct xodtemplate_hostextinfo_struct *next; } xodtemplate_hostextinfo; @@ -721,17 +687,17 @@ typedef struct xodtemplate_serviceextinfo_struct { char *icon_image; char *icon_image_alt; - int have_host_name; - int have_hostgroup_name; - int have_service_description; - int have_notes; - int have_notes_url; - int have_action_url; - int have_icon_image; - int have_icon_image_alt; + char have_host_name; + char have_hostgroup_name; + char have_service_description; + char have_notes; + char have_notes_url; + char have_action_url; + char have_icon_image; + char have_icon_image_alt; - int has_been_resolved; - int register_object; + unsigned has_been_resolved : 1; + unsigned register_object : 1; struct xodtemplate_serviceextinfo_struct *next; } xodtemplate_serviceextinfo; @@ -777,26 +743,19 @@ typedef struct xodtemplate_service_cursor_struct { /********* FUNCTION DEFINITIONS **********/ -int xodtemplate_read_config_data(char *, int, int, int); /* top-level routine processes all config files */ -int xodtemplate_grab_config_info(char *); /* grabs variables from main config file */ +int xodtemplate_read_config_data(const char *, int); /* top-level routine processes all config files */ int xodtemplate_process_config_file(char *, int); /* process data in a specific config file */ int xodtemplate_process_config_dir(char *, int); /* process all files in a specific config directory */ -#ifdef NSCORE -xodtemplate_memberlist *xodtemplate_expand_contactgroups_and_contacts(char *, char *, int, int); -int xodtemplate_expand_contactgroups(xodtemplate_memberlist **, xodtemplate_memberlist **, char *, int, int); -int xodtemplate_expand_contacts(xodtemplate_memberlist **, xodtemplate_memberlist **, char *, int, int); -int xodtemplate_add_contactgroup_members_to_memberlist(xodtemplate_memberlist **, xodtemplate_contactgroup *, int, int); +int xodtemplate_expand_services(objectlist **, bitmap *, char *, char *, int, int); +int xodtemplate_expand_contactgroups(objectlist **, bitmap *, char *, int, int); +int xodtemplate_expand_contacts(objectlist **, bitmap *, char *, int, int); -xodtemplate_memberlist *xodtemplate_expand_hostgroups_and_hosts(char *, char *, int, int); -int xodtemplate_expand_hostgroups(xodtemplate_memberlist **, xodtemplate_memberlist **, char *, int, int); -int xodtemplate_expand_hosts(xodtemplate_memberlist **, xodtemplate_memberlist **, char *, int, int); -int xodtemplate_add_hostgroup_members_to_memberlist(xodtemplate_memberlist **, xodtemplate_hostgroup *, int, int); +objectlist *xodtemplate_expand_hostgroups_and_hosts(char *, char *, int, int); +int xodtemplate_expand_hostgroups(objectlist **, bitmap *, char *, int, int); +int xodtemplate_expand_hosts(objectlist **list, bitmap *reject_map, char *, int, int); -xodtemplate_memberlist *xodtemplate_expand_servicegroups_and_services(char *, char *, char *, int, int); -int xodtemplate_expand_servicegroups(xodtemplate_memberlist **, xodtemplate_memberlist **, char *, int, int); -int xodtemplate_expand_services(xodtemplate_memberlist **, xodtemplate_memberlist **, char *, char *, int, int); -int xodtemplate_add_servicegroup_members_to_memberlist(xodtemplate_memberlist **, xodtemplate_servicegroup *, int, int); +int xodtemplate_expand_servicegroups(objectlist **, bitmap *, char *, int, int); char *xodtemplate_process_contactgroup_names(char *, int, int); int xodtemplate_get_contactgroup_names(xodtemplate_memberlist **, xodtemplate_memberlist **, char *, int, int); @@ -810,7 +769,6 @@ int xodtemplate_get_servicegroup_names(xodtemplate_memberlist **, xodtemplate_me int xodtemplate_add_member_to_memberlist(xodtemplate_memberlist **, char *, char *); int xodtemplate_free_memberlist(xodtemplate_memberlist **); void xodtemplate_remove_memberlist_item(xodtemplate_memberlist *, xodtemplate_memberlist **); -#endif int xodtemplate_begin_object_definition(char *, int, int, int); @@ -839,28 +797,22 @@ int xodtemplate_inherit_object_properties(void); int xodtemplate_resolve_objects(void); -int xodtemplate_sort_objects(void); -int xodtemplate_compare_strings1(char *, char *); -int xodtemplate_compare_strings2(char *, char *, char *, char *); - int xodtemplate_cache_objects(char *); -int xodtemplate_duplicate_service(xodtemplate_service *, char *); +int xodtemplate_duplicate_service(xodtemplate_service *, char *, int); int xodtemplate_duplicate_hostescalation(xodtemplate_hostescalation *, char *); int xodtemplate_duplicate_serviceescalation(xodtemplate_serviceescalation *, char *, char *); int xodtemplate_duplicate_hostdependency(xodtemplate_hostdependency *, char *, char *); -int xodtemplate_duplicate_servicedependency(xodtemplate_servicedependency *, char *, char *, char *, char *, char *, char *, char *, char *); +int xodtemplate_duplicate_servicedependency(xodtemplate_servicedependency *, char *, char *, char *, char *); int xodtemplate_duplicate_hostextinfo(xodtemplate_hostextinfo *, char *); int xodtemplate_duplicate_serviceextinfo(xodtemplate_serviceextinfo *, char *); +#endif int xodtemplate_recombobulate_contactgroups(void); -int xodtemplate_recombobulate_contactgroup_subgroups(xodtemplate_contactgroup *, char **); -int xodtemplate_recombobulate_object_contacts(void); int xodtemplate_recombobulate_hostgroups(void); -int xodtemplate_recombobulate_hostgroup_subgroups(xodtemplate_hostgroup *, char **); int xodtemplate_recombobulate_servicegroups(void); -int xodtemplate_recombobulate_servicegroup_subgroups(xodtemplate_servicegroup *, char **); +#ifdef NSCORE int xodtemplate_resolve_timeperiod(xodtemplate_timeperiod *); int xodtemplate_resolve_command(xodtemplate_command *); int xodtemplate_resolve_contactgroup(xodtemplate_contactgroup *); @@ -876,22 +828,10 @@ int xodtemplate_resolve_hostescalation(xodtemplate_hostescalation *); int xodtemplate_resolve_hostextinfo(xodtemplate_hostextinfo *); int xodtemplate_resolve_serviceextinfo(xodtemplate_serviceextinfo *); -int xodtemplate_sort_timeperiods(void); -int xodtemplate_sort_commands(void); -int xodtemplate_sort_contactgroups(void); -int xodtemplate_sort_hostgroups(void); -int xodtemplate_sort_servicegroups(void); -int xodtemplate_sort_contacts(void); -int xodtemplate_sort_hosts(void); -int xodtemplate_sort_services(void); -int xodtemplate_sort_servicedependencies(void); -int xodtemplate_sort_serviceescalations(void); -int xodtemplate_sort_hostdependencies(void); -int xodtemplate_sort_hostescalations(void); - int xodtemplate_merge_extinfo_ojects(void); int xodtemplate_merge_host_extinfo_object(xodtemplate_host *, xodtemplate_hostextinfo *); int xodtemplate_merge_service_extinfo_object(xodtemplate_service *, xodtemplate_serviceextinfo *); +#endif xodtemplate_timeperiod *xodtemplate_find_timeperiod(char *); xodtemplate_command *xodtemplate_find_command(char *); @@ -914,10 +854,9 @@ xodtemplate_hostescalation *xodtemplate_find_hostescalation(char *); xodtemplate_hostextinfo *xodtemplate_find_hostextinfo(char *); xodtemplate_serviceextinfo *xodtemplate_find_serviceextinfo(char *); -int xodtemplate_get_inherited_string(int *, char **, int *, char **); +int xodtemplate_get_inherited_string(char *, char **, char *, char **); int xodtemplate_clean_additive_string(char **); int xodtemplate_clean_additive_strings(void); -#endif int xodtemplate_register_timeperiod(xodtemplate_timeperiod *); int xodtemplate_get_time_ranges(char *, unsigned long *, unsigned long *); @@ -937,7 +876,6 @@ int xodtemplate_register_hostescalation(xodtemplate_hostescalation *); int xodtemplate_init_xobject_skiplists(void); int xodtemplate_free_xobject_skiplists(void); -int xodtemplate_skiplist_compare_text(const char *val1a, const char *val1b, const char *val2a, const char *val2b); int xodtemplate_skiplist_compare_host_template(void *a, void *b); int xodtemplate_skiplist_compare_service_template(void *a, void *b); int xodtemplate_skiplist_compare_command_template(void *a, void *b); @@ -966,7 +904,4 @@ int xodtemplate_skiplist_compare_servicedependency(void *a, void *b); int xodtemplate_skiplist_compare_hostescalation(void *a, void *b); int xodtemplate_skiplist_compare_serviceescalation(void *a, void *b); - #endif - - diff --git a/xdata/xpddefault.c b/xdata/xpddefault.c index 0da846a..3b05e05 100644 --- a/xdata/xpddefault.c +++ b/xdata/xpddefault.c @@ -2,8 +2,6 @@ * * XPDDEFAULT.C - Default performance data routines * - * Copyright (c) 2000-2008 Ethan Galstad (egalstad@nagios.org) - * Last Modified: 11-02-2008 * * License: * @@ -30,179 +28,18 @@ #include "../include/objects.h" #include "../include/macros.h" #include "../include/nagios.h" - - -/**** DATA INPUT-SPECIFIC HEADER FILES ****/ - +#include "../include/workers.h" #include "xpddefault.h" -int xpddefault_perfdata_timeout; - -char *xpddefault_host_perfdata_command = NULL; -char *xpddefault_service_perfdata_command = NULL; -command *xpddefault_host_perfdata_command_ptr = NULL; -command *xpddefault_service_perfdata_command_ptr = NULL; - -char *xpddefault_host_perfdata_file_template = NULL; -char *xpddefault_service_perfdata_file_template = NULL; - -char *xpddefault_host_perfdata_file = NULL; -char *xpddefault_service_perfdata_file = NULL; - -int xpddefault_host_perfdata_file_append = TRUE; -int xpddefault_service_perfdata_file_append = TRUE; -int xpddefault_host_perfdata_file_pipe = FALSE; -int xpddefault_service_perfdata_file_pipe = FALSE; - -unsigned long xpddefault_host_perfdata_file_processing_interval = 0L; -unsigned long xpddefault_service_perfdata_file_processing_interval = 0L; - -char *xpddefault_host_perfdata_file_processing_command = NULL; -char *xpddefault_service_perfdata_file_processing_command = NULL; -command *xpddefault_host_perfdata_file_processing_command_ptr = NULL; -command *xpddefault_service_perfdata_file_processing_command_ptr = NULL; - -int xpddefault_host_perfdata_process_empty_results = DEFAULT_HOST_PERFDATA_PROCESS_EMPTY_RESULTS; -int xpddefault_service_perfdata_process_empty_results = DEFAULT_SERVICE_PERFDATA_PROCESS_EMPTY_RESULTS; - -FILE *xpddefault_host_perfdata_fp = NULL; -FILE *xpddefault_service_perfdata_fp = NULL; -int xpddefault_host_perfdata_fd = -1; -int xpddefault_service_perfdata_fd = -1; - - -static pthread_mutex_t xpddefault_host_perfdata_fp_lock; -static pthread_mutex_t xpddefault_service_perfdata_fp_lock; - -/******************************************************************/ -/***************** COMMON CONFIG INITIALIZATION ******************/ -/******************************************************************/ - -/* grabs configuration information from main config file */ -int xpddefault_grab_config_info(char *config_file) { - char *input = NULL; - mmapfile *thefile = NULL; - - /* open the config file for reading */ - if((thefile = mmap_fopen(config_file)) == NULL) { - logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not open main config file '%s' for reading performance variables!\n", config_file); - return ERROR; - } - - /* read in all lines from the config file */ - while(1) { - - /* free memory */ - my_free(input); - - /* read the next line */ - if((input = mmap_fgets_multiline(thefile)) == NULL) - break; - - /* skip blank lines and comments */ - if(input[0] == '#' || input[0] == '\x0') - continue; - - strip(input); - - xpddefault_grab_config_directives(input); - } - - /* free memory and close the file */ - my_free(input); - mmap_fclose(thefile); - - return OK; - } - - -/* processes a single directive */ -int xpddefault_grab_config_directives(char *input) { - char *temp_ptr = NULL; - char *varname = NULL; - char *varvalue = NULL; - - /* get the variable name */ - if((temp_ptr = my_strtok(input, "=")) == NULL) - return ERROR; - if((varname = (char *)strdup(temp_ptr)) == NULL) - return ERROR; - - /* get the variable value */ - if((temp_ptr = my_strtok(NULL, "\n")) == NULL) { - my_free(varname); - return ERROR; - } - if((varvalue = (char *)strdup(temp_ptr)) == NULL) { - my_free(varname); - return ERROR; - } - - if(!strcmp(varname, "perfdata_timeout")) { - strip(varvalue); - xpddefault_perfdata_timeout = atoi(varvalue); - } - - else if(!strcmp(varname, "host_perfdata_command")) - xpddefault_host_perfdata_command = (char *)strdup(varvalue); - - else if(!strcmp(varname, "service_perfdata_command")) - xpddefault_service_perfdata_command = (char *)strdup(varvalue); - - else if(!strcmp(varname, "host_perfdata_file_template")) - xpddefault_host_perfdata_file_template = (char *)strdup(varvalue); - - else if(!strcmp(varname, "service_perfdata_file_template")) - xpddefault_service_perfdata_file_template = (char *)strdup(varvalue); - - else if(!strcmp(varname, "host_perfdata_file")) - xpddefault_host_perfdata_file = (char *)strdup(varvalue); - - else if(!strcmp(varname, "service_perfdata_file")) - xpddefault_service_perfdata_file = (char *)strdup(varvalue); - - else if(!strcmp(varname, "host_perfdata_file_mode")) { - if(strstr(varvalue, "p") != NULL) - xpddefault_host_perfdata_file_pipe = TRUE; - else if(strstr(varvalue, "w") != NULL) - xpddefault_host_perfdata_file_append = FALSE; - else - xpddefault_host_perfdata_file_append = TRUE; - } - - else if(!strcmp(varname, "service_perfdata_file_mode")) { - if(strstr(varvalue, "p") != NULL) - xpddefault_service_perfdata_file_pipe = TRUE; - else if(strstr(varvalue, "w") != NULL) - xpddefault_service_perfdata_file_append = FALSE; - else - xpddefault_service_perfdata_file_append = TRUE; - } - - else if(!strcmp(varname, "host_perfdata_file_processing_interval")) - xpddefault_host_perfdata_file_processing_interval = strtoul(varvalue, NULL, 0); - - else if(!strcmp(varname, "service_perfdata_file_processing_interval")) - xpddefault_service_perfdata_file_processing_interval = strtoul(varvalue, NULL, 0); - - else if(!strcmp(varname, "host_perfdata_file_processing_command")) - xpddefault_host_perfdata_file_processing_command = (char *)strdup(varvalue); - - else if(!strcmp(varname, "service_perfdata_file_processing_command")) - xpddefault_service_perfdata_file_processing_command = (char *)strdup(varvalue); - else if(!strcmp(varname, "host_perfdata_process_empty_results")) - xpddefault_host_perfdata_process_empty_results = (atoi(varvalue) > 0) ? TRUE : FALSE; - else if(!strcmp(varname, "service_perfdata_process_empty_results")) - xpddefault_service_perfdata_process_empty_results = (atoi(varvalue) > 0) ? TRUE : FALSE; - - /* free memory */ - my_free(varname); - my_free(varvalue); - - return OK; - } - +static command *host_perfdata_command_ptr = NULL; +static command *service_perfdata_command_ptr = NULL; +static command *host_perfdata_file_processing_command_ptr = NULL; +static command *service_perfdata_file_processing_command_ptr = NULL; +static FILE *host_perfdata_fp = NULL; +static FILE *service_perfdata_fp = NULL; +static int host_perfdata_fd = -1; +static int service_perfdata_fd = -1; /******************************************************************/ @@ -210,7 +47,7 @@ int xpddefault_grab_config_directives(char *input) { /******************************************************************/ /* initializes performance data */ -int xpddefault_initialize_performance_data(char *config_file) { +int xpddefault_initialize_performance_data(const char *cfgfile) { char *buffer = NULL; char *temp_buffer = NULL; char *temp_command_name = NULL; @@ -222,32 +59,29 @@ int xpddefault_initialize_performance_data(char *config_file) { time(¤t_time); /* reset vars */ - xpddefault_host_perfdata_command_ptr = NULL; - xpddefault_service_perfdata_command_ptr = NULL; - xpddefault_host_perfdata_file_processing_command_ptr = NULL; - xpddefault_service_perfdata_file_processing_command_ptr = NULL; - - /* grab config info from main config file */ - xpddefault_grab_config_info(config_file); + host_perfdata_command_ptr = NULL; + service_perfdata_command_ptr = NULL; + host_perfdata_file_processing_command_ptr = NULL; + service_perfdata_file_processing_command_ptr = NULL; /* make sure we have some templates defined */ - if(xpddefault_host_perfdata_file_template == NULL) - xpddefault_host_perfdata_file_template = (char *)strdup(DEFAULT_HOST_PERFDATA_FILE_TEMPLATE); - if(xpddefault_service_perfdata_file_template == NULL) - xpddefault_service_perfdata_file_template = (char *)strdup(DEFAULT_SERVICE_PERFDATA_FILE_TEMPLATE); + if(host_perfdata_file_template == NULL) + host_perfdata_file_template = (char *)strdup(DEFAULT_HOST_PERFDATA_FILE_TEMPLATE); + if(service_perfdata_file_template == NULL) + service_perfdata_file_template = (char *)strdup(DEFAULT_SERVICE_PERFDATA_FILE_TEMPLATE); /* process special chars in templates */ - xpddefault_preprocess_file_templates(xpddefault_host_perfdata_file_template); - xpddefault_preprocess_file_templates(xpddefault_service_perfdata_file_template); + xpddefault_preprocess_file_templates(host_perfdata_file_template); + xpddefault_preprocess_file_templates(service_perfdata_file_template); /* open the performance data files */ xpddefault_open_host_perfdata_file(); xpddefault_open_service_perfdata_file(); /* verify that performance data commands are valid */ - if(xpddefault_host_perfdata_command != NULL) { + if(host_perfdata_command != NULL) { - temp_buffer = (char *)strdup(xpddefault_host_perfdata_command); + temp_buffer = (char *)strdup(host_perfdata_command); /* get the command name, leave any arguments behind */ temp_command_name = my_strtok(temp_buffer, "!"); @@ -256,17 +90,17 @@ int xpddefault_initialize_performance_data(char *config_file) { logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Host performance command '%s' was not found - host performance data will not be processed!\n", temp_command_name); - my_free(xpddefault_host_perfdata_command); + my_free(host_perfdata_command); } my_free(temp_buffer); /* save the command pointer for later */ - xpddefault_host_perfdata_command_ptr = temp_command; + host_perfdata_command_ptr = temp_command; } - if(xpddefault_service_perfdata_command != NULL) { + if(service_perfdata_command != NULL) { - temp_buffer = (char *)strdup(xpddefault_service_perfdata_command); + temp_buffer = (char *)strdup(service_perfdata_command); /* get the command name, leave any arguments behind */ temp_command_name = my_strtok(temp_buffer, "!"); @@ -275,18 +109,18 @@ int xpddefault_initialize_performance_data(char *config_file) { logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Service performance command '%s' was not found - service performance data will not be processed!\n", temp_command_name); - my_free(xpddefault_service_perfdata_command); + my_free(service_perfdata_command); } /* free memory */ my_free(temp_buffer); /* save the command pointer for later */ - xpddefault_service_perfdata_command_ptr = temp_command; + service_perfdata_command_ptr = temp_command; } - if(xpddefault_host_perfdata_file_processing_command != NULL) { + if(host_perfdata_file_processing_command != NULL) { - temp_buffer = (char *)strdup(xpddefault_host_perfdata_file_processing_command); + temp_buffer = (char *)strdup(host_perfdata_file_processing_command); /* get the command name, leave any arguments behind */ temp_command_name = my_strtok(temp_buffer, "!"); @@ -295,18 +129,18 @@ int xpddefault_initialize_performance_data(char *config_file) { logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Host performance file processing command '%s' was not found - host performance data file will not be processed!\n", temp_command_name); - my_free(xpddefault_host_perfdata_file_processing_command); + my_free(host_perfdata_file_processing_command); } /* free memory */ my_free(temp_buffer); /* save the command pointer for later */ - xpddefault_host_perfdata_file_processing_command_ptr = temp_command; + host_perfdata_file_processing_command_ptr = temp_command; } - if(xpddefault_service_perfdata_file_processing_command != NULL) { + if(service_perfdata_file_processing_command != NULL) { - temp_buffer = (char *)strdup(xpddefault_service_perfdata_file_processing_command); + temp_buffer = (char *)strdup(service_perfdata_file_processing_command); /* get the command name, leave any arguments behind */ temp_command_name = my_strtok(temp_buffer, "!"); @@ -315,32 +149,32 @@ int xpddefault_initialize_performance_data(char *config_file) { logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Service performance file processing command '%s' was not found - service performance data file will not be processed!\n", temp_command_name); - my_free(xpddefault_service_perfdata_file_processing_command); + my_free(service_perfdata_file_processing_command); } /* save the command pointer for later */ - xpddefault_service_perfdata_file_processing_command_ptr = temp_command; + service_perfdata_file_processing_command_ptr = temp_command; } /* periodically process the host perfdata file */ - if(xpddefault_host_perfdata_file_processing_interval > 0 && xpddefault_host_perfdata_file_processing_command != NULL) - schedule_new_event(EVENT_USER_FUNCTION, TRUE, current_time + xpddefault_host_perfdata_file_processing_interval, TRUE, xpddefault_host_perfdata_file_processing_interval, NULL, TRUE, (void *)xpddefault_process_host_perfdata_file, NULL, 0); + if(host_perfdata_file_processing_interval > 0 && host_perfdata_file_processing_command != NULL) + schedule_new_event(EVENT_USER_FUNCTION, TRUE, current_time + host_perfdata_file_processing_interval, TRUE, host_perfdata_file_processing_interval, NULL, TRUE, (void *)xpddefault_process_host_perfdata_file, NULL, 0); /* periodically process the service perfdata file */ - if(xpddefault_service_perfdata_file_processing_interval > 0 && xpddefault_service_perfdata_file_processing_command != NULL) - schedule_new_event(EVENT_USER_FUNCTION, TRUE, current_time + xpddefault_service_perfdata_file_processing_interval, TRUE, xpddefault_service_perfdata_file_processing_interval, NULL, TRUE, (void *)xpddefault_process_service_perfdata_file, NULL, 0); + if(service_perfdata_file_processing_interval > 0 && service_perfdata_file_processing_command != NULL) + schedule_new_event(EVENT_USER_FUNCTION, TRUE, current_time + service_perfdata_file_processing_interval, TRUE, service_perfdata_file_processing_interval, NULL, TRUE, (void *)xpddefault_process_service_perfdata_file, NULL, 0); /* save the host perf data file macro */ my_free(mac->x[MACRO_HOSTPERFDATAFILE]); - if(xpddefault_host_perfdata_file != NULL) { - if((mac->x[MACRO_HOSTPERFDATAFILE] = (char *)strdup(xpddefault_host_perfdata_file))) + if(host_perfdata_file != NULL) { + if((mac->x[MACRO_HOSTPERFDATAFILE] = (char *)strdup(host_perfdata_file))) strip(mac->x[MACRO_HOSTPERFDATAFILE]); } /* save the service perf data file macro */ my_free(mac->x[MACRO_SERVICEPERFDATAFILE]); - if(xpddefault_service_perfdata_file != NULL) { - if((mac->x[MACRO_SERVICEPERFDATAFILE] = (char *)strdup(xpddefault_service_perfdata_file))) + if(service_perfdata_file != NULL) { + if((mac->x[MACRO_SERVICEPERFDATAFILE] = (char *)strdup(service_perfdata_file))) strip(mac->x[MACRO_SERVICEPERFDATAFILE]); } @@ -354,17 +188,17 @@ int xpddefault_initialize_performance_data(char *config_file) { /* cleans up performance data */ -int xpddefault_cleanup_performance_data(char *config_file) { +int xpddefault_cleanup_performance_data(void) { /* free memory */ - my_free(xpddefault_host_perfdata_command); - my_free(xpddefault_service_perfdata_command); - my_free(xpddefault_host_perfdata_file_template); - my_free(xpddefault_service_perfdata_file_template); - my_free(xpddefault_host_perfdata_file); - my_free(xpddefault_service_perfdata_file); - my_free(xpddefault_host_perfdata_file_processing_command); - my_free(xpddefault_service_perfdata_file_processing_command); + my_free(host_perfdata_command); + my_free(service_perfdata_command); + my_free(host_perfdata_file_template); + my_free(service_perfdata_file_template); + my_free(host_perfdata_file); + my_free(service_perfdata_file); + my_free(host_perfdata_file_processing_command); + my_free(service_perfdata_file_processing_command); /* close the files */ xpddefault_close_host_perfdata_file(); @@ -391,15 +225,15 @@ int xpddefault_update_service_performance_data(service *svc) { * on distributed setups, empty perfdata results are required, so * only drop out if demanded via configs. */ - if(xpddefault_service_perfdata_process_empty_results == FALSE) { - if(!svc || !svc->perf_data || !*svc->perf_data) { - return OK; - } - if((!xpddefault_service_perfdata_fp || !xpddefault_service_perfdata_file_template) && !xpddefault_service_perfdata_command) { - return OK; - } - + if(service_perfdata_process_empty_results==FALSE){ + if(!svc || !svc->perf_data || !*svc->perf_data) { + return OK; } + if((!service_perfdata_fp || !service_perfdata_file_template) && !service_perfdata_command) { + return OK; + } + + } /* * we know we've got some work to do, so grab the necessary * macros and get busy @@ -408,16 +242,17 @@ int xpddefault_update_service_performance_data(service *svc) { hst = find_host(svc->host_name); grab_host_macros_r(&mac, hst); grab_service_macros_r(&mac, svc); + grab_argv_macros_r(&mac, svc->check_command); /* run the performance data command */ xpddefault_run_service_performance_data_command(&mac, svc); - /* get rid of used memory we won't need anymore */ - clear_argv_macros_r(&mac); - /* update the performance data file */ xpddefault_update_service_performance_data_file(&mac, svc); + /* get rid of used memory we won't need anymore */ + clear_argv_macros_r(&mac); + /* now free() it all */ clear_volatile_macros_r(&mac); @@ -433,14 +268,14 @@ int xpddefault_update_host_performance_data(host *hst) { /* * bail early if we've got nothing to do so we don't spend a lot * of time calculating macros that never get used - * on distributed setups, empty perfdata results are required, so - * only drop out if demanded via configs. + * on distributed setups, empty perfdata results are required, so + * only drop out if demanded via configs. */ - if(xpddefault_host_perfdata_process_empty_results == FALSE) { + if(host_perfdata_process_empty_results==FALSE){ if(!hst || !hst->perf_data || !*hst->perf_data) { return OK; } - if((!xpddefault_host_perfdata_fp || !xpddefault_host_perfdata_file_template) && !xpddefault_host_perfdata_command) { + if((!host_perfdata_fp || !host_perfdata_file_template) && !host_perfdata_command) { return OK; } } @@ -448,6 +283,7 @@ int xpddefault_update_host_performance_data(host *hst) { /* set up macros and get to work */ memset(&mac, 0, sizeof(mac)); grab_host_macros_r(&mac, hst); + grab_argv_macros_r(&mac, hst->check_command); /* run the performance data command */ xpddefault_run_host_performance_data_command(&mac, hst); @@ -476,8 +312,6 @@ int xpddefault_update_host_performance_data(host *hst) { int xpddefault_run_service_performance_data_command(nagios_macros *mac, service *svc) { char *raw_command_line = NULL; char *processed_command_line = NULL; - int early_timeout = FALSE; - double exectime; int result = OK; int macro_options = STRIP_ILLEGAL_MACRO_CHARS | ESCAPE_MACRO_CHARS; @@ -487,11 +321,11 @@ int xpddefault_run_service_performance_data_command(nagios_macros *mac, service return ERROR; /* we don't have a command */ - if(xpddefault_service_perfdata_command == NULL) + if(service_perfdata_command == NULL) return OK; /* get the raw command line */ - get_raw_command_line_r(mac, xpddefault_service_perfdata_command_ptr, xpddefault_service_perfdata_command, &raw_command_line, macro_options); + get_raw_command_line_r(mac, service_perfdata_command_ptr, service_perfdata_command, &raw_command_line, macro_options); if(raw_command_line == NULL) return ERROR; @@ -506,11 +340,7 @@ int xpddefault_run_service_performance_data_command(nagios_macros *mac, service log_debug_info(DEBUGL_PERFDATA, 2, "Processed service performance data command line: %s\n", processed_command_line); /* run the command */ - my_system_r(mac, processed_command_line, xpddefault_perfdata_timeout, &early_timeout, &exectime, NULL, 0); - - /* check to see if the command timed out */ - if(early_timeout == TRUE) - logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Service performance data command '%s' for service '%s' on host '%s' timed out after %d seconds\n", processed_command_line, svc->description, svc->host_name, xpddefault_perfdata_timeout); + wproc_run(WPJOB_SVC_PERFDATA, processed_command_line, perfdata_timeout, NULL); /* free memory */ my_free(processed_command_line); @@ -523,8 +353,6 @@ int xpddefault_run_service_performance_data_command(nagios_macros *mac, service int xpddefault_run_host_performance_data_command(nagios_macros *mac, host *hst) { char *raw_command_line = NULL; char *processed_command_line = NULL; - int early_timeout = FALSE; - double exectime; int result = OK; int macro_options = STRIP_ILLEGAL_MACRO_CHARS | ESCAPE_MACRO_CHARS; @@ -534,11 +362,11 @@ int xpddefault_run_host_performance_data_command(nagios_macros *mac, host *hst) return ERROR; /* we don't have a command */ - if(xpddefault_host_perfdata_command == NULL) + if(host_perfdata_command == NULL) return OK; /* get the raw command line */ - get_raw_command_line_r(mac, xpddefault_host_perfdata_command_ptr, xpddefault_host_perfdata_command, &raw_command_line, macro_options); + get_raw_command_line_r(mac, host_perfdata_command_ptr, host_perfdata_command, &raw_command_line, macro_options); if(raw_command_line == NULL) return ERROR; @@ -547,19 +375,13 @@ int xpddefault_run_host_performance_data_command(nagios_macros *mac, host *hst) /* process any macros in the raw command line */ process_macros_r(mac, raw_command_line, &processed_command_line, macro_options); my_free(raw_command_line); - if(!processed_command_line) + if (!processed_command_line) return ERROR; log_debug_info(DEBUGL_PERFDATA, 2, "Processed host performance data command line: %s\n", processed_command_line); /* run the command */ - my_system_r(mac, processed_command_line, xpddefault_perfdata_timeout, &early_timeout, &exectime, NULL, 0); - if(processed_command_line == NULL) - return ERROR; - - /* check to see if the command timed out */ - if(early_timeout == TRUE) - logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Host performance data command '%s' for host '%s' timed out after %d seconds\n", processed_command_line, hst->name, xpddefault_perfdata_timeout); + wproc_run(WPJOB_HOST_PERFDATA, processed_command_line, perfdata_timeout, NULL); /* free memory */ my_free(processed_command_line); @@ -576,19 +398,19 @@ int xpddefault_run_host_performance_data_command(nagios_macros *mac, host *hst) /* open the host performance data file for writing */ int xpddefault_open_host_perfdata_file(void) { - if(xpddefault_host_perfdata_file != NULL) { + if(host_perfdata_file != NULL) { - if(xpddefault_host_perfdata_file_pipe == TRUE) { + if(host_perfdata_file_pipe == TRUE) { /* must open read-write to avoid failure if the other end isn't ready yet */ - xpddefault_host_perfdata_fd = open(xpddefault_host_perfdata_file, O_NONBLOCK | O_RDWR); - xpddefault_host_perfdata_fp = fdopen(xpddefault_host_perfdata_fd, "w"); + host_perfdata_fd = open(host_perfdata_file, O_NONBLOCK | O_RDWR | O_CREAT, 0644); + host_perfdata_fp = fdopen(host_perfdata_fd, "w"); } else - xpddefault_host_perfdata_fp = fopen(xpddefault_host_perfdata_file, (xpddefault_host_perfdata_file_append == TRUE) ? "a" : "w"); + host_perfdata_fp = fopen(host_perfdata_file, (host_perfdata_file_append == TRUE) ? "a" : "w"); - if(xpddefault_host_perfdata_fp == NULL) { + if(host_perfdata_fp == NULL) { - logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: File '%s' could not be opened - host performance data will not be written to file!\n", xpddefault_host_perfdata_file); + logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: File '%s' could not be opened - host performance data will not be written to file!\n", host_perfdata_file); return ERROR; } @@ -601,18 +423,18 @@ int xpddefault_open_host_perfdata_file(void) { /* open the service performance data file for writing */ int xpddefault_open_service_perfdata_file(void) { - if(xpddefault_service_perfdata_file != NULL) { - if(xpddefault_service_perfdata_file_pipe == TRUE) { + if(service_perfdata_file != NULL) { + if(service_perfdata_file_pipe == TRUE) { /* must open read-write to avoid failure if the other end isn't ready yet */ - xpddefault_service_perfdata_fd = open(xpddefault_service_perfdata_file, O_NONBLOCK | O_RDWR); - xpddefault_service_perfdata_fp = fdopen(xpddefault_service_perfdata_fd, "w"); + service_perfdata_fd = open(service_perfdata_file, O_NONBLOCK | O_RDWR); + service_perfdata_fp = fdopen(service_perfdata_fd, "w"); } else - xpddefault_service_perfdata_fp = fopen(xpddefault_service_perfdata_file, (xpddefault_service_perfdata_file_append == TRUE) ? "a" : "w"); + service_perfdata_fp = fopen(service_perfdata_file, (service_perfdata_file_append == TRUE) ? "a" : "w"); - if(xpddefault_service_perfdata_fp == NULL) { + if(service_perfdata_fp == NULL) { - logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: File '%s' could not be opened - service performance data will not be written to file!\n", xpddefault_service_perfdata_file); + logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: File '%s' could not be opened - service performance data will not be written to file!\n", service_perfdata_file); return ERROR; } @@ -625,11 +447,11 @@ int xpddefault_open_service_perfdata_file(void) { /* close the host performance data file */ int xpddefault_close_host_perfdata_file(void) { - if(xpddefault_host_perfdata_fp != NULL) - fclose(xpddefault_host_perfdata_fp); - if(xpddefault_host_perfdata_fd >= 0) { - close(xpddefault_host_perfdata_fd); - xpddefault_host_perfdata_fd = -1; + if(host_perfdata_fp != NULL) + fclose(host_perfdata_fp); + if(host_perfdata_fd >= 0) { + close(host_perfdata_fd); + host_perfdata_fd = -1; } return OK; @@ -639,11 +461,11 @@ int xpddefault_close_host_perfdata_file(void) { /* close the service performance data file */ int xpddefault_close_service_perfdata_file(void) { - if(xpddefault_service_perfdata_fp != NULL) - fclose(xpddefault_service_perfdata_fp); - if(xpddefault_service_perfdata_fd >= 0) { - close(xpddefault_service_perfdata_fd); - xpddefault_service_perfdata_fd = -1; + if(service_perfdata_fp != NULL) + fclose(service_perfdata_fp); + if(service_perfdata_fd >= 0) { + close(service_perfdata_fd); + service_perfdata_fd = -1; } return OK; @@ -653,8 +475,7 @@ int xpddefault_close_service_perfdata_file(void) { /* processes delimiter characters in templates */ int xpddefault_preprocess_file_templates(char *template) { char *tempbuf; - int x = 0; - int y = 0; + unsigned int x, y; if(template == NULL) return OK; @@ -706,11 +527,11 @@ int xpddefault_update_service_performance_data_file(nagios_macros *mac, service return ERROR; /* we don't have a file to write to*/ - if(xpddefault_service_perfdata_fp == NULL || xpddefault_service_perfdata_file_template == NULL) + if(service_perfdata_fp == NULL || service_perfdata_file_template == NULL) return OK; /* get the raw line to write */ - raw_output = (char *)strdup(xpddefault_service_perfdata_file_template); + raw_output = (char *)strdup(service_perfdata_file_template); log_debug_info(DEBUGL_PERFDATA, 2, "Raw service performance data file output: %s\n", raw_output); @@ -721,12 +542,10 @@ int xpddefault_update_service_performance_data_file(nagios_macros *mac, service log_debug_info(DEBUGL_PERFDATA, 2, "Processed service performance data file output: %s\n", processed_output); - /* lock, write to and unlock host performance data file */ - pthread_mutex_lock(&xpddefault_service_perfdata_fp_lock); - fputs(processed_output, xpddefault_service_perfdata_fp); - fputc('\n', xpddefault_service_perfdata_fp); - fflush(xpddefault_service_perfdata_fp); - pthread_mutex_unlock(&xpddefault_service_perfdata_fp_lock); + /* write to host performance data file */ + fputs(processed_output, service_perfdata_fp); + fputc('\n', service_perfdata_fp); + fflush(service_perfdata_fp); /* free memory */ my_free(raw_output); @@ -748,11 +567,11 @@ int xpddefault_update_host_performance_data_file(nagios_macros *mac, host *hst) return ERROR; /* we don't have a host perfdata file */ - if(xpddefault_host_perfdata_fp == NULL || xpddefault_host_perfdata_file_template == NULL) + if(host_perfdata_fp == NULL || host_perfdata_file_template == NULL) return OK; /* get the raw output */ - raw_output = (char *)strdup(xpddefault_host_perfdata_file_template); + raw_output = (char *)strdup(host_perfdata_file_template); log_debug_info(DEBUGL_PERFDATA, 2, "Raw host performance file output: %s\n", raw_output); @@ -763,12 +582,10 @@ int xpddefault_update_host_performance_data_file(nagios_macros *mac, host *hst) log_debug_info(DEBUGL_PERFDATA, 2, "Processed host performance data file output: %s\n", processed_output); - /* lock, write to and unlock host performance data file */ - pthread_mutex_lock(&xpddefault_host_perfdata_fp_lock); - fputs(processed_output, xpddefault_host_perfdata_fp); - fputc('\n', xpddefault_host_perfdata_fp); - fflush(xpddefault_host_perfdata_fp); - pthread_mutex_unlock(&xpddefault_host_perfdata_fp_lock); + /* write to host performance data file */ + fputs(processed_output, host_perfdata_fp); + fputc('\n', host_perfdata_fp); + fflush(host_perfdata_fp); /* free memory */ my_free(raw_output); @@ -791,14 +608,14 @@ int xpddefault_process_host_perfdata_file(void) { log_debug_info(DEBUGL_FUNCTIONS, 0, "process_host_perfdata_file()\n"); /* we don't have a command */ - if(xpddefault_host_perfdata_file_processing_command == NULL) + if(host_perfdata_file_processing_command == NULL) return OK; /* init macros */ memset(&mac, 0, sizeof(mac)); /* get the raw command line */ - get_raw_command_line_r(&mac, xpddefault_host_perfdata_file_processing_command_ptr, xpddefault_host_perfdata_file_processing_command, &raw_command_line, macro_options); + get_raw_command_line_r(&mac, host_perfdata_file_processing_command_ptr, host_perfdata_file_processing_command, &raw_command_line, macro_options); if(raw_command_line == NULL) { clear_volatile_macros_r(&mac); return ERROR; @@ -816,21 +633,19 @@ int xpddefault_process_host_perfdata_file(void) { log_debug_info(DEBUGL_PERFDATA, 2, "Processed host performance data file processing command line: %s\n", processed_command_line); - /* lock and close the performance data file */ - pthread_mutex_lock(&xpddefault_host_perfdata_fp_lock); + /* close the performance data file */ xpddefault_close_host_perfdata_file(); /* run the command */ - my_system_r(&mac, processed_command_line, xpddefault_perfdata_timeout, &early_timeout, &exectime, NULL, 0); + my_system_r(&mac, processed_command_line, perfdata_timeout, &early_timeout, &exectime, NULL, 0); clear_volatile_macros_r(&mac); - /* re-open and unlock the performance data file */ + /* re-open the performance data file */ xpddefault_open_host_perfdata_file(); - pthread_mutex_unlock(&xpddefault_host_perfdata_fp_lock); /* check to see if the command timed out */ if(early_timeout == TRUE) - logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Host performance data file processing command '%s' timed out after %d seconds\n", processed_command_line, xpddefault_perfdata_timeout); + logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Host performance data file processing command '%s' timed out after %d seconds\n", processed_command_line, perfdata_timeout); /* free memory */ @@ -853,14 +668,14 @@ int xpddefault_process_service_perfdata_file(void) { log_debug_info(DEBUGL_FUNCTIONS, 0, "process_service_perfdata_file()\n"); /* we don't have a command */ - if(xpddefault_service_perfdata_file_processing_command == NULL) + if(service_perfdata_file_processing_command == NULL) return OK; /* init macros */ memset(&mac, 0, sizeof(mac)); /* get the raw command line */ - get_raw_command_line_r(&mac, xpddefault_service_perfdata_file_processing_command_ptr, xpddefault_service_perfdata_file_processing_command, &raw_command_line, macro_options); + get_raw_command_line_r(&mac, service_perfdata_file_processing_command_ptr, service_perfdata_file_processing_command, &raw_command_line, macro_options); if(raw_command_line == NULL) { clear_volatile_macros_r(&mac); return ERROR; @@ -878,26 +693,23 @@ int xpddefault_process_service_perfdata_file(void) { log_debug_info(DEBUGL_PERFDATA, 2, "Processed service performance data file processing command line: %s\n", processed_command_line); - /* lock and close the performance data file */ - pthread_mutex_lock(&xpddefault_service_perfdata_fp_lock); + /* close the performance data file */ xpddefault_close_service_perfdata_file(); /* run the command */ - my_system_r(&mac, processed_command_line, xpddefault_perfdata_timeout, &early_timeout, &exectime, NULL, 0); + my_system_r(&mac, processed_command_line, perfdata_timeout, &early_timeout, &exectime, NULL, 0); - /* re-open and unlock the performance data file */ + /* re-open the performance data file */ xpddefault_open_service_perfdata_file(); - pthread_mutex_unlock(&xpddefault_service_perfdata_fp_lock); clear_volatile_macros_r(&mac); /* check to see if the command timed out */ if(early_timeout == TRUE) - logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Service performance data file processing command '%s' timed out after %d seconds\n", processed_command_line, xpddefault_perfdata_timeout); + logit(NSLOG_RUNTIME_WARNING, TRUE, "Warning: Service performance data file processing command '%s' timed out after %d seconds\n", processed_command_line, perfdata_timeout); /* free memory */ my_free(processed_command_line); return result; } - diff --git a/xdata/xpddefault.h b/xdata/xpddefault.h index 881ce62..1ff3512 100644 --- a/xdata/xpddefault.h +++ b/xdata/xpddefault.h @@ -2,8 +2,6 @@ * * XPDDEFAULT.H - Include file for default performance data routines * - * Copyright (c) 2001-2006 Ethan Galstad (egalstad@nagios.org) - * Last Modified: 02-28-2006 * * License: * @@ -22,23 +20,14 @@ * *****************************************************************************/ -#ifndef _XPDDEFAULT_H -#define _XPDDEFAULT_H +#ifndef NAGIOS_XPDDEFAULT_H_INCLUDED +#define NAGIOS_XPDDEFAULT_H_INCLUDED #include "../include/objects.h" -#define DEFAULT_HOST_PERFDATA_FILE_TEMPLATE "[HOSTPERFDATA]\t$TIMET$\t$HOSTNAME$\t$HOSTEXECUTIONTIME$\t$HOSTOUTPUT$\t$HOSTPERFDATA$" -#define DEFAULT_SERVICE_PERFDATA_FILE_TEMPLATE "[SERVICEPERFDATA]\t$TIMET$\t$HOSTNAME$\t$SERVICEDESC$\t$SERVICEEXECUTIONTIME$\t$SERVICELATENCY$\t$SERVICEOUTPUT$\t$SERVICEPERFDATA$" - -#define DEFAULT_HOST_PERFDATA_PROCESS_EMPTY_RESULTS 1 -#define DEFAULT_SERVICE_PERFDATA_PROCESS_EMPTY_RESULTS 1 - - -int xpddefault_initialize_performance_data(char *); -int xpddefault_cleanup_performance_data(char *); -int xpddefault_grab_config_info(char *); -int xpddefault_grab_config_directives(char *); +int xpddefault_initialize_performance_data(const char *); +int xpddefault_cleanup_performance_data(void); int xpddefault_update_service_performance_data(service *); int xpddefault_update_host_performance_data(host *); diff --git a/xdata/xrddefault.c b/xdata/xrddefault.c index a3823b3..0e084c0 100644 --- a/xdata/xrddefault.c +++ b/xdata/xrddefault.c @@ -2,9 +2,6 @@ * * XRDDEFAULT.C - Default external state retention routines for Nagios * - * Copyright (c) 2009 Nagios Core Development Team and Community Contributors - * Copyright (c) 1999-2010 Ethan Galstad (egalstad@nagios.org) - * Last Modified: 08-06-2010 * * License: * @@ -35,181 +32,8 @@ #include "../include/sretention.h" #include "../include/comments.h" #include "../include/downtime.h" - - -/**** STATE INFORMATION SPECIFIC HEADER FILES ****/ - #include "xrddefault.h" -extern host *host_list; -extern service *service_list; -extern contact *contact_list; -extern comment *comment_list; -extern scheduled_downtime *scheduled_downtime_list; - -extern char *global_host_event_handler; -extern char *global_service_event_handler; - -extern int enable_notifications; -extern int execute_service_checks; -extern int accept_passive_service_checks; -extern int execute_host_checks; -extern int accept_passive_host_checks; -extern int enable_event_handlers; -extern int obsess_over_services; -extern int obsess_over_hosts; -extern int enable_flap_detection; -extern int enable_failure_prediction; -extern int process_performance_data; -extern int check_service_freshness; -extern int check_host_freshness; - -extern int test_scheduling; - -extern int use_large_installation_tweaks; - -extern int use_retained_program_state; -extern int use_retained_scheduling_info; -extern int retention_scheduling_horizon; - -extern time_t last_program_stop; -extern time_t last_update_check; -extern unsigned long update_uid; -extern char *last_program_version; -extern int update_available; -extern char *last_program_version; -extern char *new_program_version; - -extern unsigned long next_comment_id; -extern unsigned long next_downtime_id; -extern unsigned long next_event_id; -extern unsigned long next_problem_id; -extern unsigned long next_notification_id; - -extern unsigned long modified_host_process_attributes; -extern unsigned long modified_service_process_attributes; - -extern unsigned long retained_host_attribute_mask; -extern unsigned long retained_service_attribute_mask; -extern unsigned long retained_contact_host_attribute_mask; -extern unsigned long retained_contact_service_attribute_mask; -extern unsigned long retained_process_host_attribute_mask; -extern unsigned long retained_process_service_attribute_mask; - - -char *xrddefault_retention_file = NULL; -char *xrddefault_temp_file = NULL; - - - - -/******************************************************************/ -/********************* CONFIG INITIALIZATION *********************/ -/******************************************************************/ - -int xrddefault_grab_config_info(char *main_config_file) { - char *input = NULL; - mmapfile *thefile = NULL; - nagios_macros *mac; - - mac = get_global_macros(); - - - /* open the main config file for reading */ - if((thefile = mmap_fopen(main_config_file)) == NULL) { - - log_debug_info(DEBUGL_RETENTIONDATA, 2, "Error: Cannot open main configuration file '%s' for reading!\n", main_config_file); - - my_free(xrddefault_retention_file); - my_free(xrddefault_temp_file); - - return ERROR; - } - - /* read in all lines from the main config file */ - while(1) { - - /* free memory */ - my_free(input); - - /* read the next line */ - if((input = mmap_fgets_multiline(thefile)) == NULL) - break; - - strip(input); - - /* skip blank lines and comments */ - if(input[0] == '#' || input[0] == '\x0') - continue; - - xrddefault_grab_config_directives(input); - } - - /* free memory and close the file */ - my_free(input); - mmap_fclose(thefile); - - /* initialize locations if necessary */ - if(xrddefault_retention_file == NULL) - xrddefault_retention_file = (char *)strdup(DEFAULT_RETENTION_FILE); - if(xrddefault_temp_file == NULL) - xrddefault_temp_file = (char *)strdup(DEFAULT_TEMP_FILE); - - /* make sure we have everything */ - if(xrddefault_retention_file == NULL) - return ERROR; - if(xrddefault_temp_file == NULL) - return ERROR; - - /* save the retention file macro */ - my_free(mac->x[MACRO_RETENTIONDATAFILE]); - if((mac->x[MACRO_RETENTIONDATAFILE] = (char *)strdup(xrddefault_retention_file))) - strip(mac->x[MACRO_RETENTIONDATAFILE]); - - return OK; - } - - - -/* process a single config directive */ -int xrddefault_grab_config_directives(char *input) { - char *temp_ptr = NULL; - char *varname = NULL; - char *varvalue = NULL; - - /* get the variable name */ - if((temp_ptr = my_strtok(input, "=")) == NULL) - return ERROR; - if((varname = (char *)strdup(temp_ptr)) == NULL) - return ERROR; - - /* get the variable value */ - if((temp_ptr = my_strtok(NULL, "\n")) == NULL) { - my_free(varname); - return ERROR; - } - if((varvalue = (char *)strdup(temp_ptr)) == NULL) { - my_free(varname); - return ERROR; - } - - /* retention file definition */ - if(!strcmp(varname, "xrddefault_retention_file") || !strcmp(varname, "state_retention_file")) - xrddefault_retention_file = (char *)strdup(varvalue); - - /* temp file definition */ - else if(!strcmp(varname, "temp_file")) - xrddefault_temp_file = (char *)strdup(varvalue); - - /* free memory */ - my_free(varname); - my_free(varvalue); - - return OK; - } - - - /******************************************************************/ /********************* INIT/CLEANUP FUNCTIONS *********************/ @@ -217,24 +41,34 @@ int xrddefault_grab_config_directives(char *input) { /* initialize retention data */ -int xrddefault_initialize_retention_data(char *config_file) { - int result; +int xrddefault_initialize_retention_data(const char *cfgfile) { + nagios_macros *mac; - /* grab configuration data */ - result = xrddefault_grab_config_info(config_file); - if(result == ERROR) + /* initialize locations if necessary */ + if(retention_file == NULL) + retention_file = (char *)strdup(DEFAULT_RETENTION_FILE); + + /* make sure we have everything */ + if(retention_file == NULL) return ERROR; + mac = get_global_macros(); + + /* save the retention file macro */ + my_free(mac->x[MACRO_RETENTIONDATAFILE]); + mac->x[MACRO_RETENTIONDATAFILE] = retention_file; + if((mac->x[MACRO_RETENTIONDATAFILE] = (char *)strdup(retention_file))) + strip(mac->x[MACRO_RETENTIONDATAFILE]); + return OK; } /* cleanup retention data before terminating */ -int xrddefault_cleanup_retention_data(char *config_file) { +int xrddefault_cleanup_retention_data(void) { /* free memory */ - my_free(xrddefault_retention_file); - my_free(xrddefault_temp_file); + my_free(retention_file); return OK; } @@ -245,7 +79,7 @@ int xrddefault_cleanup_retention_data(char *config_file) { /******************************************************************/ int xrddefault_save_state_information(void) { - char *temp_file = NULL; + char *tmp_file = NULL; customvariablesmember *temp_customvariablesmember = NULL; time_t current_time = 0L; int result = OK; @@ -253,7 +87,7 @@ int xrddefault_save_state_information(void) { host *temp_host = NULL; service *temp_service = NULL; contact *temp_contact = NULL; - comment *temp_comment = NULL; + nagios_comment *temp_comment = NULL; scheduled_downtime *temp_downtime = NULL; int x = 0; int fd = 0; @@ -269,29 +103,29 @@ int xrddefault_save_state_information(void) { log_debug_info(DEBUGL_FUNCTIONS, 0, "xrddefault_save_state_information()\n"); /* make sure we have everything */ - if(xrddefault_retention_file == NULL || xrddefault_temp_file == NULL) { + if(retention_file == NULL || temp_file == NULL) { logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: We don't have the required file names to store retention data!\n"); return ERROR; } /* open a safe temp file for output */ - asprintf(&temp_file, "%sXXXXXX", xrddefault_temp_file); - if(temp_file == NULL) + asprintf(&tmp_file, "%sXXXXXX", temp_file); + if(tmp_file == NULL) return ERROR; - if((fd = mkstemp(temp_file)) == -1) + if((fd = mkstemp(tmp_file)) == -1) return ERROR; - log_debug_info(DEBUGL_RETENTIONDATA, 2, "Writing retention data to temp file '%s'\n", temp_file); + log_debug_info(DEBUGL_RETENTIONDATA, 2, "Writing retention data to temp file '%s'\n", tmp_file); fp = (FILE *)fdopen(fd, "w"); if(fp == NULL) { close(fd); - unlink(temp_file); + unlink(tmp_file); - logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Could not open temp state retention file '%s' for writing!\n", temp_file); + logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Could not open temp state retention file '%s' for writing!\n", tmp_file); - my_free(temp_file); + my_free(tmp_file); return ERROR; } @@ -299,9 +133,9 @@ int xrddefault_save_state_information(void) { /* what attributes should be masked out? */ /* NOTE: host/service/contact-specific values may be added in the future, but for now we only have global masks */ process_host_attribute_mask = retained_process_host_attribute_mask; - process_service_attribute_mask = retained_process_host_attribute_mask; + process_service_attribute_mask = retained_process_service_attribute_mask; host_attribute_mask = retained_host_attribute_mask; - service_attribute_mask = retained_host_attribute_mask; + service_attribute_mask = retained_service_attribute_mask; contact_host_attribute_mask = retained_contact_host_attribute_mask; contact_service_attribute_mask = retained_contact_service_attribute_mask; @@ -317,9 +151,9 @@ int xrddefault_save_state_information(void) { /* write file info */ fprintf(fp, "info {\n"); - fprintf(fp, "created=%lu\n", current_time); + fprintf(fp, "created=%llu\n", (unsigned long long)current_time); fprintf(fp, "version=%s\n", PROGRAM_VERSION); - fprintf(fp, "last_update_check=%lu\n", last_update_check); + fprintf(fp, "last_update_check=%llu\n", (unsigned long long)last_update_check); fprintf(fp, "update_available=%d\n", update_available); fprintf(fp, "update_uid=%lu\n", update_uid); fprintf(fp, "last_version=%s\n", (last_program_version == NULL) ? "" : last_program_version); @@ -341,7 +175,6 @@ int xrddefault_save_state_information(void) { fprintf(fp, "check_service_freshness=%d\n", check_service_freshness); fprintf(fp, "check_host_freshness=%d\n", check_host_freshness); fprintf(fp, "enable_flap_detection=%d\n", enable_flap_detection); - fprintf(fp, "enable_failure_prediction=%d\n", enable_failure_prediction); fprintf(fp, "process_performance_data=%d\n", process_performance_data); fprintf(fp, "global_host_event_handler=%s\n", (global_host_event_handler == NULL) ? "" : global_host_event_handler); fprintf(fp, "global_service_event_handler=%s\n", (global_service_event_handler == NULL) ? "" : global_service_event_handler); @@ -358,7 +191,7 @@ int xrddefault_save_state_information(void) { fprintf(fp, "host {\n"); fprintf(fp, "host_name=%s\n", temp_host->name); fprintf(fp, "modified_attributes=%lu\n", (temp_host->modified_attributes & ~host_attribute_mask)); - fprintf(fp, "check_command=%s\n", (temp_host->host_check_command == NULL) ? "" : temp_host->host_check_command); + fprintf(fp, "check_command=%s\n", (temp_host->check_command == NULL) ? "" : temp_host->check_command); fprintf(fp, "check_period=%s\n", (temp_host->check_period == NULL) ? "" : temp_host->check_period); fprintf(fp, "notification_period=%s\n", (temp_host->notification_period == NULL) ? "" : temp_host->notification_period); fprintf(fp, "event_handler=%s\n", (temp_host->event_handler == NULL) ? "" : temp_host->event_handler); @@ -376,34 +209,33 @@ int xrddefault_save_state_information(void) { fprintf(fp, "plugin_output=%s\n", (temp_host->plugin_output == NULL) ? "" : temp_host->plugin_output); fprintf(fp, "long_plugin_output=%s\n", (temp_host->long_plugin_output == NULL) ? "" : temp_host->long_plugin_output); fprintf(fp, "performance_data=%s\n", (temp_host->perf_data == NULL) ? "" : temp_host->perf_data); - fprintf(fp, "last_check=%lu\n", temp_host->last_check); - fprintf(fp, "next_check=%lu\n", temp_host->next_check); + fprintf(fp, "last_check=%llu\n", (unsigned long long)temp_host->last_check); + fprintf(fp, "next_check=%llu\n", (unsigned long long)temp_host->next_check); fprintf(fp, "check_options=%d\n", temp_host->check_options); fprintf(fp, "current_attempt=%d\n", temp_host->current_attempt); fprintf(fp, "max_attempts=%d\n", temp_host->max_attempts); - fprintf(fp, "normal_check_interval=%f\n", temp_host->check_interval); - fprintf(fp, "retry_check_interval=%f\n", temp_host->check_interval); + fprintf(fp, "check_interval=%f\n", temp_host->check_interval); + fprintf(fp, "retry_interval=%f\n", temp_host->retry_interval); fprintf(fp, "state_type=%d\n", temp_host->state_type); - fprintf(fp, "last_state_change=%lu\n", temp_host->last_state_change); - fprintf(fp, "last_hard_state_change=%lu\n", temp_host->last_hard_state_change); - fprintf(fp, "last_time_up=%lu\n", temp_host->last_time_up); - fprintf(fp, "last_time_down=%lu\n", temp_host->last_time_down); - fprintf(fp, "last_time_unreachable=%lu\n", temp_host->last_time_unreachable); - fprintf(fp, "notified_on_down=%d\n", temp_host->notified_on_down); - fprintf(fp, "notified_on_unreachable=%d\n", temp_host->notified_on_unreachable); - fprintf(fp, "last_notification=%lu\n", temp_host->last_host_notification); + fprintf(fp, "last_state_change=%llu\n", (unsigned long long)temp_host->last_state_change); + fprintf(fp, "last_hard_state_change=%llu\n", (unsigned long long)temp_host->last_hard_state_change); + fprintf(fp, "last_time_up=%llu\n", (unsigned long long)temp_host->last_time_up); + fprintf(fp, "last_time_down=%llu\n", (unsigned long long)temp_host->last_time_down); + fprintf(fp, "last_time_unreachable=%llu\n", (unsigned long long)temp_host->last_time_unreachable); + fprintf(fp, "notified_on_down=%d\n", flag_isset(temp_host->notified_on, OPT_DOWN)); + fprintf(fp, "notified_on_unreachable=%d\n", flag_isset(temp_host->notified_on, OPT_UNREACHABLE)); + fprintf(fp, "last_notification=%llu\n", (unsigned long long)temp_host->last_notification); fprintf(fp, "current_notification_number=%d\n", temp_host->current_notification_number); fprintf(fp, "current_notification_id=%lu\n", temp_host->current_notification_id); fprintf(fp, "notifications_enabled=%d\n", temp_host->notifications_enabled); fprintf(fp, "problem_has_been_acknowledged=%d\n", temp_host->problem_has_been_acknowledged); fprintf(fp, "acknowledgement_type=%d\n", temp_host->acknowledgement_type); fprintf(fp, "active_checks_enabled=%d\n", temp_host->checks_enabled); - fprintf(fp, "passive_checks_enabled=%d\n", temp_host->accept_passive_host_checks); + fprintf(fp, "passive_checks_enabled=%d\n", temp_host->accept_passive_checks); fprintf(fp, "event_handler_enabled=%d\n", temp_host->event_handler_enabled); fprintf(fp, "flap_detection_enabled=%d\n", temp_host->flap_detection_enabled); - fprintf(fp, "failure_prediction_enabled=%d\n", temp_host->failure_prediction_enabled); fprintf(fp, "process_performance_data=%d\n", temp_host->process_performance_data); - fprintf(fp, "obsess_over_host=%d\n", temp_host->obsess_over_host); + fprintf(fp, "obsess=%d\n", temp_host->obsess); fprintf(fp, "is_flapping=%d\n", temp_host->is_flapping); fprintf(fp, "percent_state_change=%.2f\n", temp_host->percent_state_change); fprintf(fp, "check_flapping_recovery_notification=%d\n", temp_host->check_flapping_recovery_notification); @@ -429,7 +261,7 @@ int xrddefault_save_state_information(void) { fprintf(fp, "host_name=%s\n", temp_service->host_name); fprintf(fp, "service_description=%s\n", temp_service->description); fprintf(fp, "modified_attributes=%lu\n", (temp_service->modified_attributes & ~service_attribute_mask)); - fprintf(fp, "check_command=%s\n", (temp_service->service_check_command == NULL) ? "" : temp_service->service_check_command); + fprintf(fp, "check_command=%s\n", (temp_service->check_command == NULL) ? "" : temp_service->check_command); fprintf(fp, "check_period=%s\n", (temp_service->check_period == NULL) ? "" : temp_service->check_period); fprintf(fp, "notification_period=%s\n", (temp_service->notification_period == NULL) ? "" : temp_service->notification_period); fprintf(fp, "event_handler=%s\n", (temp_service->event_handler == NULL) ? "" : temp_service->event_handler); @@ -446,37 +278,36 @@ int xrddefault_save_state_information(void) { fprintf(fp, "last_problem_id=%lu\n", temp_service->last_problem_id); fprintf(fp, "current_attempt=%d\n", temp_service->current_attempt); fprintf(fp, "max_attempts=%d\n", temp_service->max_attempts); - fprintf(fp, "normal_check_interval=%f\n", temp_service->check_interval); - fprintf(fp, "retry_check_interval=%f\n", temp_service->retry_interval); + fprintf(fp, "check_interval=%f\n", temp_service->check_interval); + fprintf(fp, "retry_interval=%f\n", temp_service->retry_interval); fprintf(fp, "state_type=%d\n", temp_service->state_type); - fprintf(fp, "last_state_change=%lu\n", temp_service->last_state_change); - fprintf(fp, "last_hard_state_change=%lu\n", temp_service->last_hard_state_change); - fprintf(fp, "last_time_ok=%lu\n", temp_service->last_time_ok); - fprintf(fp, "last_time_warning=%lu\n", temp_service->last_time_warning); - fprintf(fp, "last_time_unknown=%lu\n", temp_service->last_time_unknown); - fprintf(fp, "last_time_critical=%lu\n", temp_service->last_time_critical); + fprintf(fp, "last_state_change=%llu\n", (unsigned long long)temp_service->last_state_change); + fprintf(fp, "last_hard_state_change=%llu\n", (unsigned long long)temp_service->last_hard_state_change); + fprintf(fp, "last_time_ok=%llu\n", (unsigned long long)temp_service->last_time_ok); + fprintf(fp, "last_time_warning=%llu\n", (unsigned long long)temp_service->last_time_warning); + fprintf(fp, "last_time_unknown=%llu\n", (unsigned long long)temp_service->last_time_unknown); + fprintf(fp, "last_time_critical=%llu\n", (unsigned long long)temp_service->last_time_critical); fprintf(fp, "plugin_output=%s\n", (temp_service->plugin_output == NULL) ? "" : temp_service->plugin_output); fprintf(fp, "long_plugin_output=%s\n", (temp_service->long_plugin_output == NULL) ? "" : temp_service->long_plugin_output); fprintf(fp, "performance_data=%s\n", (temp_service->perf_data == NULL) ? "" : temp_service->perf_data); - fprintf(fp, "last_check=%lu\n", temp_service->last_check); - fprintf(fp, "next_check=%lu\n", temp_service->next_check); + fprintf(fp, "last_check=%llu\n", (unsigned long long)temp_service->last_check); + fprintf(fp, "next_check=%llu\n", (unsigned long long)temp_service->next_check); fprintf(fp, "check_options=%d\n", temp_service->check_options); - fprintf(fp, "notified_on_unknown=%d\n", temp_service->notified_on_unknown); - fprintf(fp, "notified_on_warning=%d\n", temp_service->notified_on_warning); - fprintf(fp, "notified_on_critical=%d\n", temp_service->notified_on_critical); + fprintf(fp, "notified_on_unknown=%d\n", flag_isset(temp_service->notified_on, OPT_UNKNOWN)); + fprintf(fp, "notified_on_warning=%d\n", flag_isset(temp_service->notified_on, OPT_WARNING)); + fprintf(fp, "notified_on_critical=%d\n", flag_isset(temp_service->notified_on, OPT_CRITICAL)); fprintf(fp, "current_notification_number=%d\n", temp_service->current_notification_number); fprintf(fp, "current_notification_id=%lu\n", temp_service->current_notification_id); - fprintf(fp, "last_notification=%lu\n", temp_service->last_notification); + fprintf(fp, "last_notification=%llu\n", (unsigned long long)temp_service->last_notification); fprintf(fp, "notifications_enabled=%d\n", temp_service->notifications_enabled); fprintf(fp, "active_checks_enabled=%d\n", temp_service->checks_enabled); - fprintf(fp, "passive_checks_enabled=%d\n", temp_service->accept_passive_service_checks); + fprintf(fp, "passive_checks_enabled=%d\n", temp_service->accept_passive_checks); fprintf(fp, "event_handler_enabled=%d\n", temp_service->event_handler_enabled); fprintf(fp, "problem_has_been_acknowledged=%d\n", temp_service->problem_has_been_acknowledged); fprintf(fp, "acknowledgement_type=%d\n", temp_service->acknowledgement_type); fprintf(fp, "flap_detection_enabled=%d\n", temp_service->flap_detection_enabled); - fprintf(fp, "failure_prediction_enabled=%d\n", temp_service->failure_prediction_enabled); fprintf(fp, "process_performance_data=%d\n", temp_service->process_performance_data); - fprintf(fp, "obsess_over_service=%d\n", temp_service->obsess_over_service); + fprintf(fp, "obsess=%d\n", temp_service->obsess); fprintf(fp, "is_flapping=%d\n", temp_service->is_flapping); fprintf(fp, "percent_state_change=%.2f\n", temp_service->percent_state_change); fprintf(fp, "check_flapping_recovery_notification=%d\n", temp_service->check_flapping_recovery_notification); @@ -505,8 +336,8 @@ int xrddefault_save_state_information(void) { fprintf(fp, "modified_service_attributes=%lu\n", (temp_contact->modified_service_attributes & ~contact_service_attribute_mask)); fprintf(fp, "host_notification_period=%s\n", (temp_contact->host_notification_period == NULL) ? "" : temp_contact->host_notification_period); fprintf(fp, "service_notification_period=%s\n", (temp_contact->service_notification_period == NULL) ? "" : temp_contact->service_notification_period); - fprintf(fp, "last_host_notification=%lu\n", temp_contact->last_host_notification); - fprintf(fp, "last_service_notification=%lu\n", temp_contact->last_service_notification); + fprintf(fp, "last_host_notification=%llu\n", (unsigned long long)temp_contact->last_host_notification); + fprintf(fp, "last_service_notification=%llu\n", (unsigned long long)temp_contact->last_service_notification); fprintf(fp, "host_notifications_enabled=%d\n", temp_contact->host_notifications_enabled); fprintf(fp, "service_notifications_enabled=%d\n", temp_contact->service_notifications_enabled); @@ -533,9 +364,9 @@ int xrddefault_save_state_information(void) { fprintf(fp, "comment_id=%lu\n", temp_comment->comment_id); fprintf(fp, "source=%d\n", temp_comment->source); fprintf(fp, "persistent=%d\n", temp_comment->persistent); - fprintf(fp, "entry_time=%lu\n", temp_comment->entry_time); + fprintf(fp, "entry_time=%llu\n", (unsigned long long)temp_comment->entry_time); fprintf(fp, "expires=%d\n", temp_comment->expires); - fprintf(fp, "expire_time=%lu\n", temp_comment->expire_time); + fprintf(fp, "expire_time=%llu\n", (unsigned long long)temp_comment->expire_time); fprintf(fp, "author=%s\n", temp_comment->author); fprintf(fp, "comment_data=%s\n", temp_comment->comment_data); fprintf(fp, "}\n"); @@ -553,10 +384,10 @@ int xrddefault_save_state_information(void) { fprintf(fp, "service_description=%s\n", temp_downtime->service_description); fprintf(fp, "comment_id=%lu\n", temp_downtime->comment_id); fprintf(fp, "downtime_id=%lu\n", temp_downtime->downtime_id); - fprintf(fp, "entry_time=%lu\n", temp_downtime->entry_time); - fprintf(fp, "start_time=%lu\n", temp_downtime->start_time); - fprintf(fp, "flex_downtime_start=%lu\n", temp_downtime->flex_downtime_start); - fprintf(fp, "end_time=%lu\n", temp_downtime->end_time); + fprintf(fp, "entry_time=%llu\n", (unsigned long long)temp_downtime->entry_time); + fprintf(fp, "start_time=%llu\n", (unsigned long long)temp_downtime->start_time); + fprintf(fp, "flex_downtime_start=%llu\n", (unsigned long long)temp_downtime->flex_downtime_start); + fprintf(fp, "end_time=%llu\n", (unsigned long long)temp_downtime->end_time); fprintf(fp, "triggered_by=%lu\n", temp_downtime->triggered_by); fprintf(fp, "fixed=%d\n", temp_downtime->fixed); fprintf(fp, "duration=%lu\n", temp_downtime->duration); @@ -568,8 +399,8 @@ int xrddefault_save_state_information(void) { } fflush(fp); - result = fclose(fp); fsync(fd); + result = fclose(fp); /* save/close was successful */ if(result == 0) { @@ -577,9 +408,9 @@ int xrddefault_save_state_information(void) { result = OK; /* move the temp file to the retention file (overwrite the old retention file) */ - if(my_rename(temp_file, xrddefault_retention_file)) { - unlink(temp_file); - logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Unable to update retention file '%s': %s", xrddefault_retention_file, strerror(errno)); + if(my_rename(tmp_file, retention_file)) { + unlink(tmp_file); + logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Unable to update retention file '%s': %s", retention_file, strerror(errno)); result = ERROR; } } @@ -590,12 +421,12 @@ int xrddefault_save_state_information(void) { result = ERROR; /* remove temp file and log an error */ - unlink(temp_file); + unlink(tmp_file); logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Unable to save retention file: %s", strerror(errno)); } /* free memory */ - my_free(temp_file); + my_free(tmp_file); return result; } @@ -642,7 +473,7 @@ int xrddefault_read_state_information(void) { int scheduling_info_is_ok = FALSE; unsigned long downtime_id = 0; time_t start_time = 0L; - time_t flex_downtime_start = (time_t)0; + time_t flex_downtime_start = ( time_t)0; time_t end_time = 0L; int fixed = FALSE; unsigned long triggered_by = 0; @@ -668,7 +499,7 @@ int xrddefault_read_state_information(void) { log_debug_info(DEBUGL_FUNCTIONS, 0, "xrddefault_read_state_information() start\n"); /* make sure we have what we need */ - if(xrddefault_retention_file == NULL) { + if(retention_file == NULL) { logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: We don't have a filename for retention data!\n"); @@ -679,7 +510,7 @@ int xrddefault_read_state_information(void) { gettimeofday(&tv[0], NULL); /* open the retention file for reading */ - if((thefile = mmap_fopen(xrddefault_retention_file)) == NULL) + if((thefile = mmap_fopen(retention_file)) == NULL) return ERROR; /* what attributes should be masked out? */ @@ -768,8 +599,8 @@ int xrddefault_read_state_information(void) { } /* calculate next possible notification time */ - if(temp_host->current_state != HOST_UP && temp_host->last_host_notification != (time_t)0) - temp_host->next_host_notification = get_next_host_notification_time(temp_host, temp_host->last_host_notification); + if(temp_host->current_state != HOST_UP && temp_host->last_notification != (time_t)0) + temp_host->next_notification = get_next_host_notification_time(temp_host, temp_host->last_notification); /* ADDED 01/23/2009 adjust current check attempts if host in hard problem state (max attempts may have changed in config since restart) */ if(temp_host->current_state != HOST_UP && temp_host->state_type == HARD_STATE) @@ -939,7 +770,7 @@ int xrddefault_read_state_information(void) { remove_comment = TRUE; } /* non-persistent comments don't last past restarts UNLESS they're acks (see above) */ - else if(persistent == FALSE) + else if(persistent == FALSE && (sigrestart == FALSE || entry_type == DOWNTIME_COMMENT)) remove_comment = TRUE; if(remove_comment == TRUE) @@ -984,7 +815,7 @@ int xrddefault_read_state_information(void) { downtime_id = 0; entry_time = 0L; start_time = 0L; - flex_downtime_start = (time_t)0; + flex_downtime_start = ( time_t)0; end_time = 0L; fixed = FALSE; triggered_by = 0; @@ -1102,10 +933,6 @@ int xrddefault_read_state_information(void) { if(modified_host_process_attributes & MODATTR_FLAP_DETECTION_ENABLED) enable_flap_detection = (atoi(val) > 0) ? TRUE : FALSE; } - else if(!strcmp(var, "enable_failure_prediction")) { - if(modified_host_process_attributes & MODATTR_FAILURE_PREDICTION_ENABLED) - enable_failure_prediction = (atoi(val) > 0) ? TRUE : FALSE; - } else if(!strcmp(var, "process_performance_data")) { if(modified_host_process_attributes & MODATTR_PERFORMANCE_DATA_ENABLED) process_performance_data = (atoi(val) > 0) ? TRUE : FALSE; @@ -1212,7 +1039,7 @@ int xrddefault_read_state_information(void) { temp_host->check_options = atoi(val); } else if(!strcmp(var, "current_attempt")) - temp_host->current_attempt = (atoi(val) > 0) ? TRUE : FALSE; + temp_host->current_attempt = atoi(val); else if(!strcmp(var, "current_event_id")) temp_host->current_event_id = strtoul(val, NULL, 10); else if(!strcmp(var, "last_event_id")) @@ -1234,11 +1061,11 @@ int xrddefault_read_state_information(void) { else if(!strcmp(var, "last_time_unreachable")) temp_host->last_time_unreachable = strtoul(val, NULL, 10); else if(!strcmp(var, "notified_on_down")) - temp_host->notified_on_down = (atoi(val) > 0) ? TRUE : FALSE; + temp_host->notified_on |= (atoi(val) > 0 ? OPT_DOWN : 0); else if(!strcmp(var, "notified_on_unreachable")) - temp_host->notified_on_unreachable = (atoi(val) > 0) ? TRUE : FALSE; + temp_host->notified_on |= (atoi(val) > 0 ? OPT_UNREACHABLE : 0); else if(!strcmp(var, "last_notification")) - temp_host->last_host_notification = strtoul(val, NULL, 10); + temp_host->last_notification = strtoul(val, NULL, 10); else if(!strcmp(var, "current_notification_number")) temp_host->current_notification_number = atoi(val); else if(!strcmp(var, "current_notification_id")) @@ -1280,7 +1107,7 @@ int xrddefault_read_state_information(void) { } else if(!strcmp(var, "passive_checks_enabled")) { if(temp_host->modified_attributes & MODATTR_PASSIVE_CHECKS_ENABLED) - temp_host->accept_passive_host_checks = (atoi(val) > 0) ? TRUE : FALSE; + temp_host->accept_passive_checks = (atoi(val) > 0) ? TRUE : FALSE; } else if(!strcmp(var, "event_handler_enabled")) { if(temp_host->modified_attributes & MODATTR_EVENT_HANDLER_ENABLED) @@ -1290,17 +1117,13 @@ int xrddefault_read_state_information(void) { if(temp_host->modified_attributes & MODATTR_FLAP_DETECTION_ENABLED) temp_host->flap_detection_enabled = (atoi(val) > 0) ? TRUE : FALSE; } - else if(!strcmp(var, "failure_prediction_enabled")) { - if(temp_host->modified_attributes & MODATTR_FAILURE_PREDICTION_ENABLED) - temp_host->failure_prediction_enabled = (atoi(val) > 0) ? TRUE : FALSE; - } else if(!strcmp(var, "process_performance_data")) { if(temp_host->modified_attributes & MODATTR_PERFORMANCE_DATA_ENABLED) temp_host->process_performance_data = (atoi(val) > 0) ? TRUE : FALSE; } - else if(!strcmp(var, "obsess_over_host")) { + else if(!strcmp(var, "obsess_over_host") || !strcmp(var, "obsess")) { if(temp_host->modified_attributes & MODATTR_OBSESSIVE_HANDLER_ENABLED) - temp_host->obsess_over_host = (atoi(val) > 0) ? TRUE : FALSE; + temp_host->obsess = (atoi(val) > 0) ? TRUE : FALSE; } else if(!strcmp(var, "check_command")) { if(temp_host->modified_attributes & MODATTR_CHECK_COMMAND) { @@ -1313,8 +1136,8 @@ int xrddefault_read_state_information(void) { my_free(tempval); if(temp_command != NULL && temp_ptr != NULL) { - my_free(temp_host->host_check_command); - temp_host->host_check_command = temp_ptr; + my_free(temp_host->check_command); + temp_host->check_command = temp_ptr; } else temp_host->modified_attributes -= MODATTR_CHECK_COMMAND; @@ -1368,11 +1191,11 @@ int xrddefault_read_state_information(void) { temp_host->modified_attributes -= MODATTR_EVENT_HANDLER_COMMAND; } } - else if(!strcmp(var, "normal_check_interval")) { + else if(!strcmp(var, "check_interval")) { if(temp_host->modified_attributes & MODATTR_NORMAL_CHECK_INTERVAL && strtod(val, NULL) >= 0) temp_host->check_interval = strtod(val, NULL); } - else if(!strcmp(var, "retry_check_interval")) { + else if(!strcmp(var, "retry_interval")) { if(temp_host->modified_attributes & MODATTR_RETRY_CHECK_INTERVAL && strtod(val, NULL) >= 0) temp_host->retry_interval = strtod(val, NULL); } @@ -1507,11 +1330,11 @@ int xrddefault_read_state_information(void) { temp_service->check_options = atoi(val); } else if(!strcmp(var, "notified_on_unknown")) - temp_service->notified_on_unknown = (atoi(val) > 0) ? TRUE : FALSE; + temp_service->notified_on |= ((atoi(val) > 0) ? OPT_UNKNOWN : 0); else if(!strcmp(var, "notified_on_warning")) - temp_service->notified_on_warning = (atoi(val) > 0) ? TRUE : FALSE; + temp_service->notified_on |= ((atoi(val) > 0) ? OPT_WARNING : 0); else if(!strcmp(var, "notified_on_critical")) - temp_service->notified_on_critical = (atoi(val) > 0) ? TRUE : FALSE; + temp_service->notified_on |= ((atoi(val) > 0) ? OPT_CRITICAL : 0); else if(!strcmp(var, "current_notification_number")) temp_service->current_notification_number = atoi(val); else if(!strcmp(var, "current_notification_id")) @@ -1555,7 +1378,7 @@ int xrddefault_read_state_information(void) { } else if(!strcmp(var, "passive_checks_enabled")) { if(temp_service->modified_attributes & MODATTR_PASSIVE_CHECKS_ENABLED) - temp_service->accept_passive_service_checks = (atoi(val) > 0) ? TRUE : FALSE; + temp_service->accept_passive_checks = (atoi(val) > 0) ? TRUE : FALSE; } else if(!strcmp(var, "event_handler_enabled")) { if(temp_service->modified_attributes & MODATTR_EVENT_HANDLER_ENABLED) @@ -1565,17 +1388,13 @@ int xrddefault_read_state_information(void) { if(temp_service->modified_attributes & MODATTR_FLAP_DETECTION_ENABLED) temp_service->flap_detection_enabled = (atoi(val) > 0) ? TRUE : FALSE; } - else if(!strcmp(var, "failure_prediction_enabled")) { - if(temp_service->modified_attributes & MODATTR_FAILURE_PREDICTION_ENABLED) - temp_service->failure_prediction_enabled = (atoi(val) > 0) ? TRUE : FALSE; - } else if(!strcmp(var, "process_performance_data")) { if(temp_service->modified_attributes & MODATTR_PERFORMANCE_DATA_ENABLED) temp_service->process_performance_data = (atoi(val) > 0) ? TRUE : FALSE; } - else if(!strcmp(var, "obsess_over_service")) { + else if(!strcmp(var, "obsess_over_service") || !strcmp(var, "obsess")) { if(temp_service->modified_attributes & MODATTR_OBSESSIVE_HANDLER_ENABLED) - temp_service->obsess_over_service = (atoi(val) > 0) ? TRUE : FALSE; + temp_service->obsess = (atoi(val) > 0) ? TRUE : FALSE; } else if(!strcmp(var, "check_command")) { if(temp_service->modified_attributes & MODATTR_CHECK_COMMAND) { @@ -1588,8 +1407,8 @@ int xrddefault_read_state_information(void) { my_free(tempval); if(temp_command != NULL && temp_ptr != NULL) { - my_free(temp_service->service_check_command); - temp_service->service_check_command = temp_ptr; + my_free(temp_service->check_command); + temp_service->check_command = temp_ptr; } else temp_service->modified_attributes -= MODATTR_CHECK_COMMAND; @@ -1643,11 +1462,11 @@ int xrddefault_read_state_information(void) { temp_service->modified_attributes -= MODATTR_EVENT_HANDLER_COMMAND; } } - else if(!strcmp(var, "normal_check_interval")) { + else if(!strcmp(var, "check_interval")) { if(temp_service->modified_attributes & MODATTR_NORMAL_CHECK_INTERVAL && strtod(val, NULL) >= 0) temp_service->check_interval = strtod(val, NULL); } - else if(!strcmp(var, "retry_check_interval")) { + else if(!strcmp(var, "retry_interval")) { if(temp_service->modified_attributes & MODATTR_RETRY_CHECK_INTERVAL && strtod(val, NULL) >= 0) temp_service->retry_interval = strtod(val, NULL); } diff --git a/xdata/xrddefault.h b/xdata/xrddefault.h index c8fab4f..31a3635 100644 --- a/xdata/xrddefault.h +++ b/xdata/xrddefault.h @@ -2,8 +2,6 @@ * * XRDDEFAULT.H - Header file for default state retention routines * - * Copyright (c) 1999-2006 Ethan Galstad (egalstad@nagios.org) - * Last Modified: 03-01-2006 * * License: * @@ -22,8 +20,8 @@ * *****************************************************************************/ -#ifndef _XRDDEFAULT_H -#define _XRDDEFAULT_H +#ifndef NAGIOS_XRDDEFAULT_H_INCLUDED +#define NAGIOS_XRDDEFAULT_H_INCLUDED #define XRDDEFAULT_NO_DATA 0 @@ -37,10 +35,8 @@ #define XRDDEFAULT_HOSTDOWNTIME_DATA 8 #define XRDDEFAULT_SERVICEDOWNTIME_DATA 9 -int xrddefault_initialize_retention_data(char *); -int xrddefault_cleanup_retention_data(char *); -int xrddefault_grab_config_info(char *); -int xrddefault_grab_config_directives(char *); +int xrddefault_initialize_retention_data(const char *); +int xrddefault_cleanup_retention_data(void); int xrddefault_save_state_information(void); /* saves all host and service state information */ int xrddefault_read_state_information(void); /* reads in initial host and service state information */ diff --git a/xdata/xsddefault.c b/xdata/xsddefault.c index c8d0d20..dfde377 100644 --- a/xdata/xsddefault.c +++ b/xdata/xsddefault.c @@ -2,9 +2,6 @@ * * XSDDEFAULT.C - Default external status data input routines for Nagios * - * Copyright (c) 2009 Nagios Core Development Team and Community Contributors - * Copyright (c) 2000-2009 Ethan Galstad (egalstad@nagios.org) - * Last Modified: 07-31-2009 * * License: * @@ -33,7 +30,7 @@ #include "../include/comments.h" #include "../include/downtime.h" #include "../include/macros.h" -#include "../include/skiplist.h" +#include "xsddefault.h" #ifdef NSCORE #include "../include/nagios.h" @@ -41,18 +38,8 @@ #ifdef NSCGI #include "../include/cgiutils.h" -#endif - - -/**** IMPLEMENTATION SPECIFIC HEADER FILES ****/ -#include "xsddefault.h" - - - -#ifdef NSCGI time_t program_start; int daemon_mode; -time_t last_command_check; time_t last_log_rotation; int enable_notifications; int execute_service_checks; @@ -65,221 +52,12 @@ int obsess_over_hosts; int check_service_freshness; int check_host_freshness; int enable_flap_detection; -int enable_failure_prediction; int process_performance_data; int nagios_pid; int buffer_stats[1][3]; int program_stats[MAX_CHECK_STATS_TYPES][3]; #endif -#ifdef NSCORE -extern time_t program_start; -extern int nagios_pid; -extern int daemon_mode; -extern time_t last_command_check; -extern time_t last_log_rotation; -extern int enable_notifications; -extern int execute_service_checks; -extern int accept_passive_service_checks; -extern int execute_host_checks; -extern int accept_passive_host_checks; -extern int enable_event_handlers; -extern int obsess_over_services; -extern int obsess_over_hosts; -extern int check_service_freshness; -extern int check_host_freshness; -extern int enable_flap_detection; -extern int enable_failure_prediction; -extern int process_performance_data; -extern int aggregate_status_updates; -extern int check_external_commands; - -extern time_t last_update_check; -extern char *last_program_version; -extern int update_available; -extern char *last_program_version; -extern char *new_program_version; - -extern int external_command_buffer_slots; -extern circular_buffer external_command_buffer; - -extern host *host_list; -extern service *service_list; -extern contact *contact_list; -extern comment *comment_list; -extern scheduled_downtime *scheduled_downtime_list; - -extern skiplist *object_skiplists[NUM_OBJECT_SKIPLISTS]; - -extern unsigned long next_comment_id; -extern unsigned long next_downtime_id; -extern unsigned long next_event_id; -extern unsigned long next_problem_id; -extern unsigned long next_notification_id; - -extern unsigned long modified_host_process_attributes; -extern unsigned long modified_service_process_attributes; -extern char *global_host_event_handler; -extern char *global_service_event_handler; - -extern check_stats check_statistics[MAX_CHECK_STATS_TYPES]; -#endif - - -char *xsddefault_status_log = NULL; -char *xsddefault_temp_file = NULL; - - - -/******************************************************************/ -/***************** COMMON CONFIG INITIALIZATION ******************/ -/******************************************************************/ - -/* grab configuration information */ -int xsddefault_grab_config_info(char *config_file) { - char *input = NULL; - mmapfile *thefile; -#ifdef NSCGI - char *input2 = NULL; - mmapfile *thefile2; - char *temp_buffer; -#else - nagios_macros *mac; -#endif - - - /*** CORE PASSES IN MAIN CONFIG FILE, CGIS PASS IN CGI CONFIG FILE! ***/ - - /* open the config file for reading */ - if((thefile = mmap_fopen(config_file)) == NULL) - return ERROR; - - /* read in all lines from the main config file */ - while(1) { - - /* free memory */ - my_free(input); - - /* read the next line */ - if((input = mmap_fgets_multiline(thefile)) == NULL) - break; - - strip(input); - - /* skip blank lines and comments */ - if(input[0] == '#' || input[0] == '\x0') - continue; - -#ifdef NSCGI - /* CGI needs to find and read contents of main config file, since it was passed the name of the CGI config file */ - if(strstr(input, "main_config_file") == input) { - - temp_buffer = strtok(input, "="); - temp_buffer = strtok(NULL, "\n"); - if(temp_buffer == NULL) - continue; - - if((thefile2 = mmap_fopen(temp_buffer)) == NULL) - continue; - - /* read in all lines from the main config file */ - while(1) { - - /* free memory */ - my_free(input2); - - /* read the next line */ - if((input2 = mmap_fgets_multiline(thefile2)) == NULL) - break; - - strip(input2); - - /* skip blank lines and comments */ - if(input2[0] == '#' || input2[0] == '\x0') - continue; - - xsddefault_grab_config_directives(input2); - } - - /* free memory and close the file */ - my_free(input2); - mmap_fclose(thefile2); - } -#endif - -#ifdef NSCORE - /* core reads variables directly from the main config file */ - xsddefault_grab_config_directives(input); -#endif - } - - /* free memory and close the file */ - my_free(input); - mmap_fclose(thefile); - - /* initialize locations if necessary */ - if(xsddefault_status_log == NULL) - xsddefault_status_log = (char *)strdup(DEFAULT_STATUS_FILE); - if(xsddefault_temp_file == NULL) - xsddefault_temp_file = (char *)strdup(DEFAULT_TEMP_FILE); - - /* make sure we have what we need */ - if(xsddefault_status_log == NULL) - return ERROR; - if(xsddefault_temp_file == NULL) - return ERROR; - -#ifdef NSCORE - mac = get_global_macros(); - /* save the status file macro */ - my_free(mac->x[MACRO_STATUSDATAFILE]); - if((mac->x[MACRO_STATUSDATAFILE] = (char *)strdup(xsddefault_status_log))) - strip(mac->x[MACRO_STATUSDATAFILE]); -#endif - - return OK; - } - - -/* processes a single directive */ -int xsddefault_grab_config_directives(char *input) { - char *temp_ptr = NULL; - char *varname = NULL; - char *varvalue = NULL; - - /* get the variable name */ - if((temp_ptr = my_strtok(input, "=")) == NULL) - return ERROR; - if((varname = (char *)strdup(temp_ptr)) == NULL) - return ERROR; - - /* get the variable value */ - if((temp_ptr = my_strtok(NULL, "\n")) == NULL) { - my_free(varname); - return ERROR; - } - if((varvalue = (char *)strdup(temp_ptr)) == NULL) { - my_free(varname); - return ERROR; - } - - /* status log definition */ - if(!strcmp(varname, "status_file") || !strcmp(varname, "xsddefault_status_log")) - xsddefault_status_log = (char *)strdup(temp_ptr); - - /* temp file definition */ - else if(!strcmp(varname, "temp_file")) - xsddefault_temp_file = (char *)strdup(temp_ptr); - - /* free memory */ - my_free(varname); - my_free(varvalue); - - return OK; - } - - - #ifdef NSCORE /******************************************************************/ @@ -288,34 +66,42 @@ int xsddefault_grab_config_directives(char *input) { /* initialize status data */ -int xsddefault_initialize_status_data(char *config_file) { - int result; +int xsddefault_initialize_status_data(const char *cfgfile) { + nagios_macros *mac; - /* grab configuration data */ - result = xsddefault_grab_config_info(config_file); - if(result == ERROR) + /* initialize locations if necessary */ + if(!status_file) + status_file = (char *)strdup(DEFAULT_STATUS_FILE); + + /* make sure we have what we need */ + if(status_file == NULL) return ERROR; + mac = get_global_macros(); + /* save the status file macro */ + my_free(mac->x[MACRO_STATUSDATAFILE]); + if((mac->x[MACRO_STATUSDATAFILE] = (char *)strdup(status_file))) + strip(mac->x[MACRO_STATUSDATAFILE]); + /* delete the old status log (it might not exist) */ - if(xsddefault_status_log) - unlink(xsddefault_status_log); + if(status_file) + unlink(status_file); return OK; } /* cleanup status data before terminating */ -int xsddefault_cleanup_status_data(char *config_file, int delete_status_data) { +int xsddefault_cleanup_status_data(int delete_status_data) { /* delete the status log */ - if(delete_status_data == TRUE && xsddefault_status_log) { - if(unlink(xsddefault_status_log)) + if(delete_status_data == TRUE && status_file) { + if(unlink(status_file)) return ERROR; } /* free memory */ - my_free(xsddefault_status_log); - my_free(xsddefault_temp_file); + my_free(status_file); return OK; } @@ -327,38 +113,37 @@ int xsddefault_cleanup_status_data(char *config_file, int delete_status_data) { /* write all status data to file */ int xsddefault_save_status_data(void) { - char *temp_file = NULL; + char *tmp_log = NULL; customvariablesmember *temp_customvariablesmember = NULL; host *temp_host = NULL; service *temp_service = NULL; contact *temp_contact = NULL; - comment *temp_comment = NULL; + nagios_comment *temp_comment = NULL; scheduled_downtime *temp_downtime = NULL; time_t current_time; int fd = 0; FILE *fp = NULL; - int used_external_command_buffer_slots = 0; - int high_external_command_buffer_slots = 0; int result = OK; log_debug_info(DEBUGL_FUNCTIONS, 0, "save_status_data()\n"); - /* open a safe temp file for output */ - if(xsddefault_temp_file == NULL) - return ERROR; - asprintf(&temp_file, "%sXXXXXX", xsddefault_temp_file); - if(temp_file == NULL) + /* users may not want us to write status data */ + if(!status_file || !strcmp(status_file, "/dev/null")) + return OK; + + 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", temp_file); + log_debug_info(DEBUGL_STATUSDATA, 2, "Writing status data to temp file '%s'\n", tmp_log); - if((fd = mkstemp(temp_file)) == -1) { + if((fd = mkstemp(tmp_log)) == -1) { /* log an error */ - logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Unable to create temp file for writing status data: %s\n", strerror(errno)); + logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Unable to create temp file '%s' for writing status data: %s\n", tmp_log, strerror(errno)); /* free memory */ - my_free(temp_file); + my_free(tmp_log); return ERROR; } @@ -366,29 +151,17 @@ int xsddefault_save_status_data(void) { if(fp == NULL) { close(fd); - unlink(temp_file); + unlink(tmp_log); /* log an error */ - logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Unable to open temp file '%s' for writing status data: %s\n", temp_file, strerror(errno)); + logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Unable to open temp file '%s' for writing status data: %s\n", tmp_log, strerror(errno)); /* free memory */ - my_free(temp_file); + my_free(tmp_log); return ERROR; } - /* get number of items in the command buffer */ - if(check_external_commands == TRUE) { - pthread_mutex_lock(&external_command_buffer.buffer_lock); - used_external_command_buffer_slots = external_command_buffer.items; - high_external_command_buffer_slots = external_command_buffer.high; - pthread_mutex_unlock(&external_command_buffer.buffer_lock); - } - else { - used_external_command_buffer_slots = 0; - high_external_command_buffer_slots = 0; - } - /* generate check statistics */ generate_check_stats(); @@ -404,9 +177,9 @@ int xsddefault_save_status_data(void) { /* write file info */ fprintf(fp, "info {\n"); - fprintf(fp, "\tcreated=%lu\n", current_time); + fprintf(fp, "\tcreated=%llu\n", (unsigned long long)current_time); fprintf(fp, "\tversion=%s\n", PROGRAM_VERSION); - fprintf(fp, "\tlast_update_check=%lu\n", last_update_check); + fprintf(fp, "\tlast_update_check=%llu\n", (unsigned long long)last_update_check); fprintf(fp, "\tupdate_available=%d\n", update_available); fprintf(fp, "\tlast_version=%s\n", (last_program_version == NULL) ? "" : last_program_version); fprintf(fp, "\tnew_version=%s\n", (new_program_version == NULL) ? "" : new_program_version); @@ -418,9 +191,8 @@ int xsddefault_save_status_data(void) { 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_command_check=%lu\n", last_command_check); - fprintf(fp, "\tlast_log_rotation=%lu\n", last_log_rotation); + fprintf(fp, "\tprogram_start=%llu\n", (unsigned long long)program_start); + fprintf(fp, "\tlast_log_rotation=%llu\n", (unsigned long long)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); @@ -432,7 +204,6 @@ int xsddefault_save_status_data(void) { 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, "\tenable_failure_prediction=%d\n", enable_failure_prediction); 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); @@ -441,9 +212,6 @@ int xsddefault_save_status_data(void) { 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, "\ttotal_external_command_buffer_slots=%d\n", external_command_buffer_slots); - fprintf(fp, "\tused_external_command_buffer_slots=%d\n", used_external_command_buffer_slots); - fprintf(fp, "\thigh_external_command_buffer_slots=%d\n", high_external_command_buffer_slots); 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]); @@ -466,7 +234,7 @@ int xsddefault_save_status_data(void) { 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->host_check_command == NULL) ? "" : temp_host->host_check_command); + 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); @@ -487,19 +255,19 @@ int xsddefault_save_status_data(void) { 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, "\tlast_check=%llu\n", (unsigned long long)temp_host->last_check); + fprintf(fp, "\tnext_check=%llu\n", (unsigned long long)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_host_notification); - fprintf(fp, "\tnext_notification=%lu\n", temp_host->next_host_notification); + fprintf(fp, "\tlast_state_change=%llu\n", (unsigned long long)temp_host->last_state_change); + fprintf(fp, "\tlast_hard_state_change=%llu\n", (unsigned long long)temp_host->last_hard_state_change); + fprintf(fp, "\tlast_time_up=%llu\n", (unsigned long long)temp_host->last_time_up); + fprintf(fp, "\tlast_time_down=%llu\n", (unsigned long long)temp_host->last_time_down); + fprintf(fp, "\tlast_time_unreachable=%llu\n", (unsigned long long)temp_host->last_time_unreachable); + fprintf(fp, "\tlast_notification=%llu\n", (unsigned long long)temp_host->last_notification); + fprintf(fp, "\tnext_notification=%llu\n", (unsigned long long)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); @@ -507,22 +275,15 @@ int xsddefault_save_status_data(void) { 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_host_checks); + 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, "\tfailure_prediction_enabled=%d\n", temp_host->failure_prediction_enabled); fprintf(fp, "\tprocess_performance_data=%d\n", temp_host->process_performance_data); - fprintf(fp, "\tobsess_over_host=%d\n", temp_host->obsess_over_host); - fprintf(fp, "\tlast_update=%lu\n", current_time); + fprintf(fp, "\tobsess=%d\n", temp_host->obsess); + fprintf(fp, "\tlast_update=%llu\n", (unsigned long long)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); - /* - fprintf(fp,"\tstate_history="); - for(x=0;x0)?",":"",temp_host->state_history[(x+temp_host->state_history_index)%MAX_STATE_HISTORY_ENTRIES]); - fprintf(fp,"\n"); - */ /* custom variables */ for(temp_customvariablesmember = temp_host->custom_variables; temp_customvariablesmember != NULL; temp_customvariablesmember = temp_customvariablesmember->next) { if(temp_customvariablesmember->variable_name) @@ -539,7 +300,7 @@ int xsddefault_save_status_data(void) { 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->service_check_command == NULL) ? "" : temp_service->service_check_command); + 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); @@ -560,43 +321,36 @@ int xsddefault_save_status_data(void) { 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, "\tlast_state_change=%llu\n", (unsigned long long)temp_service->last_state_change); + fprintf(fp, "\tlast_hard_state_change=%llu\n", (unsigned long long)temp_service->last_hard_state_change); + fprintf(fp, "\tlast_time_ok=%llu\n", (unsigned long long)temp_service->last_time_ok); + fprintf(fp, "\tlast_time_warning=%llu\n", (unsigned long long)temp_service->last_time_warning); + fprintf(fp, "\tlast_time_unknown=%llu\n", (unsigned long long)temp_service->last_time_unknown); + fprintf(fp, "\tlast_time_critical=%llu\n", (unsigned long long)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, "\tlast_check=%llu\n", (unsigned long long)temp_service->last_check); + fprintf(fp, "\tnext_check=%llu\n", (unsigned long long)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, "\tlast_notification=%llu\n", (unsigned long long)temp_service->last_notification); + fprintf(fp, "\tnext_notification=%llu\n", (unsigned long long)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_service_checks); + 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, "\tfailure_prediction_enabled=%d\n", temp_service->failure_prediction_enabled); fprintf(fp, "\tprocess_performance_data=%d\n", temp_service->process_performance_data); - fprintf(fp, "\tobsess_over_service=%d\n", temp_service->obsess_over_service); - fprintf(fp, "\tlast_update=%lu\n", current_time); + fprintf(fp, "\tobsess=%d\n", temp_service->obsess); + fprintf(fp, "\tlast_update=%llu\n", (unsigned long long)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); - /* - fprintf(fp,"\tstate_history="); - for(x=0;x0)?",":"",temp_service->state_history[(x+temp_service->state_history_index)%MAX_STATE_HISTORY_ENTRIES]); - fprintf(fp,"\n"); - */ /* custom variables */ for(temp_customvariablesmember = temp_service->custom_variables; temp_customvariablesmember != NULL; temp_customvariablesmember = temp_customvariablesmember->next) { if(temp_customvariablesmember->variable_name) @@ -617,8 +371,8 @@ int xsddefault_save_status_data(void) { 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, "\tlast_host_notification=%llu\n", (unsigned long long)temp_contact->last_host_notification); + fprintf(fp, "\tlast_service_notification=%llu\n", (unsigned long long)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 */ @@ -643,9 +397,9 @@ int xsddefault_save_status_data(void) { 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, "\tentry_time=%llu\n", (unsigned long long)temp_comment->entry_time); fprintf(fp, "\texpires=%d\n", temp_comment->expires); - fprintf(fp, "\texpire_time=%lu\n", temp_comment->expire_time); + fprintf(fp, "\texpire_time=%llu\n", (unsigned long long)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"); @@ -663,10 +417,10 @@ int xsddefault_save_status_data(void) { 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, "\tentry_time=%llu\n", (unsigned long long)temp_downtime->entry_time); + fprintf(fp, "\tstart_time=%llu\n", (unsigned long long)temp_downtime->start_time); + fprintf(fp, "\tflex_downtime_start=%llu\n", (unsigned long long)temp_downtime->flex_downtime_start); + fprintf(fp, "\tend_time=%llu\n", (unsigned long long)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); @@ -684,21 +438,21 @@ int xsddefault_save_status_data(void) { /* flush the file to disk */ fflush(fp); - /* close the temp file */ - result = fclose(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(temp_file, xsddefault_status_log)) { - unlink(temp_file); - logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Unable to update status data file '%s': %s", xsddefault_status_log, strerror(errno)); + if(my_rename(tmp_log, status_file)) { + unlink(tmp_log); + logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Unable to update status data file '%s': %s", status_file, strerror(errno)); result = ERROR; } } @@ -709,12 +463,12 @@ int xsddefault_save_status_data(void) { result = ERROR; /* remove temp file and log an error */ - unlink(temp_file); + unlink(tmp_log); logit(NSLOG_RUNTIME_ERROR, TRUE, "Error: Unable to save status file: %s", strerror(errno)); } /* free memory */ - my_free(temp_file); + my_free(tmp_log); return result; } @@ -730,7 +484,7 @@ int xsddefault_save_status_data(void) { /******************************************************************/ /* read all program, host, and service status information */ -int xsddefault_read_status_data(char *config_file, int options) { +int xsddefault_read_status_data(const char *status_file_name, int options) { #ifdef NO_MMAP char input[MAX_PLUGIN_OUTPUT_LENGTH] = ""; FILE *fp = NULL; @@ -744,7 +498,6 @@ int xsddefault_read_status_data(char *config_file, int options) { char *var = NULL; char *val = NULL; char *ptr = NULL; - int result = 0; /* comment and downtime vars */ unsigned long comment_id = 0; int persistent = FALSE; @@ -757,6 +510,7 @@ int xsddefault_read_status_data(char *config_file, int options) { char *service_description = NULL; char *author = NULL; char *comment_data = NULL; + scheduled_downtime *temp_downtime; unsigned long downtime_id = 0; time_t start_time = 0L; time_t flex_downtime_start = 0L; @@ -776,17 +530,12 @@ int xsddefault_read_status_data(char *config_file, int options) { program_stats[x][2] = 0; } - /* grab configuration data */ - result = xsddefault_grab_config_info(config_file); - if(result == ERROR) - return ERROR; - /* open the status file for reading */ #ifdef NO_MMAP - if((fp = fopen(xsddefault_status_log, "r")) == NULL) + if((fp = fopen(status_file_name, "r")) == NULL) return ERROR; #else - if((thefile = mmap_fopen(xsddefault_status_log)) == NULL) + if((thefile = mmap_fopen(status_file_name)) == NULL) return ERROR; #endif @@ -892,10 +641,16 @@ int xsddefault_read_status_data(char *config_file, int options) { case XSDDEFAULT_SERVICEDOWNTIME_DATA: /* add the downtime */ - if(data_type == XSDDEFAULT_HOSTDOWNTIME_DATA) + if(data_type == XSDDEFAULT_HOSTDOWNTIME_DATA) { add_host_downtime(host_name, entry_time, author, comment_data, start_time, flex_downtime_start, end_time, fixed, triggered_by, duration, downtime_id, is_in_effect, start_notification_sent); - else + temp_downtime = find_downtime(HOST_DOWNTIME, downtime_id); + } else { add_service_downtime(host_name, service_description, entry_time, author, comment_data, start_time, flex_downtime_start, end_time, fixed, triggered_by, duration, downtime_id, is_in_effect, start_notification_sent); + temp_downtime = find_downtime(SERVICE_DOWNTIME, downtime_id); + } + + if (temp_downtime) + temp_downtime->comment_id = comment_id; /* free temp memory */ my_free(host_name); @@ -905,6 +660,7 @@ int xsddefault_read_status_data(char *config_file, int options) { /* reset defaults */ downtime_id = 0; + comment_id = 0; entry_time = 0L; start_time = 0L; end_time = 0L; @@ -943,8 +699,6 @@ int xsddefault_read_status_data(char *config_file, int options) { daemon_mode = (atoi(val) > 0) ? TRUE : FALSE; else if(!strcmp(var, "program_start")) program_start = strtoul(val, NULL, 10); - else if(!strcmp(var, "last_command_check")) - last_command_check = strtoul(val, NULL, 10); else if(!strcmp(var, "last_log_rotation")) last_log_rotation = strtoul(val, NULL, 10); else if(!strcmp(var, "enable_notifications")) @@ -969,19 +723,9 @@ int xsddefault_read_status_data(char *config_file, int options) { check_host_freshness = (atoi(val) > 0) ? TRUE : FALSE; else if(!strcmp(var, "enable_flap_detection")) enable_flap_detection = (atoi(val) > 0) ? TRUE : FALSE; - else if(!strcmp(var, "enable_failure_prediction")) - enable_failure_prediction = (atoi(val) > 0) ? TRUE : FALSE; else if(!strcmp(var, "process_performance_data")) process_performance_data = (atoi(val) > 0) ? TRUE : FALSE; - else if(!strcmp(var, "total_external_command_buffer_slots")) - buffer_stats[0][0] = atoi(val); - else if(!strcmp(var, "used_external_command_buffer_slots")) - buffer_stats[0][1] = atoi(val); - else if(!strcmp(var, "high_external_command_buffer_slots")) - buffer_stats[0][2] = atoi(val); - - else if(strstr(var, "_stats")) { x = -1; @@ -1060,8 +804,6 @@ int xsddefault_read_status_data(char *config_file, int options) { temp_hoststatus->next_check = strtoul(val, NULL, 10); else if(!strcmp(var, "check_options")) temp_hoststatus->check_options = atoi(val); - else if(!strcmp(var, "current_attempt")) - temp_hoststatus->current_attempt = (atoi(val) > 0) ? TRUE : FALSE; else if(!strcmp(var, "state_type")) temp_hoststatus->state_type = atoi(val); else if(!strcmp(var, "last_state_change")) @@ -1091,33 +833,26 @@ int xsddefault_read_status_data(char *config_file, int options) { else if(!strcmp(var, "active_checks_enabled")) temp_hoststatus->checks_enabled = (atoi(val) > 0) ? TRUE : FALSE; else if(!strcmp(var, "passive_checks_enabled")) - temp_hoststatus->accept_passive_host_checks = (atoi(val) > 0) ? TRUE : FALSE; + temp_hoststatus->accept_passive_checks = (atoi(val) > 0) ? TRUE : FALSE; else if(!strcmp(var, "event_handler_enabled")) temp_hoststatus->event_handler_enabled = (atoi(val) > 0) ? TRUE : FALSE; else if(!strcmp(var, "flap_detection_enabled")) temp_hoststatus->flap_detection_enabled = (atoi(val) > 0) ? TRUE : FALSE; - else if(!strcmp(var, "failure_prediction_enabled")) - temp_hoststatus->failure_prediction_enabled = (atoi(val) > 0) ? TRUE : FALSE; else if(!strcmp(var, "process_performance_data")) temp_hoststatus->process_performance_data = (atoi(val) > 0) ? TRUE : FALSE; - else if(!strcmp(var, "obsess_over_host")) - temp_hoststatus->obsess_over_host = (atoi(val) > 0) ? TRUE : FALSE; + else if(!strcmp(var, "obsess_over_host") || !strcmp(var, "obsess")) + temp_hoststatus->obsess = (atoi(val) > 0) ? TRUE : FALSE; else if(!strcmp(var, "last_update")) temp_hoststatus->last_update = strtoul(val, NULL, 10); else if(!strcmp(var, "is_flapping")) temp_hoststatus->is_flapping = (atoi(val) > 0) ? TRUE : FALSE; else if(!strcmp(var, "percent_state_change")) temp_hoststatus->percent_state_change = strtod(val, NULL); - else if(!strcmp(var, "scheduled_downtime_depth")) + else if(!strcmp(var, "scheduled_downtime_depth")) { temp_hoststatus->scheduled_downtime_depth = atoi(val); - /* - else if(!strcmp(var,"state_history")){ - temp_ptr=val; - for(x=0;xstate_history[x]=atoi(my_strsep(&temp_ptr,",")); - temp_hoststatus->state_history_index=0; - } - */ + if (temp_hoststatus->scheduled_downtime_depth < 0) + temp_hoststatus->scheduled_downtime_depth = 0; + } } break; @@ -1189,7 +924,7 @@ int xsddefault_read_status_data(char *config_file, int options) { else if(!strcmp(var, "active_checks_enabled")) temp_servicestatus->checks_enabled = (atoi(val) > 0) ? TRUE : FALSE; else if(!strcmp(var, "passive_checks_enabled")) - temp_servicestatus->accept_passive_service_checks = (atoi(val) > 0) ? TRUE : FALSE; + temp_servicestatus->accept_passive_checks = (atoi(val) > 0) ? TRUE : FALSE; else if(!strcmp(var, "event_handler_enabled")) temp_servicestatus->event_handler_enabled = (atoi(val) > 0) ? TRUE : FALSE; else if(!strcmp(var, "problem_has_been_acknowledged")) @@ -1198,28 +933,21 @@ int xsddefault_read_status_data(char *config_file, int options) { temp_servicestatus->acknowledgement_type = atoi(val); else if(!strcmp(var, "flap_detection_enabled")) temp_servicestatus->flap_detection_enabled = (atoi(val) > 0) ? TRUE : FALSE; - else if(!strcmp(var, "failure_prediction_enabled")) - temp_servicestatus->failure_prediction_enabled = (atoi(val) > 0) ? TRUE : FALSE; else if(!strcmp(var, "process_performance_data")) temp_servicestatus->process_performance_data = (atoi(val) > 0) ? TRUE : FALSE; - else if(!strcmp(var, "obsess_over_service")) - temp_servicestatus->obsess_over_service = (atoi(val) > 0) ? TRUE : FALSE; + else if(!strcmp(var, "obsess_over_service") || !strcmp(var, "obsess")) + temp_servicestatus->obsess = (atoi(val) > 0) ? TRUE : FALSE; else if(!strcmp(var, "last_update")) temp_servicestatus->last_update = strtoul(val, NULL, 10); else if(!strcmp(var, "is_flapping")) temp_servicestatus->is_flapping = (atoi(val) > 0) ? TRUE : FALSE; else if(!strcmp(var, "percent_state_change")) temp_servicestatus->percent_state_change = strtod(val, NULL); - else if(!strcmp(var, "scheduled_downtime_depth")) + else if(!strcmp(var, "scheduled_downtime_depth")) { temp_servicestatus->scheduled_downtime_depth = atoi(val); - /* - else if(!strcmp(var,"state_history")){ - temp_ptr=val; - for(x=0;xstate_history[x]=atoi(my_strsep(&temp_ptr,",")); - temp_servicestatus->state_history_index=0; - } - */ + if (temp_servicestatus->scheduled_downtime_depth < 0) + temp_servicestatus->scheduled_downtime_depth = 0; + } } break; @@ -1302,10 +1030,6 @@ int xsddefault_read_status_data(char *config_file, int options) { mmap_fclose(thefile); #endif - /* free memory */ - my_free(xsddefault_status_log); - my_free(xsddefault_temp_file); - if(sort_downtime() != OK) return ERROR; if(sort_comments() != OK) @@ -1315,4 +1039,3 @@ int xsddefault_read_status_data(char *config_file, int options) { } #endif - diff --git a/xdata/xsddefault.h b/xdata/xsddefault.h index 0a9eec1..77f45ce 100644 --- a/xdata/xsddefault.h +++ b/xdata/xsddefault.h @@ -2,8 +2,6 @@ * * XSDDEFAULT.H - Header file for default status data routines * - * Copyright (c) 1999-2006 Ethan Galstad (egalstad@nagios.org) - * Last Modified: 03-01-2006 * * License: * @@ -22,12 +20,12 @@ * *****************************************************************************/ -#ifndef _XSDDEFAULT_H -#define _XSDDEFAULT_H +#ifndef NAGIOS_XSDDEFAULT_H_INCLUDED +#define NAGIOS_XSDDEFAULT_H_INCLUDED #ifdef NSCORE -int xsddefault_initialize_status_data(char *); -int xsddefault_cleanup_status_data(char *, int); +int xsddefault_initialize_status_data(const char *); +int xsddefault_cleanup_status_data(int); int xsddefault_save_status_data(void); #endif @@ -44,10 +42,7 @@ int xsddefault_save_status_data(void); #define XSDDEFAULT_HOSTDOWNTIME_DATA 8 #define XSDDEFAULT_SERVICEDOWNTIME_DATA 9 -int xsddefault_read_status_data(char *, int); +int xsddefault_read_status_data(const char *, int); #endif -int xsddefault_grab_config_info(char *); -int xsddefault_grab_config_directives(char *); - #endif
\n"); - printf("\n"); + printf("
\n"); printf("\n"); printf("\n", EXTINFO_CGI, DISPLAY_PERFORMANCE); printf("\n"); @@ -974,10 +900,10 @@ void display_tac_overview(void) { printf("\n"); printf("",""],legend:[1,"
","
"],thead:[1,"
 Monitoring Performance
\n"); - printf("\n"); + printf("
\n"); printf("\n"); printf(""; - echo ""; - - # foreach over each item in the array. - # displaying simple links - # - # we could be doing all sorts of neat things with the dublin core - # info, or the event info, or what not, but keeping it simple for now. - # - foreach ($rss->items as $item ) { - echo ""; - } - - echo "
\n"); - printf("\n"); + printf("
\n"); printf("\n"); printf("", EXTINFO_CGI, DISPLAY_PERFORMANCE); printf("\n", EXTINFO_CGI, DISPLAY_PERFORMANCE, min_service_execution_time, max_service_execution_time, average_service_execution_time); @@ -1103,11 +1029,11 @@ void display_tac_overview(void) { strncpy(service_health_image, THERM_OK_IMAGE, sizeof(service_health_image)); service_health_image[sizeof(service_health_image) - 1] = '\x0'; - printf("
Service Check Execution Time:%.2f / %.2f / %.3f sec
\n"); + printf("
\n"); printf("\n"); printf("\n"); @@ -1320,10 +1246,10 @@ void display_tac_overview(void) { printf("
\n"); - printf("\n"); + printf("
\n"); printf("\n"); printf("\n"); printf("\n"); @@ -1115,10 +1041,10 @@ void display_tac_overview(void) { printf("\n"); printf("\n"); @@ -1239,7 +1165,7 @@ void display_tac_overview(void) { printf("
 Network Health
\n"); - printf("\n"); + printf("
\n"); printf("\n"); printf("\n"); @@ -1208,16 +1134,16 @@ void display_tac_overview(void) { printf("
\n"); - printf("\n"); + printf("
\n"); printf("\n"); printf(""); printf("\n", url_images_path, host_health_image, (percent_host_health < 5.0) ? 5 : (int)percent_host_health, percent_host_health, percent_host_health); @@ -1158,9 +1084,9 @@ void display_tac_overview(void) { printf("\n"); printf("\n"); - printf("\n", STATUS_CGI, HOST_DOWN, hosts_down); - printf("\n", STATUS_CGI, HOST_UNREACHABLE, hosts_unreachable); - printf("\n", STATUS_CGI, HOST_UP, hosts_up); + printf("\n", STATUS_CGI, SD_HOST_DOWN, hosts_down); + printf("\n", STATUS_CGI, SD_HOST_UNREACHABLE, hosts_unreachable); + printf("\n", STATUS_CGI, SD_HOST_UP, hosts_up); printf("\n", STATUS_CGI, HOST_PENDING, hosts_pending); printf("\n"); @@ -1177,16 +1103,16 @@ void display_tac_overview(void) { printf("
Host Health:%2.1f%% Health
 Hosts
%d Down%d Unreachable%d Up%d Down%d Unreachable%d Up%d Pending
\n"); if(hosts_down_unacknowledged > 0) - printf("\n", STATUS_CGI, HOST_DOWN, HOST_NO_SCHEDULED_DOWNTIME | HOST_STATE_UNACKNOWLEDGED | HOST_CHECKS_ENABLED, hosts_down_unacknowledged); + printf("\n", STATUS_CGI, SD_HOST_DOWN, HOST_NO_SCHEDULED_DOWNTIME | HOST_STATE_UNACKNOWLEDGED | HOST_CHECKS_ENABLED, hosts_down_unacknowledged); if(hosts_down_scheduled > 0) - printf("\n", STATUS_CGI, HOST_DOWN, HOST_SCHEDULED_DOWNTIME, hosts_down_scheduled); + printf("\n", STATUS_CGI, SD_HOST_DOWN, HOST_SCHEDULED_DOWNTIME, hosts_down_scheduled); if(hosts_down_acknowledged > 0) - printf("\n", STATUS_CGI, HOST_DOWN, HOST_STATE_ACKNOWLEDGED, hosts_down_acknowledged); + printf("\n", STATUS_CGI, SD_HOST_DOWN, HOST_STATE_ACKNOWLEDGED, hosts_down_acknowledged); if(hosts_down_disabled > 0) - printf("\n", STATUS_CGI, HOST_DOWN, HOST_CHECKS_DISABLED, hosts_down_disabled); + printf("\n", STATUS_CGI, SD_HOST_DOWN, HOST_CHECKS_DISABLED, hosts_down_disabled); printf("
%d Unhandled Problems
%d Unhandled Problems
%d Scheduled
%d Scheduled
%d Acknowledged
%d Acknowledged
%d Disabled
%d Disabled
\n"); printf("
\n"); if(hosts_unreachable_unacknowledged > 0) - printf("\n", STATUS_CGI, HOST_UNREACHABLE, HOST_NO_SCHEDULED_DOWNTIME | HOST_STATE_UNACKNOWLEDGED | HOST_CHECKS_ENABLED, hosts_unreachable_unacknowledged); + printf("\n", STATUS_CGI, SD_HOST_UNREACHABLE, HOST_NO_SCHEDULED_DOWNTIME | HOST_STATE_UNACKNOWLEDGED | HOST_CHECKS_ENABLED, hosts_unreachable_unacknowledged); if(hosts_unreachable_scheduled > 0) - printf("\n", STATUS_CGI, HOST_UNREACHABLE, HOST_SCHEDULED_DOWNTIME, hosts_unreachable_scheduled); + printf("\n", STATUS_CGI, SD_HOST_UNREACHABLE, HOST_SCHEDULED_DOWNTIME, hosts_unreachable_scheduled); if(hosts_unreachable_acknowledged > 0) - printf("\n", STATUS_CGI, HOST_UNREACHABLE, HOST_STATE_ACKNOWLEDGED, hosts_unreachable_acknowledged); + printf("\n", STATUS_CGI, SD_HOST_UNREACHABLE, HOST_STATE_ACKNOWLEDGED, hosts_unreachable_acknowledged); if(hosts_unreachable_disabled > 0) - printf("\n", STATUS_CGI, HOST_UNREACHABLE, HOST_CHECKS_DISABLED, hosts_unreachable_disabled); + printf("\n", STATUS_CGI, SD_HOST_UNREACHABLE, HOST_CHECKS_DISABLED, hosts_unreachable_disabled); printf("
%d Unhandled Problems
%d Unhandled Problems
%d Scheduled
%d Scheduled
%d Acknowledged
%d Acknowledged
%d Disabled
%d Disabled
\n"); printf("
\n"); if(hosts_up_disabled > 0) - printf("\n", STATUS_CGI, HOST_UP, HOST_CHECKS_DISABLED, hosts_up_disabled); + printf("\n", STATUS_CGI, SD_HOST_UP, HOST_CHECKS_DISABLED, hosts_up_disabled); printf("
%d Disabled
%d Disabled
\n"); printf("
\n"); if(services_critical_unacknowledged > 0) - printf("\n", STATUS_CGI, SERVICE_CRITICAL, HOST_UP | HOST_PENDING, SERVICE_NO_SCHEDULED_DOWNTIME | SERVICE_STATE_UNACKNOWLEDGED | SERVICE_CHECKS_ENABLED, services_critical_unacknowledged); + printf("\n", STATUS_CGI, SERVICE_CRITICAL, SD_HOST_UP | HOST_PENDING, SERVICE_NO_SCHEDULED_DOWNTIME | SERVICE_STATE_UNACKNOWLEDGED | SERVICE_CHECKS_ENABLED, services_critical_unacknowledged); if(services_critical_host_problem > 0) - printf("\n", STATUS_CGI, SERVICE_CRITICAL, HOST_DOWN | HOST_UNREACHABLE, services_critical_host_problem); + printf("\n", STATUS_CGI, SERVICE_CRITICAL, SD_HOST_DOWN | SD_HOST_UNREACHABLE, services_critical_host_problem); if(services_critical_scheduled > 0) printf("\n", STATUS_CGI, SERVICE_CRITICAL, SERVICE_SCHEDULED_DOWNTIME, services_critical_scheduled); @@ -1355,10 +1281,10 @@ void display_tac_overview(void) { printf("
%d Unhandled Problems
%d Unhandled Problems
%d on Problem Hosts
%d on Problem Hosts
%d Scheduled
\n"); if(services_warning_unacknowledged > 0) - printf("\n", STATUS_CGI, SERVICE_WARNING, HOST_UP | HOST_PENDING, SERVICE_NO_SCHEDULED_DOWNTIME | SERVICE_STATE_UNACKNOWLEDGED | SERVICE_CHECKS_ENABLED, services_warning_unacknowledged); + printf("\n", STATUS_CGI, SERVICE_WARNING, SD_HOST_UP | HOST_PENDING, SERVICE_NO_SCHEDULED_DOWNTIME | SERVICE_STATE_UNACKNOWLEDGED | SERVICE_CHECKS_ENABLED, services_warning_unacknowledged); if(services_warning_host_problem > 0) - printf("\n", STATUS_CGI, SERVICE_WARNING, HOST_DOWN | HOST_UNREACHABLE, services_warning_host_problem); + printf("\n", STATUS_CGI, SERVICE_WARNING, SD_HOST_DOWN | SD_HOST_UNREACHABLE, services_warning_host_problem); if(services_warning_scheduled > 0) printf("\n", STATUS_CGI, SERVICE_WARNING, SERVICE_SCHEDULED_DOWNTIME, services_warning_scheduled); @@ -1390,10 +1316,10 @@ void display_tac_overview(void) { printf("
%d Unhandled Problems
%d Unhandled Problems
%d on Problem Hosts
%d on Problem Hosts
%d Scheduled
\n"); if(services_unknown_unacknowledged > 0) - printf("\n", STATUS_CGI, SERVICE_UNKNOWN, HOST_UP | HOST_PENDING, SERVICE_NO_SCHEDULED_DOWNTIME | SERVICE_STATE_UNACKNOWLEDGED | SERVICE_CHECKS_ENABLED, services_unknown_unacknowledged); + printf("\n", STATUS_CGI, SERVICE_UNKNOWN, SD_HOST_UP | HOST_PENDING, SERVICE_NO_SCHEDULED_DOWNTIME | SERVICE_STATE_UNACKNOWLEDGED | SERVICE_CHECKS_ENABLED, services_unknown_unacknowledged); if(services_unknown_host_problem > 0) - printf("\n", STATUS_CGI, SERVICE_UNKNOWN, HOST_DOWN | HOST_UNREACHABLE, services_unknown_host_problem); + printf("\n", STATUS_CGI, SERVICE_UNKNOWN, SD_HOST_DOWN | SD_HOST_UNREACHABLE, services_unknown_host_problem); if(services_unknown_scheduled > 0) printf("\n", STATUS_CGI, SERVICE_UNKNOWN, SERVICE_SCHEDULED_DOWNTIME, services_unknown_scheduled); @@ -1508,12 +1434,12 @@ void display_tac_overview(void) { printf("\n"); if(flap_disabled_hosts > 0) - printf("\n", STATUS_CGI, HOST_FLAP_DETECTION_DISABLED, flap_disabled_hosts, (flap_disabled_hosts == 1) ? "" : "s"); + printf("\n", STATUS_CGI, HOST_FLAP_DETECTION_DISABLED, flap_disabled_hosts, (flap_disabled_hosts == 1) ? "" : "s"); else printf("\n"); if(flapping_hosts > 0) - printf("\n", STATUS_CGI, HOST_IS_FLAPPING, flapping_hosts, (flapping_hosts == 1) ? "" : "s"); + printf("\n", STATUS_CGI, HOST_IS_FLAPPING, flapping_hosts, (flapping_hosts == 1) ? "" : "s"); else printf("\n"); @@ -1544,7 +1470,7 @@ void display_tac_overview(void) { printf("\n"); if(notification_disabled_hosts > 0) - printf("\n", STATUS_CGI, HOST_NOTIFICATIONS_DISABLED, notification_disabled_hosts, (notification_disabled_hosts == 1) ? "" : "s"); + printf("\n", STATUS_CGI, HOST_NOTIFICATIONS_DISABLED, notification_disabled_hosts, (notification_disabled_hosts == 1) ? "" : "s"); else printf("\n"); @@ -1576,7 +1502,7 @@ void display_tac_overview(void) { printf("\n"); if(event_handler_disabled_hosts > 0) - printf("\n", STATUS_CGI, HOST_EVENT_HANDLER_DISABLED, event_handler_disabled_hosts, (event_handler_disabled_hosts == 1) ? "" : "s"); + printf("\n", STATUS_CGI, HOST_EVENT_HANDLER_DISABLED, event_handler_disabled_hosts, (event_handler_disabled_hosts == 1) ? "" : "s"); else printf("\n"); @@ -1608,7 +1534,7 @@ void display_tac_overview(void) { printf("\n"); if(active_checks_disabled_hosts > 0) - printf("\n", STATUS_CGI, HOST_CHECKS_DISABLED, active_checks_disabled_hosts, (active_checks_disabled_hosts == 1) ? "" : "s"); + printf("\n", STATUS_CGI, HOST_CHECKS_DISABLED, active_checks_disabled_hosts, (active_checks_disabled_hosts == 1) ? "" : "s"); else printf("\n"); @@ -1641,7 +1567,7 @@ void display_tac_overview(void) { printf("\n"); if(passive_checks_disabled_hosts > 0) - printf("\n", STATUS_CGI, HOST_PASSIVE_CHECKS_DISABLED, passive_checks_disabled_hosts, (passive_checks_disabled_hosts == 1) ? "" : "s"); + printf("\n", STATUS_CGI, HOST_PASSIVE_CHECKS_DISABLED, passive_checks_disabled_hosts, (passive_checks_disabled_hosts == 1) ? "" : "s"); else printf("\n"); @@ -1663,4 +1589,3 @@ void display_tac_overview(void) { return; } - diff --git a/cgi/trends.c b/cgi/trends.c index 3d16af5..75fdf60 100644 --- a/cgi/trends.c +++ b/cgi/trends.c @@ -2,8 +2,6 @@ * * TRENDS.C - Nagios State Trends CGI * - * Copyright (c) 1999-2008 Ethan Galstad (egalstad@nagios.org) - * Last Modified: 10-15-2008 * * License: * @@ -43,15 +41,10 @@ extern char url_html_path[MAX_FILENAME_LENGTH]; extern char url_images_path[MAX_FILENAME_LENGTH]; extern char url_stylesheets_path[MAX_FILENAME_LENGTH]; extern char physical_images_path[MAX_FILENAME_LENGTH]; +extern char *status_file; extern int log_rotation_method; -extern host *host_list; -extern service *service_list; - -#include "../include/skiplist.h" -extern skiplist *object_skiplists[NUM_OBJECT_SKIPLISTS]; - /* archived state types */ #define AS_CURRENT_STATE -1 /* special case for initial assumed state */ #define AS_NO_DATA 0 @@ -271,6 +264,9 @@ int main(int argc, char **argv) { /* reset internal CGI variables */ reset_cgi_vars(); + /* Initialize shared configuration variables */ + init_shared_cfg_vars(1); + /* read the CGI configuration file */ result = read_cgi_config_file(get_cgi_config_location()); if(result == ERROR) { @@ -335,7 +331,7 @@ int main(int argc, char **argv) { } /* read all status data */ - result = read_all_status_data(get_cgi_config_location(), READ_ALL_STATUS_DATA); + result = read_all_status_data(status_file, READ_ALL_STATUS_DATA); if(result == ERROR) { if(mode == CREATE_HTML) { document_header(FALSE); @@ -394,7 +390,7 @@ int main(int argc, char **argv) { problem_found = FALSE; if(display_type == DISPLAY_HOST_TRENDS) { for(temp_as = as_list; temp_as != NULL; temp_as = temp_as->next) { - if((temp_as->entry_type == HOST_DOWN || temp_as->entry_type == HOST_UNREACHABLE) && temp_as->time_stamp > t1) { + if((temp_as->entry_type == SD_HOST_DOWN || temp_as->entry_type == SD_HOST_UNREACHABLE) && temp_as->time_stamp > t1) { problem_t1 = temp_as->time_stamp; problem_found = TRUE; break; @@ -453,7 +449,7 @@ int main(int argc, char **argv) { if(display_type == DISPLAY_HOST_TRENDS) { printf("View Availability Report For This Host
\n", AVAIL_CGI, url_encode(host_name), t1, t2, (include_soft_states == TRUE) ? "yes" : "no", (assume_state_retention == TRUE) ? "yes" : "no", (assume_initial_states == TRUE) ? "yes" : "no", (assume_states_during_notrunning == TRUE) ? "yes" : "no", initial_assumed_host_state, backtrack_archives); -#ifdef USE_HISTROGRAM +#ifdef USE_HISTOGRAM printf("View Alert Histogram For This Host
\n", HISTOGRAM_CGI, url_encode(host_name), t1, t2, (assume_state_retention == TRUE) ? "yes" : "no"); #endif printf("View Status Detail For This Host
\n", STATUS_CGI, url_encode(host_name)); @@ -461,7 +457,11 @@ int main(int argc, char **argv) { printf("View Notifications For This Host
\n", NOTIFICATIONS_CGI, url_encode(host_name)); } else { +#ifdef LEGACY_GRAPHICAL_CGIS printf("View Trends For This Host
\n", TRENDS_CGI, url_encode(host_name), t1, t2, (include_soft_states == TRUE) ? "yes" : "no", (assume_state_retention == TRUE) ? "yes" : "no", (assume_initial_states == TRUE) ? "yes" : "no", (assume_states_during_notrunning == TRUE) ? "yes" : "no", initial_assumed_service_state, backtrack_archives); +#else + printf("View Trends For This Host
\n", LEGACY_TRENDS_CGI, url_encode(host_name), t1, t2, (include_soft_states == TRUE) ? "yes" : "no", (assume_state_retention == TRUE) ? "yes" : "no", (assume_initial_states == TRUE) ? "yes" : "no", (assume_states_during_notrunning == TRUE) ? "yes" : "no", initial_assumed_service_state, backtrack_archives); +#endif printf("View Availability Report For This Service
\n", url_encode(svc_description), t1, t2, (include_soft_states == TRUE) ? "yes" : "no", (assume_state_retention == TRUE) ? "yes" : "no", (assume_initial_states == TRUE) ? "yes" : "no", (assume_states_during_notrunning == TRUE) ? "yes" : "no", initial_assumed_service_state, backtrack_archives); printf("\n"); if(display_type != DISPLAY_NO_TRENDS && input_type == GET_INPUT_NONE) { @@ -809,7 +813,11 @@ int main(int argc, char **argv) { printf("

\n"); printf("
\n"); +#ifdef LEGACY_GRAPHICAL_CGIS printf("
\n"); +#ifdef LEGACY_GRAPHICAL_CGIS printf("\n", TRENDS_CGI); +#else + printf("\n", LEGACY_TRENDS_CGI); +#endif printf("\n"); printf("
%d Unhandled Problems
%d Unhandled Problems
%d on Problem Hosts
%d on Problem Hosts
%d Scheduled
No Services Flapping
%d Host%s Disabled
%d Host%s Disabled
All Hosts Enabled
%d Host%s Flapping
%d Host%s Flapping
No Hosts Flapping
All Services Enabled
%d Host%s Disabled
%d Host%s Disabled
All Hosts Enabled
All Services Enabled
%d Host%s Disabled
%d Host%s Disabled
All Hosts Enabled
All Services Enabled
%d Host%s Disabled
%d Host%s Disabled
All Hosts Enabled
All Services Enabled
%d Host%s Disabled
%d Host%s Disabled
All Hosts Enabled
\n"); @@ -931,7 +943,11 @@ int main(int argc, char **argv) { printf("

\n"); +#ifdef LEGACY_GRAPHICAL_CGIS printf("\n", TRENDS_CGI); +#else + printf("\n", LEGACY_TRENDS_CGI); +#endif printf("\n"); printf("\n", (first_service == NULL) ? "unknown" : (char *)escape_string(first_service)); printf("
\n"); @@ -975,7 +991,11 @@ int main(int argc, char **argv) { printf("

\n"); +#ifdef LEGACY_GRAPHICAL_CGIS printf("\n", TRENDS_CGI); +#else + printf("\n", LEGACY_TRENDS_CGI); +#endif printf("\n", escape_string(host_name)); if(display_type == DISPLAY_SERVICE_TRENDS) printf("\n", escape_string(svc_description)); @@ -1137,7 +1157,11 @@ int main(int argc, char **argv) { printf("

\n"); +#ifdef LEGACY_GRAPHICAL_CGIS printf("\n", TRENDS_CGI); +#else + printf("\n", LEGACY_TRENDS_CGI); +#endif printf("
\n"); printf("\n"); @@ -1190,7 +1214,7 @@ void document_header(int use_stylesheet) { get_time_string(&expire_time, date_time, sizeof(date_time), HTTP_DATE_TIME); printf("Expires: %s\r\n", date_time); - printf("Content-type: text/html\r\n\r\n"); + printf("Content-type: text/html; charset=utf-8\r\n\r\n"); if(embedded == TRUE) return; @@ -1216,7 +1240,11 @@ void document_header(int use_stylesheet) { printf("\n"); /* include user SSI header */ +#ifdef LEGACY_GRAPHICAL_CGIS include_ssi_files(TRENDS_CGI, SSI_HEADER); +#else + include_ssi_files(LEGACY_TRENDS_CGI, SSI_HEADER); +#endif printf("
\n"); } @@ -1249,7 +1277,11 @@ void document_footer(void) { if(mode == CREATE_HTML) { /* include user SSI footer */ +#ifdef LEGACY_GRAPHICAL_CGIS include_ssi_files(TRENDS_CGI, SSI_FOOTER); +#else + include_ssi_files(LEGACY_TRENDS_CGI, SSI_FOOTER); +#endif printf("\n"); printf("\n"); @@ -1271,7 +1303,6 @@ int process_cgivars(void) { /* do some basic length checking on the variable identifier to prevent buffer overflows */ if(strlen(variables[x]) >= MAX_INPUT_BUFFER - 1) { - x++; continue; } @@ -1739,7 +1770,6 @@ void graph_all_trend_data(void) { hoststatus *hststatus = NULL; servicestatus *svcstatus = NULL; unsigned long wobble = 300; - int first_real_state = AS_NO_DATA; time_t initial_assumed_time; int initial_assumed_state = AS_SVC_OK; int error = FALSE; @@ -1766,25 +1796,22 @@ void graph_all_trend_data(void) { /* the "wobble" value is necessary because when the CGI is called to do the PNG generation, t2 will actually be less that current_time by a bit */ /* if we don't have any data, assume current state (if possible) */ - if(as_list == NULL && current_time > t1 && current_time < (t2 + wobble)) { + if(as_list == NULL && current_time > t1 && current_time < (time_t)(t2 + wobble)) { /* we don't have any historical information, but the current time falls within the reporting period, so use */ /* the current status of the host/service as the starting data */ if(display_type == DISPLAY_HOST_TRENDS) { if(hststatus != NULL) { - if(hststatus->status == HOST_DOWN) + if(hststatus->status == SD_HOST_DOWN) last_known_state = AS_HOST_DOWN; - else if(hststatus->status == HOST_UNREACHABLE) + else if(hststatus->status == SD_HOST_UNREACHABLE) last_known_state = AS_HOST_UNREACHABLE; else last_known_state = AS_HOST_UP; /* add a dummy archived state item, so something can get graphed */ add_archived_state(last_known_state, AS_HARD_STATE, t1, "Current Host State Assumed (Faked Log Entry)"); - - /* use the current state as the last known real state */ - first_real_state = last_known_state; } } else { @@ -1801,9 +1828,6 @@ void graph_all_trend_data(void) { /* add a dummy archived state item, so something can get graphed */ add_archived_state(last_known_state, AS_HARD_STATE, t1, "Current Service State Assumed (Faked Log Entry)"); - - /* use the current state as the last known real state */ - first_real_state = last_known_state; } } } @@ -1838,13 +1862,13 @@ void graph_all_trend_data(void) { if(((display_type == DISPLAY_HOST_TRENDS && initial_assumed_host_state == AS_CURRENT_STATE) || (display_type == DISPLAY_SERVICE_TRENDS && initial_assumed_service_state == AS_CURRENT_STATE)) && error == FALSE) { if(display_type == DISPLAY_HOST_TRENDS) { switch(hststatus->status) { - case HOST_DOWN: + case SD_HOST_DOWN: initial_assumed_state = AS_HOST_DOWN; break; - case HOST_UNREACHABLE: + case SD_HOST_UNREACHABLE: initial_assumed_state = AS_HOST_UNREACHABLE; break; - case HOST_UP: + case SD_HOST_UP: initial_assumed_state = AS_HOST_UP; break; default: @@ -2044,7 +2068,6 @@ void graph_all_trend_data(void) { /* graphs trend data */ void graph_trend_data(int first_state, int last_state, time_t real_start_time, time_t start_time, time_t end_time, char *state_info) { int start_state; - int end_state; int start_pixel = 0; int end_pixel = 0; int color_to_use = 0; @@ -2114,12 +2137,6 @@ void graph_trend_data(int first_state, int last_state, time_t real_start_time, t last_known_state = first_state; } - /* special case if last entry was program stop */ - if(last_state == AS_PROGRAM_END) - end_state = first_state; - else - end_state = last_state; - #ifdef DEBUG printf("Graphing state %d\n", start_state); printf("\tfrom %s", ctime(&start_time)); @@ -2253,7 +2270,11 @@ void graph_trend_data(int first_state, int last_state, time_t real_start_time, t printf("coords='%d,%d,%d,%d' ", drawing_x_offset + start_pixel, drawing_y_offset + (drawing_height - height), drawing_x_offset + end_pixel, drawing_y_offset + drawing_height); - printf("href='%s?t1=%lu&t2=%lu&host=%s", TRENDS_CGI, (unsigned long)next_start_time, (unsigned long)next_end_time, url_encode(host_name)); +#ifdef LEGACY_GRAPHICAL_CGIS + printf("href='%s?t1=%llu&t2=%llu&host=%s", TRENDS_CGI, (unsigned long long)next_start_time, (unsigned long long)next_end_time, url_encode(host_name)); +#else + printf("href='%s?t1=%llu&t2=%llu&host=%s", LEGACY_TRENDS_CGI, (unsigned long long)next_start_time, (unsigned long long)next_end_time, url_encode(host_name)); +#endif if(display_type == DISPLAY_SERVICE_TRENDS) printf("&service=%s", url_encode(svc_description)); printf("&assumeinitialstates=%s", (assume_initial_states == TRUE) ? "yes" : "no"); @@ -2332,11 +2353,11 @@ void graph_trend_data(int first_state, int last_state, time_t real_start_time, t /* convert current host state to archived state value */ int convert_host_state_to_archived_state(int current_status) { - if(current_status == HOST_UP) + if(current_status == SD_HOST_UP) return AS_HOST_UP; - if(current_status == HOST_DOWN) + if(current_status == SD_HOST_DOWN) return AS_HOST_DOWN; - if(current_status == HOST_UNREACHABLE) + if(current_status == SD_HOST_UNREACHABLE) return AS_HOST_UNREACHABLE; return AS_NO_DATA; @@ -2799,7 +2820,6 @@ void draw_time_breakdowns(void) { unsigned long total_time = 0L; unsigned long total_state_time; unsigned long time_indeterminate = 0L; - int string_height; if(mode == CREATE_HTML) return; @@ -2819,7 +2839,6 @@ void draw_time_breakdowns(void) { else time_indeterminate = total_time - total_state_time; - string_height = gdFontSmall->h; if(display_type == DISPLAY_HOST_TRENDS) { diff --git a/common/Makefile.in b/common/Makefile.in index b0d74f6..6ae77ec 100644 --- a/common/Makefile.in +++ b/common/Makefile.in @@ -1,7 +1,6 @@ ############################ # Makefile for Nagios # -# Last Modified: 04-08-2003 ############################ # Source code directories diff --git a/common/comments.c b/common/comments.c index 72070bb..086cfa0 100644 --- a/common/comments.c +++ b/common/comments.c @@ -2,8 +2,6 @@ * * COMMENTS.C - Comment functions for Nagios * - * Copyright (c) 1999-2010 Ethan Galstad (egalstad@nagios.org) - * Last Modified: 08-28-2010 * * License: * @@ -26,12 +24,7 @@ #include "../include/common.h" #include "../include/comments.h" #include "../include/objects.h" - -/***** IMPLEMENTATION-SPECIFIC INCLUDES *****/ - -#ifdef USE_XCDDEFAULT #include "../xdata/xcddefault.h" -#endif #ifdef NSCORE #include "../include/nagios.h" @@ -43,15 +36,14 @@ #endif -comment *comment_list = NULL; +nagios_comment *comment_list = NULL; int defer_comment_sorting = 0; -comment **comment_hashlist = NULL; +nagios_comment **comment_hashlist = NULL; #ifdef NSCORE -pthread_mutex_t nagios_comment_lock = PTHREAD_MUTEX_INITIALIZER; /******************************************************************/ /**************** INITIALIZATION/CLEANUP FUNCTIONS ****************/ @@ -59,32 +51,11 @@ pthread_mutex_t nagios_comment_lock = PTHREAD_MUTEX_INITIALIZER; /* initializes comment data */ -int initialize_comment_data(char *config_file) { - int result = OK; - - /**** IMPLEMENTATION-SPECIFIC CALLS ****/ -#ifdef USE_XCDDEFAULT - result = xcddefault_initialize_comment_data(config_file); -#endif - - return result; +int initialize_comment_data(void) { + return xcddefault_initialize_comment_data(); } -/* removes old/invalid comments */ -int cleanup_comment_data(char *config_file) { - int result = OK; - - /**** IMPLEMENTATION-SPECIFIC CALLS ****/ -#ifdef USE_XCDDEFAULT - result = xcddefault_cleanup_comment_data(config_file); -#endif - - return result; - } - - - /******************************************************************/ /****************** COMMENT OUTPUT FUNCTIONS **********************/ /******************************************************************/ @@ -92,7 +63,7 @@ int cleanup_comment_data(char *config_file) { /* adds a new host or service comment */ int add_new_comment(int type, int entry_type, char *host_name, char *svc_description, time_t entry_time, char *author_name, char *comment_data, int persistent, int source, int expires, time_t expire_time, unsigned long *comment_id) { - int result = OK; + int result; unsigned long new_comment_id = 0L; if(type == HOST_COMMENT) @@ -114,13 +85,10 @@ int add_new_comment(int type, int entry_type, char *host_name, char *svc_descrip /* adds a new host comment */ int add_new_host_comment(int entry_type, char *host_name, time_t entry_time, char *author_name, char *comment_data, int persistent, int source, int expires, time_t expire_time, unsigned long *comment_id) { - int result = OK; + int result; unsigned long new_comment_id = 0L; - /**** IMPLEMENTATION-SPECIFIC CALLS ****/ -#ifdef USE_XCDDEFAULT result = xcddefault_add_new_host_comment(entry_type, host_name, entry_time, author_name, comment_data, persistent, source, expires, expire_time, &new_comment_id); -#endif /* save comment id */ if(comment_id != NULL) @@ -137,13 +105,10 @@ int add_new_host_comment(int entry_type, char *host_name, time_t entry_time, cha /* adds a new service comment */ int add_new_service_comment(int entry_type, char *host_name, char *svc_description, time_t entry_time, char *author_name, char *comment_data, int persistent, int source, int expires, time_t expire_time, unsigned long *comment_id) { - int result = OK; + int result; unsigned long new_comment_id = 0L; - /**** IMPLEMENTATION-SPECIFIC CALLS ****/ -#ifdef USE_XCDDEFAULT result = xcddefault_add_new_service_comment(entry_type, host_name, svc_description, entry_time, author_name, comment_data, persistent, source, expires, expire_time, &new_comment_id); -#endif /* save comment id */ if(comment_id != NULL) @@ -166,18 +131,12 @@ int add_new_service_comment(int entry_type, char *host_name, char *svc_descripti /* deletes a host or service comment */ int delete_comment(int type, unsigned long comment_id) { - int result = OK; - comment *this_comment = NULL; - comment *last_comment = NULL; - comment *next_comment = NULL; + nagios_comment *this_comment = NULL; + nagios_comment *last_comment = NULL; + nagios_comment *next_comment = NULL; int hashslot = 0; - comment *this_hash = NULL; - comment *last_hash = NULL; - - /* lock the comments so we can modify them safely */ -#ifdef NSCORE - pthread_mutex_lock(&nagios_comment_lock); -#endif + nagios_comment *this_hash = NULL; + nagios_comment *last_hash = NULL; /* find the comment we should remove */ for(this_comment = comment_list, last_comment = comment_list; this_comment != NULL; this_comment = next_comment) { @@ -190,63 +149,47 @@ int delete_comment(int type, unsigned long comment_id) { last_comment = this_comment; } + if(this_comment == NULL) + return ERROR; + /* remove the comment from the list in memory */ - if(this_comment != NULL) { - #ifdef USE_EVENT_BROKER - /* send data to event broker */ - broker_comment_data(NEBTYPE_COMMENT_DELETE, NEBFLAG_NONE, NEBATTR_NONE, type, this_comment->entry_type, this_comment->host_name, this_comment->service_description, this_comment->entry_time, this_comment->author, this_comment->comment_data, this_comment->persistent, this_comment->source, this_comment->expires, this_comment->expire_time, comment_id, NULL); + /* send data to event broker */ + broker_comment_data(NEBTYPE_COMMENT_DELETE, NEBFLAG_NONE, NEBATTR_NONE, type, this_comment->entry_type, this_comment->host_name, this_comment->service_description, this_comment->entry_time, this_comment->author, this_comment->comment_data, this_comment->persistent, this_comment->source, this_comment->expires, this_comment->expire_time, comment_id, NULL); #endif - /* first remove from chained hash list */ - hashslot = hashfunc(this_comment->host_name, NULL, COMMENT_HASHSLOTS); - last_hash = NULL; - for(this_hash = comment_hashlist[hashslot]; this_hash; this_hash = this_hash->nexthash) { - if(this_hash == this_comment) { - if(last_hash) - last_hash->nexthash = this_hash->nexthash; - else { - if(this_hash->nexthash) - comment_hashlist[hashslot] = this_hash->nexthash; - else - comment_hashlist[hashslot] = NULL; - } - break; + /* first remove from chained hash list */ + hashslot = hashfunc(this_comment->host_name, NULL, COMMENT_HASHSLOTS); + last_hash = NULL; + for(this_hash = comment_hashlist[hashslot]; this_hash; this_hash = this_hash->nexthash) { + if(this_hash == this_comment) { + if(last_hash) + last_hash->nexthash = this_hash->nexthash; + else { + if(this_hash->nexthash) + comment_hashlist[hashslot] = this_hash->nexthash; + else + comment_hashlist[hashslot] = NULL; } - last_hash = this_hash; + break; } - - /* then removed from linked list */ - if(comment_list == this_comment) - comment_list = this_comment->next; - else - last_comment->next = next_comment; - - /* free memory */ - my_free(this_comment->host_name); - my_free(this_comment->service_description); - my_free(this_comment->author); - my_free(this_comment->comment_data); - my_free(this_comment); - - result = OK; + last_hash = this_hash; } + + /* then removed from linked list */ + if(comment_list == this_comment) + comment_list = this_comment->next; else - result = ERROR; + last_comment->next = next_comment; - /**** IMPLEMENTATION-SPECIFIC CALLS ****/ -#ifdef USE_XCDDEFAULT - if(type == HOST_COMMENT) - result = xcddefault_delete_host_comment(comment_id); - else - result = xcddefault_delete_service_comment(comment_id); -#endif + /* free memory */ + my_free(this_comment->host_name); + my_free(this_comment->service_description); + my_free(this_comment->author); + my_free(this_comment->comment_data); + my_free(this_comment); -#ifdef NSCORE - pthread_mutex_unlock(&nagios_comment_lock); -#endif - - return result; + return OK; } @@ -289,8 +232,8 @@ int delete_all_comments(int type, char *host_name, char *svc_description) { /* deletes all comments for a particular host */ int delete_all_host_comments(char *host_name) { int result = OK; - comment *temp_comment = NULL; - comment *next_comment = NULL; + nagios_comment *temp_comment = NULL; + nagios_comment *next_comment = NULL; if(host_name == NULL) return ERROR; @@ -309,15 +252,15 @@ int delete_all_host_comments(char *host_name) { /* deletes all non-persistent acknowledgement comments for a particular host */ int delete_host_acknowledgement_comments(host *hst) { int result = OK; - comment *temp_comment = NULL; - comment *next_comment = NULL; + nagios_comment *temp_comment = NULL; + nagios_comment *next_comment = NULL; if(hst == NULL) return ERROR; /* delete comments from memory */ temp_comment = get_first_comment_by_host(hst->name); - while(temp_comment) { + while (temp_comment) { next_comment = get_next_comment_by_host(hst->name, temp_comment); if(temp_comment->comment_type == HOST_COMMENT && temp_comment->entry_type == ACKNOWLEDGEMENT_COMMENT && temp_comment->persistent == FALSE) { delete_comment(HOST_COMMENT, temp_comment->comment_id); @@ -332,8 +275,8 @@ int delete_host_acknowledgement_comments(host *hst) { /* deletes all comments for a particular service */ int delete_all_service_comments(char *host_name, char *svc_description) { int result = OK; - comment *temp_comment = NULL; - comment *next_comment = NULL; + nagios_comment *temp_comment = NULL; + nagios_comment *next_comment = NULL; if(host_name == NULL || svc_description == NULL) return ERROR; @@ -352,8 +295,8 @@ int delete_all_service_comments(char *host_name, char *svc_description) { /* deletes all non-persistent acknowledgement comments for a particular service */ int delete_service_acknowledgement_comments(service *svc) { int result = OK; - comment *temp_comment = NULL; - comment *next_comment = NULL; + nagios_comment *temp_comment = NULL; + nagios_comment *next_comment = NULL; if(svc == NULL) return ERROR; @@ -371,7 +314,7 @@ int delete_service_acknowledgement_comments(service *svc) { /* checks for an expired comment (and removes it) */ int check_for_expired_comment(unsigned long comment_id) { - comment *temp_comment = NULL; + nagios_comment *temp_comment = NULL; /* check all comments */ for(temp_comment = comment_list; temp_comment != NULL; temp_comment = temp_comment->next) { @@ -398,16 +341,16 @@ int check_for_expired_comment(unsigned long comment_id) { /******************************************************************/ /* adds comment to hash list in memory */ -int add_comment_to_hashlist(comment *new_comment) { - comment *temp_comment = NULL; - comment *lastpointer = NULL; +int add_comment_to_hashlist(nagios_comment *new_comment) { + nagios_comment *temp_comment = NULL; + nagios_comment *lastpointer = NULL; int hashslot = 0; /* initialize hash list */ if(comment_hashlist == NULL) { int i; - comment_hashlist = (comment **)malloc(sizeof(comment *) * COMMENT_HASHSLOTS); + comment_hashlist = (nagios_comment **)malloc(sizeof(nagios_comment *) * COMMENT_HASHSLOTS); if(comment_hashlist == NULL) return 0; @@ -467,9 +410,9 @@ int add_service_comment(int entry_type, char *host_name, char *svc_description, /* adds a comment to the list in memory */ int add_comment(int comment_type, int entry_type, char *host_name, char *svc_description, time_t entry_time, char *author, char *comment_data, unsigned long comment_id, int persistent, int expires, time_t expire_time, int source) { - comment *new_comment = NULL; - comment *last_comment = NULL; - comment *temp_comment = NULL; + nagios_comment *new_comment = NULL; + nagios_comment *last_comment = NULL; + nagios_comment *temp_comment = NULL; int result = OK; /* make sure we have the data we need */ @@ -477,7 +420,7 @@ int add_comment(int comment_type, int entry_type, char *host_name, char *svc_des return ERROR; /* allocate memory for the comment */ - if((new_comment = (comment *)calloc(1, sizeof(comment))) == NULL) + if((new_comment = (nagios_comment *)calloc(1, sizeof(nagios_comment))) == NULL) return ERROR; /* duplicate vars */ @@ -522,13 +465,7 @@ int add_comment(int comment_type, int entry_type, char *host_name, char *svc_des comment_list = new_comment; } else { - /* add new comment to comment list, sorted by comment id, - * but lock the list first so broker threads doesn't crash - * out in case they're modifying this list too - */ -#ifdef NSCORE - pthread_mutex_lock(&nagios_comment_lock); -#endif + /* add new comment to comment list, sorted by comment id */ last_comment = comment_list; for(temp_comment = comment_list; temp_comment != NULL; temp_comment = temp_comment->next) { if(new_comment->comment_id < temp_comment->comment_id) { @@ -550,9 +487,6 @@ int add_comment(int comment_type, int entry_type, char *host_name, char *svc_des new_comment->next = NULL; last_comment->next = new_comment; } -#ifdef NSCORE - pthread_mutex_unlock(&nagios_comment_lock); -#endif } #ifdef NSCORE @@ -566,13 +500,13 @@ int add_comment(int comment_type, int entry_type, char *host_name, char *svc_des } static int comment_compar(const void *p1, const void *p2) { - comment *c1 = *(comment **)p1; - comment *c2 = *(comment **)p2; - return (c1->comment_id < c2->comment_id) ? -1 : (c1->comment_id - c2->comment_id); + nagios_comment *c1 = *(nagios_comment **)p1; + nagios_comment *c2 = *(nagios_comment **)p2; + return c1->comment_id - c2->comment_id; } int sort_comments(void) { - comment **array, *temp_comment; + nagios_comment **array, *temp_comment; unsigned long i = 0, unsorted_comments = 0; if(!defer_comment_sorting) @@ -612,8 +546,8 @@ int sort_comments(void) { /* frees memory allocated for the comment data */ void free_comment_data(void) { - comment *this_comment = NULL; - comment *next_comment = NULL; + nagios_comment *this_comment = NULL; + nagios_comment *next_comment = NULL; /* free memory for the comment list */ for(this_comment = comment_list; this_comment != NULL; this_comment = next_comment) { @@ -642,7 +576,7 @@ void free_comment_data(void) { /* get the number of comments associated with a particular host */ int number_of_host_comments(char *host_name) { - comment *temp_comment = NULL; + nagios_comment *temp_comment = NULL; int total_comments = 0; if(host_name == NULL) @@ -659,7 +593,7 @@ int number_of_host_comments(char *host_name) { /* get the number of comments associated with a particular service */ int number_of_service_comments(char *host_name, char *svc_description) { - comment *temp_comment = NULL; + nagios_comment *temp_comment = NULL; int total_comments = 0; if(host_name == NULL || svc_description == NULL) @@ -679,14 +613,14 @@ int number_of_service_comments(char *host_name, char *svc_description) { /********************* TRAVERSAL FUNCTIONS ************************/ /******************************************************************/ -comment *get_first_comment_by_host(char *host_name) { +nagios_comment *get_first_comment_by_host(char *host_name) { return get_next_comment_by_host(host_name, NULL); } -comment *get_next_comment_by_host(char *host_name, comment *start) { - comment *temp_comment = NULL; +nagios_comment *get_next_comment_by_host(char *host_name, nagios_comment *start) { + nagios_comment *temp_comment = NULL; if(host_name == NULL || comment_hashlist == NULL) return NULL; @@ -711,22 +645,22 @@ comment *get_next_comment_by_host(char *host_name, comment *start) { /******************************************************************/ /* find a service comment by id */ -comment *find_service_comment(unsigned long comment_id) { +nagios_comment *find_service_comment(unsigned long comment_id) { return find_comment(comment_id, SERVICE_COMMENT); } /* find a host comment by id */ -comment *find_host_comment(unsigned long comment_id) { +nagios_comment *find_host_comment(unsigned long comment_id) { return find_comment(comment_id, HOST_COMMENT); } /* find a comment by id */ -comment *find_comment(unsigned long comment_id, int comment_type) { - comment *temp_comment = NULL; +nagios_comment *find_comment(unsigned long comment_id, int comment_type) { + nagios_comment *temp_comment = NULL; for(temp_comment = comment_list; temp_comment != NULL; temp_comment = temp_comment->next) { if(temp_comment->comment_id == comment_id && temp_comment->comment_type == comment_type) @@ -735,8 +669,3 @@ comment *find_comment(unsigned long comment_id, int comment_type) { return NULL; } - - - - - diff --git a/common/downtime.c b/common/downtime.c index a749163..c7e3187 100644 --- a/common/downtime.c +++ b/common/downtime.c @@ -2,8 +2,6 @@ * * DOWNTIME.C - Scheduled downtime functions for Nagios * - * Copyright (c) 2000-2008 Ethan Galstad (egalstad@nagios.org) - * Last Modified: 02-17-2008 * * License: * @@ -26,37 +24,184 @@ #include "../include/common.h" #include "../include/comments.h" #include "../include/downtime.h" -#include "../include/objects.h" #include "../include/statusdata.h" -/***** IMPLEMENTATION-SPECIFIC INCLUDES *****/ - -#ifdef USE_XDDDEFAULT -#include "../xdata/xdddefault.h" -#endif - -#ifdef NSCORE -#include "../include/nagios.h" -#include "../include/broker.h" -#endif - #ifdef NSCGI #include "../include/cgiutils.h" +#else +#include "../include/nagios.h" +#include "../include/broker.h" #endif scheduled_downtime *scheduled_downtime_list = NULL; int defer_downtime_sorting = 0; - -#ifdef NSCORE -extern timed_event *event_list_high; -extern timed_event *event_list_high_tail; -pthread_mutex_t nagios_downtime_lock = PTHREAD_MUTEX_INITIALIZER; -#endif +static fanout_table *dt_fanout; +unsigned long next_downtime_id = 0; +#define DT_ENULL (-1) +#define DT_EHOST (-2) +#define DT_ESERVICE (-3) +#define DT_ETYPE (-4) +#define DT_ETRIGGER (-5) +#define DT_ETIME (-6) +static const char *dt_strerror(int err) +{ + if (err > 0) + return strerror(err); -#ifdef NSCORE + switch(err) { + case DT_ENULL: return "NULL pointer"; + case DT_EHOST: return "No hostname, or host not found"; + case DT_ESERVICE: return "No service_description, or service not found"; + case DT_ETYPE: return "Invalid downtime type, or type/data mismatch"; + case DT_ETRIGGER: return "Triggering downtime not found"; + case DT_ETIME: return "Bad time spec"; + } + return "Unknown error"; +} + +static int downtime_compar(const void *p1, const void *p2) { + scheduled_downtime *d1 = *(scheduled_downtime **)p1; + scheduled_downtime *d2 = *(scheduled_downtime **)p2; + + /* + If the start times of two downtimes are equal and one is triggered + but the other is not, the triggered downtime should be later in the + list than the untriggered one. This is so they are written to the + retention.dat and status.dat in the correct order. + + Previously the triggered downtime always appeared before its + triggering downtime in those files. When the downtimes were read + from those files, either on a core restart or by the CGIs, the + triggered downtime would be discarded because the triggering + downtime did not yet exist. + + The most common case for this is when a downtime is created and + the option is selected to create triggered downtimes on all child + objects. This change in the sort order does NOT resolve the + case where a manually created, triggered downtime is created with + a start time earlier than the triggering downtime. + + This would need to be resolved by comparing the triggered_by value + with the downtime ID regardless of the start time. However, this + should be a relatively rare case and only caused by intentional + scheduling by a human. This change was not implemented because it + would cause the downtime list to be out of time order and the + implications of this were not well understood. + */ + + if(d1->start_time == d2->start_time) { + if(( d1->triggered_by == 0 && d2->triggered_by != 0) || + ( d1->triggered_by != 0 && d2->triggered_by == 0)) { + return d1->triggered_by == 0 ? -1 : 1; + } + } + return (d1->start_time < d2->start_time) ? -1 : (d1->start_time - d2->start_time); + } + +static int downtime_add(scheduled_downtime *dt) +{ + unsigned long prev_downtime_id; + scheduled_downtime *trigger = NULL; + struct host *h; + struct service *s; + + if (!dt) + return DT_ENULL; + + log_debug_info(DEBUGL_DOWNTIME, 0, "downtime_add(): id=%lu; type=%s; host=%s; service=%s\n", + dt->downtime_id, + dt->type == HOST_DOWNTIME ? "host" : "service", + dt->host_name, dt->service_description); + /* + * check for errors. + * host_name must always be set + */ + if (!dt->host_name) + return DT_EHOST; + + /* service_description should only be set for service downtime */ + if ((dt->type == HOST_DOWNTIME) != (!dt->service_description)) + return DT_ETYPE; + /* type must be either SERVICE_DOWNTIME or HOST_DOWNTIME */ + if (dt->type != SERVICE_DOWNTIME && dt->type != HOST_DOWNTIME) + return DT_ETYPE; + /* triggered downtime must be triggered by an existing downtime */ + if (dt->triggered_by && !(trigger = find_downtime(ANY_DOWNTIME, dt->triggered_by))) + return DT_ETRIGGER; + /* non-triggered downtime must have start_time < end_time */ + if (!trigger && dt->start_time >= dt->end_time) + return DT_ETIME; + /* flexible downtime must have a duration */ + if (!dt->fixed && !dt->duration) + return DT_ETIME; + + /* the object we're adding downtime for must exist */ + if (!dt->service_description) { + if (!(h = find_host(dt->host_name))) + return DT_EHOST; + } else if (!(s = find_service(dt->host_name, dt->service_description))) { + return DT_ESERVICE; + } + + /* set downtime_id if not already set */ + prev_downtime_id = next_downtime_id; + if (!dt->downtime_id) { + dt->downtime_id = next_downtime_id++; + } else if (dt->downtime_id > next_downtime_id) { + next_downtime_id = dt->downtime_id + 1; + } + + if (fanout_add(dt_fanout, dt->downtime_id, dt) < 0) { + next_downtime_id = prev_downtime_id; + return errno; + } + + if(defer_downtime_sorting || !scheduled_downtime_list || + downtime_compar(&dt, &scheduled_downtime_list) < 0) + { + if (scheduled_downtime_list) { + scheduled_downtime_list->prev = dt; + } + dt->next = scheduled_downtime_list; + scheduled_downtime_list = dt; + } + else { + scheduled_downtime *cur; + + /* add new downtime to downtime list, sorted by start time */ + for(cur = scheduled_downtime_list; cur; cur = cur->next) { + if(downtime_compar(&dt, &cur) < 0) { + dt->prev = cur->prev; + dt->next = cur; + cur->prev->next = dt; + cur->prev = dt; + break; + } + if (!cur->next) { + dt->next = NULL; + cur->next = dt; + dt->prev = cur; + break; + } + } + } + return OK; +} + +void downtime_remove(scheduled_downtime *dt) +{ + fanout_remove(dt_fanout, dt->downtime_id); + if(scheduled_downtime_list == dt) + scheduled_downtime_list = dt->next; + else { + dt->prev->next = dt->next; + if (dt->next) + dt->next->prev = dt->prev; + } +} /******************************************************************/ /**************** INITIALIZATION/CLEANUP FUNCTIONS ****************/ @@ -64,38 +209,24 @@ pthread_mutex_t nagios_downtime_lock = PTHREAD_MUTEX_INITIALIZER; /* initializes scheduled downtime data */ -int initialize_downtime_data(char *config_file) { - int result = OK; - +int initialize_downtime_data(void) { log_debug_info(DEBUGL_FUNCTIONS, 0, "initialize_downtime_data()\n"); - - /**** IMPLEMENTATION-SPECIFIC CALLS ****/ -#ifdef USE_XDDDEFAULT - result = xdddefault_initialize_downtime_data(config_file); -#endif - - return result; + dt_fanout = fanout_create(16384); + next_downtime_id = 1; + return dt_fanout ? OK : ERROR; } /* cleans up scheduled downtime data */ -int cleanup_downtime_data(char *config_file) { - int result = OK; - - log_debug_info(DEBUGL_FUNCTIONS, 0, "cleanup_downtime_data()\n"); - - /**** IMPLEMENTATION-SPECIFIC CALLS ****/ -#ifdef USE_XDDDEFAULT - result = xdddefault_cleanup_downtime_data(config_file); -#endif - +int cleanup_downtime_data(void) { /* free memory allocated to downtime data */ free_downtime_data(); - - return result; + return OK; } +#ifdef NSCORE + /******************************************************************/ /********************** SCHEDULING FUNCTIONS **********************/ /******************************************************************/ @@ -107,14 +238,12 @@ int schedule_downtime(int type, char *host_name, char *service_description, time log_debug_info(DEBUGL_FUNCTIONS, 0, "schedule_downtime()\n"); /* don't add old or invalid downtimes */ - if(start_time >= end_time || end_time <= time(NULL)) { log_debug_info(DEBUGL_DOWNTIME, 1, "Invalid start (%lu) or end (%lu) times\n", - start_time, end_time); + start_time, end_time); return ERROR; } - /* add a new downtime entry */ add_new_downtime(type, host_name, service_description, entry_time, author, comment_data, start_time, end_time, fixed, triggered_by, duration, &downtime_id, FALSE, FALSE); @@ -135,7 +264,6 @@ int unschedule_downtime(int type, unsigned long downtime_id) { scheduled_downtime *next_downtime = NULL; host *hst = NULL; service *svc = NULL; - timed_event *temp_event = NULL; #ifdef USE_EVENT_BROKER int attr = 0; #endif @@ -164,6 +292,10 @@ int unschedule_downtime(int type, unsigned long downtime_id) { svc->pending_flex_downtime--; } + log_debug_info(DEBUGL_DOWNTIME, 0, "Cancelling %s downtime (id=%lu)\n", + temp_downtime->type == HOST_DOWNTIME ? "host" : "service", + temp_downtime->downtime_id); + /* decrement the downtime depth variable and update status data if necessary */ if(temp_downtime->is_in_effect == TRUE) { @@ -175,7 +307,8 @@ int unschedule_downtime(int type, unsigned long downtime_id) { if(temp_downtime->type == HOST_DOWNTIME) { - hst->scheduled_downtime_depth--; + if (hst->scheduled_downtime_depth > 0) + hst->scheduled_downtime_depth--; update_host_status(hst, FALSE); /* log a notice - this is parsed by the history CGI */ @@ -190,7 +323,8 @@ int unschedule_downtime(int type, unsigned long downtime_id) { else { - svc->scheduled_downtime_depth--; + if (svc->scheduled_downtime_depth > 0) + svc->scheduled_downtime_depth--; update_service_status(svc, FALSE); /* log a notice - this is parsed by the history CGI */ @@ -204,17 +338,14 @@ int unschedule_downtime(int type, unsigned long downtime_id) { } } - /* remove scheduled entry from event queue */ - for(temp_event = event_list_high; temp_event != NULL; temp_event = temp_event->next) { - if(temp_event->event_type != EVENT_SCHEDULED_DOWNTIME) - continue; - if(((unsigned long)temp_event->event_data) == downtime_id) - break; + /* remove scheduled entries from event queue */ + if (temp_downtime->start_event) { + remove_event(nagios_squeue, temp_downtime->start_event); + my_free(temp_downtime->start_event); } - if(temp_event != NULL) { - remove_event(temp_event, &event_list_high, &event_list_high_tail); - my_free(temp_event->event_data); - my_free(temp_event); + if (temp_downtime->stop_event) { + remove_event(nagios_squeue, temp_downtime->stop_event); + my_free(temp_downtime->stop_event); } /* delete downtime entry */ @@ -223,7 +354,12 @@ int unschedule_downtime(int type, unsigned long downtime_id) { else delete_service_downtime(downtime_id); - /* unschedule all downtime entries that were triggered by this one */ + /* + * unschedule all downtime entries that were triggered by this one + * @TODO: Fix this algorithm so it uses something sane instead + * of this horrible mess of recursive O(n * t), where t is + * "downtime triggered by this downtime" + */ while(1) { for(temp_downtime = scheduled_downtime_list; temp_downtime != NULL; temp_downtime = next_downtime) { @@ -252,7 +388,7 @@ int register_downtime(int type, unsigned long downtime_id) { scheduled_downtime *temp_downtime = NULL; host *hst = NULL; service *svc = NULL; - char *type_string = NULL; + const char *type_string = NULL; int hours = 0; int minutes = 0; int seconds = 0; @@ -260,7 +396,7 @@ int register_downtime(int type, unsigned long downtime_id) { int was_in_effect = FALSE; log_debug_info(DEBUGL_FUNCTIONS, 0, "register_downtime( %d, %lu)\n", type, - downtime_id); + downtime_id); /* find the downtime entry in memory */ temp_downtime = find_downtime(type, downtime_id); @@ -273,17 +409,17 @@ int register_downtime(int type, unsigned long downtime_id) { if(temp_downtime->type == HOST_DOWNTIME) { if((hst = find_host(temp_downtime->host_name)) == NULL) { log_debug_info(DEBUGL_DOWNTIME, 1, - "Cannot find host (%s) for downtime ID: %lu\n", - temp_downtime->host_name, downtime_id); + "Cannot find host (%s) for downtime ID: %lu\n", + temp_downtime->host_name, downtime_id); return ERROR; } } else { if((svc = find_service(temp_downtime->host_name, temp_downtime->service_description)) == NULL) { log_debug_info(DEBUGL_DOWNTIME, 1, - "Cannot find service (%s) for host (%s) for downtime ID: %lu\n", - temp_downtime->service_description, temp_downtime->host_name, - downtime_id); + "Cannot find service (%s) for host (%s) for downtime ID: %lu\n", + temp_downtime->service_description, temp_downtime->host_name, + downtime_id); return ERROR; } } @@ -317,7 +453,7 @@ int register_downtime(int type, unsigned long downtime_id) { } log_debug_info(DEBUGL_DOWNTIME, 0, " Fixed/Flex: %s\n", (temp_downtime->fixed == TRUE) ? "Fixed" : "Flexible"); log_debug_info(DEBUGL_DOWNTIME, 0, " Start: %s\n", start_time_string); - if(temp_downtime->flex_downtime_start) { + if( temp_downtime->flex_downtime_start) { log_debug_info(DEBUGL_DOWNTIME, 0, " Flex Start: %s\n", flex_start_string); } log_debug_info(DEBUGL_DOWNTIME, 0, " End: %s\n", end_time_string); @@ -334,12 +470,10 @@ int register_downtime(int type, unsigned long downtime_id) { my_free(temp_buffer); - /*** SCHEDULE DOWNTIME - FLEXIBLE (NON-FIXED) DOWNTIME IS HANDLED AT A LATER POINT ***/ - /* only non-triggered downtime is scheduled... */ if((temp_downtime->triggered_by == 0) && ((TRUE == temp_downtime->fixed) || - ((FALSE == temp_downtime->fixed) && - (TRUE == temp_downtime->is_in_effect)))) { + ((FALSE == temp_downtime->fixed) && + (TRUE == temp_downtime->is_in_effect)))) { /* If this is a fixed downtime, schedule the event to start it. If this is a flexible downtime, normally we wait for one of the check_pending_flex_*_downtime() functions to start it, but if the @@ -347,12 +481,11 @@ int register_downtime(int type, unsigned long downtime_id) { Nagios and the downtime was in effect when we last shutdown Nagios, so we should restart the flexible downtime now. This should work even if the downtime has ended because the - handle_scheduled_dowtime() function will immediately schedule + handle_scheduled_downtime() function will immediately schedule another downtime event which will end the downtime. */ - if((new_downtime_id = (unsigned long *)malloc(sizeof(unsigned long *)))) { + if((new_downtime_id = (unsigned long *)malloc(sizeof(unsigned long)))) { *new_downtime_id = downtime_id; - /*temp_downtime->start_event = schedule_new_event(EVENT_SCHEDULED_DOWNTIME, TRUE, temp_downtime->start_time, FALSE, 0, NULL, FALSE, (void *)new_downtime_id, NULL, 0); */ - schedule_new_event(EVENT_SCHEDULED_DOWNTIME, TRUE, temp_downtime->start_time, FALSE, 0, NULL, FALSE, (void *)new_downtime_id, NULL, 0); + temp_downtime->start_event = schedule_new_event(EVENT_SCHEDULED_DOWNTIME, TRUE, temp_downtime->start_time, FALSE, 0, NULL, FALSE, (void *)new_downtime_id, NULL, 0); /* Turn off is_in_effect flag so handle_scheduled_downtime() will handle it correctly */ was_in_effect = temp_downtime->is_in_effect; @@ -380,11 +513,9 @@ int register_downtime(int type, unsigned long downtime_id) { case the event is never triggered. The expire event will NOT cancel a downtime event that is in effect */ log_debug_info(DEBUGL_DOWNTIME, 1, "Scheduling downtime expire event in case flexible downtime is never triggered\n"); - /*temp_downtime->stop_event = schedule_new_event(EVENT_EXPIRE_DOWNTIME, TRUE, (temp_downtime->end_time + 1), FALSE, 0, NULL, FALSE, NULL, NULL, 0);*/ - schedule_new_event(EVENT_EXPIRE_DOWNTIME, TRUE, (temp_downtime->end_time + 1), FALSE, 0, NULL, FALSE, NULL, NULL, 0); + temp_downtime->stop_event = schedule_new_event(EVENT_EXPIRE_DOWNTIME, TRUE, (temp_downtime->end_time + 1), FALSE, 0, NULL, FALSE, NULL, NULL, 0); } - #ifdef PROBABLY_NOT_NEEDED /*** FLEXIBLE DOWNTIME SANITY CHECK - ADDED 02/17/2008 ****/ @@ -412,10 +543,17 @@ int handle_scheduled_downtime_by_id(unsigned long downtime_id) { /* find the downtime entry */ if((temp_downtime = find_downtime(ANY_DOWNTIME, downtime_id)) == NULL) { log_debug_info(DEBUGL_DOWNTIME, 1, "Unable to find downtime id: %lu\n", - downtime_id); + downtime_id); return ERROR; } + /* NULL out this event's start time since the calling function, + handle_timed_event(), will free the event, this will prevent + unschedule_downtime from freeing something that has already been + freed. The start event is not needed within + handle_scheduled_downtime(). */ + temp_downtime->start_event = NULL; + /* handle the downtime */ return handle_scheduled_downtime(temp_downtime); } @@ -428,7 +566,6 @@ int handle_scheduled_downtime(scheduled_downtime *temp_downtime) { host *hst = NULL; service *svc = NULL; time_t event_time = 0L; - //time_t current_time = 0L; unsigned long *new_downtime_id = NULL; #ifdef USE_EVENT_BROKER int attr = 0; @@ -451,11 +588,9 @@ int handle_scheduled_downtime(scheduled_downtime *temp_downtime) { if((svc = find_service(temp_downtime->host_name, temp_downtime->service_description)) == NULL) { log_debug_info(DEBUGL_DOWNTIME, 1, "Unable to find service (%s) host (%s) for downtime\n", temp_downtime->service_description, temp_downtime->host_name); return ERROR; - } } - /* have we come to the end of the scheduled downtime? */ if(temp_downtime->is_in_effect == TRUE) { @@ -466,9 +601,9 @@ int handle_scheduled_downtime(scheduled_downtime *temp_downtime) { #endif /* decrement the downtime depth variable */ - if(temp_downtime->type == HOST_DOWNTIME) + if(temp_downtime->type == HOST_DOWNTIME && hst->scheduled_downtime_depth > 0) hst->scheduled_downtime_depth--; - else + else if (svc->scheduled_downtime_depth > 0) svc->scheduled_downtime_depth--; if(temp_downtime->type == HOST_DOWNTIME && hst->scheduled_downtime_depth == 0) { @@ -550,7 +685,7 @@ int handle_scheduled_downtime(scheduled_downtime *temp_downtime) { logit(NSLOG_INFO_MESSAGE, FALSE, "HOST DOWNTIME ALERT: %s;STARTED; Host has entered a period of scheduled downtime", hst->name); /* send a notification */ - if(FALSE == temp_downtime->start_notification_sent) { + if( FALSE == temp_downtime->start_notification_sent) { host_notification(hst, NOTIFICATION_DOWNTIMESTART, temp_downtime->author, temp_downtime->comment, NOTIFICATION_OPTION_NONE); temp_downtime->start_notification_sent = TRUE; } @@ -564,7 +699,7 @@ int handle_scheduled_downtime(scheduled_downtime *temp_downtime) { logit(NSLOG_INFO_MESSAGE, FALSE, "SERVICE DOWNTIME ALERT: %s;%s;STARTED; Service has entered a period of scheduled downtime", svc->host_name, svc->description); /* send a notification */ - if(FALSE == temp_downtime->start_notification_sent) { + if( FALSE == temp_downtime->start_notification_sent) { service_notification(svc, NOTIFICATION_DOWNTIMESTART, temp_downtime->author, temp_downtime->comment, NOTIFICATION_OPTION_NONE); temp_downtime->start_notification_sent = TRUE; } @@ -588,12 +723,12 @@ int handle_scheduled_downtime(scheduled_downtime *temp_downtime) { /* schedule an event to end the downtime */ if(temp_downtime->fixed == FALSE) { event_time = (time_t)((unsigned long)temp_downtime->flex_downtime_start - + temp_downtime->duration); + + temp_downtime->duration); } else { event_time = temp_downtime->end_time; } - if((new_downtime_id = (unsigned long *)malloc(sizeof(unsigned long *)))) { + if((new_downtime_id = (unsigned long *)malloc(sizeof(unsigned long)))) { *new_downtime_id = temp_downtime->downtime_id; schedule_new_event(EVENT_SCHEDULED_DOWNTIME, TRUE, event_time, FALSE, 0, NULL, FALSE, (void *)new_downtime_id, NULL, 0); } @@ -616,6 +751,7 @@ int check_pending_flex_host_downtime(host *hst) { time_t current_time = 0L; unsigned long * new_downtime_id = NULL; + log_debug_info(DEBUGL_FUNCTIONS, 0, "check_pending_flex_host_downtime()\n"); if(hst == NULL) @@ -650,12 +786,10 @@ int check_pending_flex_host_downtime(host *hst) { if(temp_downtime->start_time <= current_time && current_time <= temp_downtime->end_time) { log_debug_info(DEBUGL_DOWNTIME, 0, "Flexible downtime (id=%lu) for host '%s' starting now...\n", temp_downtime->downtime_id, hst->name); - temp_downtime->flex_downtime_start = current_time; - if((new_downtime_id = (unsigned long *)malloc(sizeof(unsigned long *)))) { + if((new_downtime_id = (unsigned long *)malloc(sizeof(unsigned long)))) { *new_downtime_id = temp_downtime->downtime_id; - /*temp_downtime->start_event = schedule_new_event(EVENT_SCHEDULED_DOWNTIME, TRUE, temp_downtime->flex_downtime_start, FALSE, 0, NULL, FALSE, (void *)new_downtime_id, NULL, 0);*/ - schedule_new_event(EVENT_SCHEDULED_DOWNTIME, TRUE, temp_downtime->flex_downtime_start, FALSE, 0, NULL, FALSE, (void *)new_downtime_id, NULL, 0); + temp_downtime->start_event = schedule_new_event(EVENT_SCHEDULED_DOWNTIME, TRUE, temp_downtime->flex_downtime_start, FALSE, 0, NULL, FALSE, (void *)new_downtime_id, NULL, 0); } } } @@ -669,7 +803,6 @@ int check_pending_flex_host_downtime(host *hst) { int check_pending_flex_service_downtime(service *svc) { scheduled_downtime *temp_downtime = NULL; time_t current_time = 0L; - unsigned long * new_downtime_id = NULL; log_debug_info(DEBUGL_FUNCTIONS, 0, "check_pending_flex_service_downtime()\n"); @@ -708,10 +841,7 @@ int check_pending_flex_service_downtime(service *svc) { log_debug_info(DEBUGL_DOWNTIME, 0, "Flexible downtime (id=%lu) for service '%s' on host '%s' starting now...\n", temp_downtime->downtime_id, svc->description, svc->host_name); temp_downtime->flex_downtime_start = current_time; - if((new_downtime_id = (unsigned long *)malloc(sizeof(unsigned long *)))) { - *new_downtime_id = temp_downtime->downtime_id; - schedule_new_event(EVENT_SCHEDULED_DOWNTIME, TRUE, temp_downtime->flex_downtime_start, FALSE, 0, NULL, FALSE, (void *)new_downtime_id, NULL, 0); - } + handle_scheduled_downtime_by_id(temp_downtime->downtime_id); } } } @@ -719,12 +849,84 @@ int check_pending_flex_service_downtime(service *svc) { return OK; } +int is_host_in_pending_flex_downtime(struct host *temp_host) +{ + scheduled_downtime *temp_downtime = NULL; + time_t current_time = 0L; + + log_debug_info(DEBUGL_FUNCTIONS, 0, "is_host_in_pending_flex_downtime()\n"); + + if (temp_host == NULL) + return FALSE; + + time(¤t_time); + + /* check all downtime entries */ + for (temp_downtime = scheduled_downtime_list; temp_downtime != NULL; temp_downtime = temp_downtime->next) { + if(temp_downtime->type != HOST_DOWNTIME) + continue; + if(temp_downtime->fixed == TRUE) + continue; + if(temp_downtime->is_in_effect == TRUE) + continue; + /* triggered downtime entries should be ignored here */ + if(temp_downtime->triggered_by != 0) + continue; + + /* this entry matches our host! */ + if(find_host(temp_downtime->host_name) == temp_host) { + /* if the time boundaries are okay, start this scheduled downtime */ + if(temp_downtime->start_time <= current_time && current_time <= temp_downtime->end_time) + return TRUE; + } + } + + return FALSE; +} + +int is_service_in_pending_flex_downtime(struct service *temp_service) +{ + scheduled_downtime *temp_downtime = NULL; + time_t current_time = 0L; + + log_debug_info(DEBUGL_FUNCTIONS, 0, "is_service_in_pending_flex_downtime()\n"); + + if(temp_service == NULL) + return FALSE; + + time(¤t_time); + + /* check all downtime entries */ + for(temp_downtime = scheduled_downtime_list; temp_downtime != NULL; temp_downtime = temp_downtime->next) { + if(temp_downtime->type != SERVICE_DOWNTIME) + continue; + if(temp_downtime->fixed == TRUE) + continue; + if(temp_downtime->is_in_effect == TRUE) + continue; + /* triggered downtime entries should be ignored here */ + if(temp_downtime->triggered_by != 0) + continue; + + /* this entry matches our service! */ + if(find_service(temp_downtime->host_name, temp_downtime->service_description) == temp_service) { + /* if the time boundaries are okay, start this scheduled downtime */ + if(temp_downtime->start_time <= current_time && current_time <= temp_downtime->end_time) + return TRUE; + } + } + + return FALSE; +} + /* checks for (and removes) expired downtime entries */ int check_for_expired_downtime(void) { scheduled_downtime *temp_downtime = NULL; scheduled_downtime *next_downtime = NULL; time_t current_time = 0L; + service *svc = NULL; + host *hst = NULL; log_debug_info(DEBUGL_FUNCTIONS, 0, "check_for_expired_downtime()\n"); @@ -737,10 +939,40 @@ int check_for_expired_downtime(void) { next_downtime = temp_downtime->next; /* this entry should be removed */ - if(temp_downtime->is_in_effect == FALSE && temp_downtime->end_time < current_time) { + if(temp_downtime->is_in_effect == FALSE && temp_downtime->end_time <= current_time) { log_debug_info(DEBUGL_DOWNTIME, 0, "Expiring %s downtime (id=%lu)...\n", (temp_downtime->type == HOST_DOWNTIME) ? "host" : "service", temp_downtime->downtime_id); + /* find the host or service associated with this downtime */ + if(temp_downtime->type == HOST_DOWNTIME) { + if((hst = find_host(temp_downtime->host_name)) == NULL) { + log_debug_info(DEBUGL_DOWNTIME, 1, + "Unable to find host (%s) for downtime\n", + temp_downtime->host_name); + return ERROR; + } + + /* send a notification */ + host_notification(hst, NOTIFICATION_DOWNTIMEEND, + temp_downtime->author, temp_downtime->comment, + NOTIFICATION_OPTION_NONE); + } + else { + if((svc = find_service(temp_downtime->host_name, + temp_downtime->service_description)) == NULL) { + log_debug_info(DEBUGL_DOWNTIME, 1, + "Unable to find service (%s) host (%s) for downtime\n", + temp_downtime->service_description, + temp_downtime->host_name); + return ERROR; + } + + /* send a notification */ + service_notification(svc, NOTIFICATION_DOWNTIMEEND, + temp_downtime->author, temp_downtime->comment, + NOTIFICATION_OPTION_NONE); + } + /* delete the downtime entry */ if(temp_downtime->type == HOST_DOWNTIME) delete_host_downtime(temp_downtime->downtime_id); @@ -760,30 +992,39 @@ int check_for_expired_downtime(void) { /* save a host or service downtime */ -int add_new_downtime(int type, char *host_name, char *service_description, time_t entry_time, char *author, char *comment_data, time_t start_time, time_t end_time, int fixed, unsigned long triggered_by, unsigned long duration, unsigned long *downtime_id, int is_in_effect, int start_notification_sent) { +int add_new_downtime(int type, char *host_name, char *service_description, time_t entry_time, char *author, char *comment_data, time_t start_time, time_t end_time, int fixed, unsigned long triggered_by, unsigned long duration, unsigned long *downtime_id, int is_in_effect, int start_notification_sent){ int result = OK; if(type == HOST_DOWNTIME) - result = add_new_host_downtime(host_name, entry_time, author, comment_data, start_time, end_time, fixed, triggered_by, duration, downtime_id, is_in_effect, start_notification_sent); + return add_new_host_downtime(host_name, entry_time, author, comment_data, start_time, end_time, fixed, triggered_by, duration, downtime_id, is_in_effect, start_notification_sent); else - result = add_new_service_downtime(host_name, service_description, entry_time, author, comment_data, start_time, end_time, fixed, triggered_by, duration, downtime_id, is_in_effect, start_notification_sent); + return add_new_service_downtime(host_name, service_description, entry_time, author, comment_data, start_time, end_time, fixed, triggered_by, duration, downtime_id, is_in_effect, start_notification_sent); return result; } +static unsigned long get_next_downtime_id(void) { + unsigned long new_dt_id; + for (;;) { + new_dt_id = next_downtime_id++; + if (!find_downtime(ANY_DOWNTIME, next_downtime_id)) { + return new_dt_id; + } + } + return 0; + } /* saves a host downtime entry */ -int add_new_host_downtime(char *host_name, time_t entry_time, char *author, char *comment_data, time_t start_time, time_t end_time, int fixed, unsigned long triggered_by, unsigned long duration, unsigned long *downtime_id, int is_in_effect, int start_notification_sent) { +int add_new_host_downtime(char *host_name, time_t entry_time, char *author, char *comment_data, time_t start_time, time_t end_time, int fixed, unsigned long triggered_by, unsigned long duration, unsigned long *downtime_id, int is_in_effect, int start_notification_sent){ int result = OK; unsigned long new_downtime_id = 0L; if(host_name == NULL) return ERROR; - /**** IMPLEMENTATION-SPECIFIC CALLS ****/ -#ifdef USE_XDDDEFAULT - result = xdddefault_add_new_host_downtime(host_name, entry_time, author, comment_data, start_time, end_time, fixed, triggered_by, duration, &new_downtime_id, is_in_effect, start_notification_sent); -#endif + log_debug_info(DEBUGL_FUNCTIONS, 0, "cleanup_downtime_data()\n"); + new_downtime_id = get_next_downtime_id(); + result = add_host_downtime(host_name, entry_time, author, comment_data, start_time, 0, end_time, fixed, triggered_by, duration, new_downtime_id, is_in_effect, start_notification_sent); /* save downtime id */ if(downtime_id != NULL) @@ -799,17 +1040,22 @@ int add_new_host_downtime(char *host_name, time_t entry_time, char *author, char /* saves a service downtime entry */ -int add_new_service_downtime(char *host_name, char *service_description, time_t entry_time, char *author, char *comment_data, time_t start_time, time_t end_time, int fixed, unsigned long triggered_by, unsigned long duration, unsigned long *downtime_id, int is_in_effect, int start_notification_sent) { +int add_new_service_downtime(char *host_name, char *service_description, time_t entry_time, char *author, char *comment_data, time_t start_time, time_t end_time, int fixed, unsigned long triggered_by, unsigned long duration, unsigned long *downtime_id, int is_in_effect, int start_notification_sent){ int result = OK; unsigned long new_downtime_id = 0L; - if(host_name == NULL || service_description == NULL) - return ERROR; + log_debug_info(DEBUGL_FUNCTIONS, 0, "add_new_service_downtime()\n"); - /**** IMPLEMENTATION-SPECIFIC CALLS ****/ -#ifdef USE_XDDDEFAULT - result = xdddefault_add_new_service_downtime(host_name, service_description, entry_time, author, comment_data, start_time, end_time, fixed, triggered_by, duration, &new_downtime_id, is_in_effect, start_notification_sent); -#endif + if(host_name == NULL || service_description == NULL) { + log_debug_info(DEBUGL_DOWNTIME, 1, + "Host name (%s) or service description (%s) is null\n", + ((NULL == host_name) ? "null" : host_name), + ((NULL == service_description) ? "null" : service_description)); + return ERROR; + } + + new_downtime_id = get_next_downtime_id(); + result = add_service_downtime(host_name, service_description, entry_time, author, comment_data, start_time, 0, end_time, fixed, triggered_by, duration, new_downtime_id, is_in_effect, start_notification_sent); /* save downtime id */ if(downtime_id != NULL) @@ -832,107 +1078,60 @@ int add_new_service_downtime(char *host_name, char *service_description, time_t /* deletes a scheduled host or service downtime entry from the list in memory */ int delete_downtime(int type, unsigned long downtime_id) { - int result = OK; scheduled_downtime *this_downtime = NULL; - scheduled_downtime *last_downtime = NULL; - scheduled_downtime *next_downtime = NULL; -#ifdef NSCORE - pthread_mutex_lock(&nagios_downtime_lock); -#endif /* find the downtime we should remove */ - for(this_downtime = scheduled_downtime_list, last_downtime = scheduled_downtime_list; this_downtime != NULL; this_downtime = next_downtime) { - next_downtime = this_downtime->next; + this_downtime = find_downtime(type, downtime_id); + if(!this_downtime) + return ERROR; - /* we found the downtime we should delete */ - if(this_downtime->downtime_id == downtime_id && this_downtime->type == type) - break; + downtime_remove(this_downtime); - last_downtime = this_downtime; - } - - /* remove the downtime from the list in memory */ - if(this_downtime != NULL) { - - /* first remove the comment associated with this downtime */ - if(this_downtime->type == HOST_DOWNTIME) - delete_host_comment(this_downtime->comment_id); - else - delete_service_comment(this_downtime->comment_id); + /* first remove the comment associated with this downtime */ + if(this_downtime->type == HOST_DOWNTIME) + delete_host_comment(this_downtime->comment_id); + else + delete_service_comment(this_downtime->comment_id); #ifdef USE_EVENT_BROKER - /* send data to event broker */ - broker_downtime_data(NEBTYPE_DOWNTIME_DELETE, NEBFLAG_NONE, NEBATTR_NONE, type, this_downtime->host_name, this_downtime->service_description, this_downtime->entry_time, this_downtime->author, this_downtime->comment, this_downtime->start_time, this_downtime->end_time, this_downtime->fixed, this_downtime->triggered_by, this_downtime->duration, downtime_id, NULL); + /* send data to event broker */ + broker_downtime_data(NEBTYPE_DOWNTIME_DELETE, NEBFLAG_NONE, NEBATTR_NONE, type, this_downtime->host_name, this_downtime->service_description, this_downtime->entry_time, this_downtime->author, this_downtime->comment, this_downtime->start_time, this_downtime->end_time, this_downtime->fixed, this_downtime->triggered_by, this_downtime->duration, downtime_id, NULL); #endif - if(scheduled_downtime_list == this_downtime) - scheduled_downtime_list = this_downtime->next; - else - last_downtime->next = next_downtime; - - /* free memory */ - my_free(this_downtime->host_name); - my_free(this_downtime->service_description); - my_free(this_downtime->author); - my_free(this_downtime->comment); - my_free(this_downtime); - - result = OK; - } - else - result = ERROR; - -#ifdef NSCORE - pthread_mutex_unlock(&nagios_downtime_lock); -#endif - - return result; + /* free memory */ + my_free(this_downtime->host_name); + my_free(this_downtime->service_description); + my_free(this_downtime->author); + my_free(this_downtime->comment); + my_free(this_downtime); + return OK; } -/* deletes a scheduled host downtime entry */ int delete_host_downtime(unsigned long downtime_id) { - int result = OK; - - /* delete the downtime from memory */ - delete_downtime(HOST_DOWNTIME, downtime_id); - - /**** IMPLEMENTATION-SPECIFIC CALLS ****/ -#ifdef USE_XDDDEFAULT - result = xdddefault_delete_host_downtime(downtime_id); -#endif - - return result; + return delete_downtime(HOST_DOWNTIME, downtime_id); } -/* deletes a scheduled service downtime entry */ int delete_service_downtime(unsigned long downtime_id) { - int result = OK; - - /* delete the downtime from memory */ - delete_downtime(SERVICE_DOWNTIME, downtime_id); - - /**** IMPLEMENTATION-SPECIFIC CALLS ****/ -#ifdef USE_XDDDEFAULT - result = xdddefault_delete_service_downtime(downtime_id); -#endif - - return result; + return delete_downtime(SERVICE_DOWNTIME, downtime_id); } /* -Deletes all host and service downtimes on a host by hostname, optionally filtered by service description, start time and comment. -All char* must be set or NULL - "" will silently fail to match -Returns number deleted -*/ -int delete_downtime_by_hostname_service_description_start_time_comment(char *hostname, char *service_description, time_t start_time, char *comment) { + * Deletes all host and service downtimes on a host by hostname, + * optionally filtered by service description, start time and comment. + * All char* must be set or NULL - "" will silently fail to match + * Returns number deleted + */ +int delete_downtime_by_hostname_service_description_start_time_comment(char *hostname, char *service_description, time_t start_time, char *cmnt) { scheduled_downtime *temp_downtime; scheduled_downtime *next_downtime; + void *downtime_cpy; int deleted = 0; + objectlist *matches = NULL, *tmp_match = NULL; /* Do not allow deletion of everything - must have at least 1 filter on */ - if(hostname == NULL && service_description == NULL && start_time == 0 && comment == NULL) + if(hostname == NULL && service_description == NULL && start_time == 0 && cmnt == NULL) return deleted; for(temp_downtime = scheduled_downtime_list; temp_downtime != NULL; temp_downtime = next_downtime) { @@ -940,7 +1139,7 @@ int delete_downtime_by_hostname_service_description_start_time_comment(char *hos if(start_time != 0 && temp_downtime->start_time != start_time) { continue; } - if(comment != NULL && strcmp(temp_downtime->comment, comment) != 0) + if(cmnt != NULL && strcmp(temp_downtime->comment, cmnt) != 0) continue; if(temp_downtime->type == HOST_DOWNTIME) { /* If service is specified, then do not delete the host downtime */ @@ -956,9 +1155,20 @@ int delete_downtime_by_hostname_service_description_start_time_comment(char *hos continue; } - unschedule_downtime(temp_downtime->type, temp_downtime->downtime_id); + downtime_cpy = malloc(sizeof(scheduled_downtime)); + memcpy(downtime_cpy, temp_downtime, sizeof(scheduled_downtime)); + prepend_object_to_objectlist(&matches, downtime_cpy); deleted++; } + + for(tmp_match = matches; tmp_match != NULL; tmp_match = tmp_match->next) { + temp_downtime = (scheduled_downtime *)tmp_match->object_ptr; + unschedule_downtime(temp_downtime->type, temp_downtime->downtime_id); + my_free(temp_downtime); + } + + free_objectlist(&matches); + return deleted; } @@ -973,87 +1183,66 @@ int delete_downtime_by_hostname_service_description_start_time_comment(char *hos /******************************************************************/ /* adds a host downtime entry to the list in memory */ -int add_host_downtime(char *host_name, time_t entry_time, char *author, char *comment_data, time_t start_time, time_t flex_downtime_start, time_t end_time, int fixed, unsigned long triggered_by, unsigned long duration, unsigned long downtime_id, int is_in_effect, int start_notification_sent) { - int result = OK; - - result = add_downtime(HOST_DOWNTIME, host_name, NULL, entry_time, author, comment_data, start_time, flex_downtime_start, end_time, fixed, triggered_by, duration, downtime_id, is_in_effect, start_notification_sent); - - return result; +int add_host_downtime(char *host_name, time_t entry_time, char *author, char *comment_data, time_t start_time, time_t flex_downtime_start, time_t end_time, int fixed, unsigned long triggered_by, unsigned long duration, unsigned long downtime_id, int is_in_effect, int start_notification_sent){ + return add_downtime(HOST_DOWNTIME, host_name, NULL, entry_time, author, comment_data, start_time, flex_downtime_start, end_time, fixed, triggered_by, duration, downtime_id, is_in_effect, start_notification_sent); } /* adds a service downtime entry to the list in memory */ -int add_service_downtime(char *host_name, char *svc_description, time_t entry_time, char *author, char *comment_data, time_t start_time, time_t flex_downtime_start, time_t end_time, int fixed, unsigned long triggered_by, unsigned long duration, unsigned long downtime_id, int is_in_effect, int start_notification_sent) { - int result = OK; - - result = add_downtime(SERVICE_DOWNTIME, host_name, svc_description, entry_time, author, comment_data, start_time, flex_downtime_start, end_time, fixed, triggered_by, duration, downtime_id, is_in_effect, start_notification_sent); - - return result; +int add_service_downtime(char *host_name, char *svc_description, time_t entry_time, char *author, char *comment_data, time_t start_time, time_t flex_downtime_start, time_t end_time, int fixed, unsigned long triggered_by, unsigned long duration, unsigned long downtime_id, int is_in_effect, int start_notification_sent){ + return add_downtime(SERVICE_DOWNTIME, host_name, svc_description, entry_time, author, comment_data, start_time, flex_downtime_start, end_time, fixed, triggered_by, duration, downtime_id, is_in_effect, start_notification_sent); } /* adds a host or service downtime entry to the list in memory */ -int add_downtime(int downtime_type, char *host_name, char *svc_description, time_t entry_time, char *author, char *comment_data, time_t start_time, time_t flex_downtime_start, time_t end_time, int fixed, unsigned long triggered_by, unsigned long duration, unsigned long downtime_id, int is_in_effect, int start_notification_sent) { +int add_downtime(int downtime_type, char *host_name, char *svc_description, time_t entry_time, char *author, char *comment_data, time_t start_time, time_t flex_downtime_start, time_t end_time, int fixed, unsigned long triggered_by, unsigned long duration, unsigned long downtime_id, int is_in_effect, int start_notification_sent){ scheduled_downtime *new_downtime = NULL; - scheduled_downtime *last_downtime = NULL; - scheduled_downtime *temp_downtime = NULL; int result = OK; log_debug_info(DEBUGL_FUNCTIONS, 0, "add_downtime()\n"); - /* don't add triggered downtimes that don't have a valid parent */ - if(triggered_by > 0 && find_downtime(ANY_DOWNTIME, triggered_by) == NULL) { - log_debug_info(DEBUGL_DOWNTIME, 1, - "Downtime is triggered, but has no valid parent\n"); - return ERROR; - } - /* we don't have enough info */ if(host_name == NULL || (downtime_type == SERVICE_DOWNTIME && svc_description == NULL)) { log_debug_info(DEBUGL_DOWNTIME, 1, - "Host name (%s) or service description (%s) is null\n", - ((NULL == host_name) ? "null" : host_name), - ((NULL == svc_description) ? "null" : svc_description)); + "Host name (%s) or service description (%s) is null\n", + ((NULL == host_name) ? "null" : host_name), + ((NULL == svc_description) ? "null" : svc_description)); return ERROR; } /* allocate memory for the downtime */ - if((new_downtime = (scheduled_downtime *)calloc(1, sizeof(scheduled_downtime))) == NULL) + if((new_downtime = (scheduled_downtime *)calloc(1, sizeof(scheduled_downtime))) == NULL) { + log_debug_info(DEBUGL_DOWNTIME, 1, + "Unable to allocate memory for new downtime\n"); return ERROR; + } /* duplicate vars */ if((new_downtime->host_name = (char *)strdup(host_name)) == NULL) { log_debug_info(DEBUGL_DOWNTIME, 1, - "Unable to allocate memory for new downtime's host name\n"); + "Unable to allocate memory for new downtime's host name\n"); result = ERROR; } if(downtime_type == SERVICE_DOWNTIME) { if((new_downtime->service_description = (char *)strdup(svc_description)) == NULL) { log_debug_info(DEBUGL_DOWNTIME, 1, - "Unable to allocate memory for new downtime's service description\n"); + "Unable to allocate memory for new downtime's service description\n"); result = ERROR; } } if(author) { if((new_downtime->author = (char *)strdup(author)) == NULL) { log_debug_info(DEBUGL_DOWNTIME, 1, - "Unable to allocate memory for new downtime's author\n"); + "Unable to allocate memory for new downtime's author\n"); result = ERROR; } } if(comment_data) { - if((new_downtime->comment = (char *)strdup(comment_data)) == NULL) + if((new_downtime->comment = (char *)strdup(comment_data)) == NULL) { + log_debug_info(DEBUGL_DOWNTIME, 1, + "Unable to allocate memory for new downtime's comment\n"); result = ERROR; - } - - /* handle errors */ - if(result == ERROR) { - my_free(new_downtime->comment); - my_free(new_downtime->author); - my_free(new_downtime->service_description); - my_free(new_downtime->host_name); - my_free(new_downtime); - return ERROR; + } } new_downtime->type = downtime_type; @@ -1065,47 +1254,34 @@ int add_downtime(int downtime_type, char *host_name, char *svc_description, time new_downtime->triggered_by = triggered_by; new_downtime->duration = duration; new_downtime->downtime_id = downtime_id; - new_downtime->is_in_effect = is_in_effect; - new_downtime->start_notification_sent = start_notification_sent; + new_downtime->is_in_effect=is_in_effect; + new_downtime->start_notification_sent=start_notification_sent; +#ifdef NSCORE + new_downtime->start_event = ( timed_event *)0; + new_downtime->stop_event = ( timed_event *)0; +#endif + result = downtime_add(new_downtime); + if (result) { + if (new_downtime->type == SERVICE_DOWNTIME) { + log_debug_info(DEBUGL_DOWNTIME, 0, "Failed to add downtime for service '%s' on host '%s': %s\n", + new_downtime->service_description, new_downtime->host_name, dt_strerror(result)); + } + else { + log_debug_info(DEBUGL_DOWNTIME, 0, "Failed to add downtime for host '%s': %s\n", new_downtime->host_name, dt_strerror(result)); + } + result = ERROR; + } - if(defer_downtime_sorting) { - new_downtime->next = scheduled_downtime_list; - scheduled_downtime_list = new_downtime; - } - else { - /* - * add new downtime to downtime list, sorted by start time, - * but lock the lists first so broker modules fiddling - * with them at the same time doesn't crash out. - */ -#ifdef NSCORE - pthread_mutex_lock(&nagios_downtime_lock); -#endif - last_downtime = scheduled_downtime_list; - for(temp_downtime = scheduled_downtime_list; temp_downtime != NULL; temp_downtime = temp_downtime->next) { - if(new_downtime->start_time < temp_downtime->start_time) { - new_downtime->next = temp_downtime; - if(temp_downtime == scheduled_downtime_list) - scheduled_downtime_list = new_downtime; - else - last_downtime->next = new_downtime; - break; - } - else - last_downtime = temp_downtime; - } - if(scheduled_downtime_list == NULL) { - new_downtime->next = NULL; - scheduled_downtime_list = new_downtime; - } - else if(temp_downtime == NULL) { - new_downtime->next = NULL; - last_downtime->next = new_downtime; - } -#ifdef NSCORE - pthread_mutex_unlock(&nagios_downtime_lock); -#endif + /* handle errors */ + if(result == ERROR) { + my_free(new_downtime->comment); + my_free(new_downtime->author); + my_free(new_downtime->service_description); + my_free(new_downtime->host_name); + my_free(new_downtime); + return ERROR; } + #ifdef NSCORE #ifdef USE_EVENT_BROKER /* send data to event broker */ @@ -1116,45 +1292,6 @@ int add_downtime(int downtime_type, char *host_name, char *svc_description, time return OK; } -static int downtime_compar(const void *p1, const void *p2) { - scheduled_downtime *d1 = *(scheduled_downtime **)p1; - scheduled_downtime *d2 = *(scheduled_downtime **)p2; - - /* - If the start times of two downtimes are equal and one is triggered but - but the other is not, the triggered downtime should be later in the - list than the untriggered one. This is so they are written to the - retention.dat and status.dat in the correct order. - - Previously the triggered downtime always appeared before its - triggering downtime in those files. When the downtimes were read - from those files, either on a core restart or by the CGIs, the - triggered downtime would be discarded because the triggering - downtime did not yet exist. - - The most common case for this is when a downtime is created and - the option is selected to create triggered downtimes on all child - objects. This change in the sort order does NOT resolve the - case where a manually created, triggered downtime is created with - a start time earlier than the triggering downtime. - - This would need to be resolved by comparing the triggered_by value - with the downtime ID regardless of the start time. However, this - should be a relatively rare case and only caused by intentional - scheduling by a human. This change was not implemented because it - would cause the downtime list to be out of time order and the - implications of this were not well understood. - */ - - if(d1->start_time == d2->start_time) { - if(( d1->triggered_by == 0 && d2->triggered_by != 0) || - ( d1->triggered_by != 0 && d2->triggered_by == 0)) { - return d1->triggered_by == 0 ? -1 : 1; - } - } - return (d1->start_time < d2->start_time) ? -1 : (d1->start_time - d2->start_time); - } - int sort_downtime(void) { scheduled_downtime **array, *temp_downtime; unsigned long i = 0, unsorted_downtimes = 0; @@ -1183,9 +1320,11 @@ int sort_downtime(void) { qsort((void *)array, i, sizeof(*array), downtime_compar); scheduled_downtime_list = temp_downtime = array[0]; + temp_downtime->prev = NULL; for(i = 1; i < unsorted_downtimes; i++) { temp_downtime->next = array[i]; temp_downtime = temp_downtime->next; + temp_downtime->prev = array[i-1]; } temp_downtime->next = NULL; my_free(array); @@ -1200,19 +1339,13 @@ int sort_downtime(void) { /* finds a specific downtime entry */ scheduled_downtime *find_downtime(int type, unsigned long downtime_id) { - scheduled_downtime *temp_downtime = NULL; + scheduled_downtime *dt = NULL; log_debug_info(DEBUGL_FUNCTIONS, 0, "find_downtime()\n"); - for(temp_downtime = scheduled_downtime_list; temp_downtime != NULL; temp_downtime = temp_downtime->next) { - log_debug_info(DEBUGL_DOWNTIME, 2, "find_downtime() looking at type %d, id: %lu\n", type, downtime_id); - - if(type != ANY_DOWNTIME && temp_downtime->type != type) - continue; - if(temp_downtime->downtime_id == downtime_id) - return temp_downtime; - } - + dt = fanout_get(dt_fanout, downtime_id); + if (dt && (type == ANY_DOWNTIME || type == dt->type)) + return dt; return NULL; } @@ -1241,6 +1374,8 @@ void free_downtime_data(void) { scheduled_downtime *this_downtime = NULL; scheduled_downtime *next_downtime = NULL; + fanout_destroy(dt_fanout, NULL); + /* free memory for the scheduled_downtime list */ for(this_downtime = scheduled_downtime_list; this_downtime != NULL; this_downtime = next_downtime) { next_downtime = this_downtime->next; @@ -1256,5 +1391,3 @@ void free_downtime_data(void) { return; } - - diff --git a/common/macros.c b/common/macros.c index 815b2b3..eb26baa 100644 --- a/common/macros.c +++ b/common/macros.c @@ -2,8 +2,6 @@ * * MACROS.C - Common macro functions for Nagios * - * Copyright (c) 1999-2010 Ethan Galstad (egalstad@nagios.org) - * Last Modified: 08-06-2010 * * License: * @@ -22,8 +20,8 @@ * *****************************************************************************/ -#include "../include/macros.h" #include "../include/config.h" +#include "../include/macros.h" #include "../include/common.h" #include "../include/objects.h" #include "../include/statusdata.h" @@ -34,33 +32,17 @@ #include "../include/cgiutils.h" #endif -#ifdef NSCORE -extern int use_large_installation_tweaks; -extern int enable_environment_macros; -#endif - -extern char *illegal_output_chars; - -extern contact *contact_list; -extern contactgroup *contactgroup_list; -extern host *host_list; -extern hostgroup *hostgroup_list; -extern service *service_list; -extern servicegroup *servicegroup_list; -extern command *command_list; -extern timeperiod *timeperiod_list; - -char *macro_x_names[MACRO_X_COUNT]; /* the macro names */ +static char *macro_x_names[MACRO_X_COUNT]; /* the macro names */ char *macro_user[MAX_USER_MACROS]; /* $USERx$ macros */ struct macro_key_code { - char *name; /* macro key name */ + char *name; /* macro key name */ + char *value; /* macro value */ int code; /* numeric macro code, usable in case statements */ - int clean_options; - char *value; - }; + int options; /* Options for how the macro can be escaped */ +}; -struct macro_key_code macro_keys[MACRO_X_COUNT]; +static struct macro_key_code macro_keys[MACRO_X_COUNT]; /* * These point to their corresponding pointer arrays in global_macros @@ -71,7 +53,7 @@ struct macro_key_code macro_keys[MACRO_X_COUNT]; * on their values after having run a certain command will require an * update */ -char **macro_x = NULL; +static char **macro_x = NULL; /* * scoped to this file to prevent (unintentional) mischief, @@ -93,20 +75,20 @@ nagios_macros *get_global_macros(void) { * over all keys. O(log(n)) complexity and a vast improvement over * the previous linear scan */ -const struct macro_key_code *find_macro_key(const char *name) { +static const struct macro_key_code *find_macro_key(const char *name) { unsigned int high, low = 0; int value; struct macro_key_code *key; high = MACRO_X_COUNT; - while(high - low > 0) { + while (high - low > 0) { unsigned int mid = low + ((high - low) / 2); key = ¯o_keys[mid]; value = strcmp(name, key->name); - if(value == 0) { + if (value == 0) { return key; } - if(value > 0) + if (value > 0) low = mid + 1; else high = mid; @@ -125,14 +107,9 @@ int process_macros_r(nagios_macros *mac, char *input_buffer, char **output_buffe char *buf_ptr = NULL; char *delim_ptr = NULL; int in_macro = FALSE; - int x = 0; char *selected_macro = NULL; char *original_macro = NULL; - char *cleaned_macro = NULL; - int clean_macro = FALSE; - int found_macro_x = FALSE; int result = OK; - int clean_options = 0; int free_macro = FALSE; int macro_options = 0; @@ -171,8 +148,6 @@ int process_macros_r(nagios_macros *mac, char *input_buffer, char **output_buffe log_debug_info(DEBUGL_MACROS, 2, " Processing part: '%s'\n", temp_buffer); selected_macro = NULL; - found_macro_x = FALSE; - clean_macro = FALSE; /* we're in plain text... */ if(in_macro == FALSE) { @@ -187,13 +162,10 @@ int process_macros_r(nagios_macros *mac, char *input_buffer, char **output_buffe /* looks like we're in a macro, so process it... */ else { - - /* reset clean options */ - clean_options = 0; - /* grab the macro value */ - result = grab_macro_value_r(mac, temp_buffer, &selected_macro, &clean_options, &free_macro); - log_debug_info(DEBUGL_MACROS, 2, " Processed '%s', Clean Options: %d, Free: %d\n", temp_buffer, clean_options, free_macro); + free_macro = FALSE; + result = grab_macro_value_r(mac, temp_buffer, &selected_macro, ¯o_options, &free_macro); + log_debug_info(DEBUGL_MACROS, 2, " Processed '%s', Free: %d\n", temp_buffer, free_macro); /* an error occurred - we couldn't parse the macro, so continue on */ if(result == ERROR) { @@ -202,10 +174,8 @@ int process_macros_r(nagios_macros *mac, char *input_buffer, char **output_buffe my_free(selected_macro); } - /* we already have a macro... */ - if(result == OK) - x = 0; - + if (result == OK) + ; /* do nothing special if things worked out ok */ /* an escaped $ is done by specifying two $$ next to each other */ else if(!strcmp(temp_buffer, "")) { log_debug_info(DEBUGL_MACROS, 2, " Escaped $. Running output (%lu): '%s'\n", (unsigned long)strlen(*output_buffer), *output_buffer); @@ -226,15 +196,10 @@ int process_macros_r(nagios_macros *mac, char *input_buffer, char **output_buffe /* insert macro */ if(selected_macro != NULL) { - log_debug_info(DEBUGL_MACROS, 2, " Processed '%s', Clean Options: %d, Free: %d\n", temp_buffer, clean_options, free_macro); - - /* include any cleaning options passed back to us */ - macro_options = (options | clean_options); - - log_debug_info(DEBUGL_MACROS, 2, " Cleaning options: global=%d, local=%d, effective=%d\n", options, clean_options, macro_options); + log_debug_info(DEBUGL_MACROS, 2, " Processed '%s', Free: %d, Cleaning options: %d\n", temp_buffer, free_macro, options); /* URL encode the macro if requested - this allocates new memory */ - if(macro_options & URL_ENCODE_MACRO_CHARS) { + if(options & URL_ENCODE_MACRO_CHARS) { original_macro = selected_macro; selected_macro = get_url_encoded_string(selected_macro); if(free_macro == TRUE) { @@ -243,13 +208,16 @@ int process_macros_r(nagios_macros *mac, char *input_buffer, char **output_buffe free_macro = TRUE; } - /* some macros are cleaned... */ - if(clean_macro == TRUE || ((macro_options & STRIP_ILLEGAL_MACRO_CHARS) || (macro_options & ESCAPE_MACRO_CHARS))) { + /* some macros should sometimes be cleaned */ + if(macro_options & options & (STRIP_ILLEGAL_MACRO_CHARS | ESCAPE_MACRO_CHARS)) { + char *cleaned_macro = NULL; /* add the (cleaned) processed macro to the end of the already processed buffer */ - if(selected_macro != NULL && (cleaned_macro = clean_macro_chars(selected_macro, macro_options)) != NULL) { + if(selected_macro != NULL && (cleaned_macro = clean_macro_chars(selected_macro, options)) != NULL) { *output_buffer = (char *)realloc(*output_buffer, strlen(*output_buffer) + strlen(cleaned_macro) + 1); strcat(*output_buffer, cleaned_macro); + if(*cleaned_macro) + my_free(cleaned_macro); log_debug_info(DEBUGL_MACROS, 2, " Cleaned macro. Running output (%lu): '%s'\n", (unsigned long)strlen(*output_buffer), *output_buffer); } @@ -307,11 +275,9 @@ int grab_host_macros_r(nagios_macros *mac, host *hst) { if(hst == NULL) return ERROR; -#ifdef NSCORE /* save pointer to host's first/primary hostgroup */ if(hst->hostgroups_ptr) mac->hostgroup_ptr = (hostgroup *)hst->hostgroups_ptr->object_ptr; -#endif return OK; } @@ -354,11 +320,9 @@ int grab_service_macros_r(nagios_macros *mac, service *svc) { if(svc == NULL) return ERROR; -#ifdef NSCORE /* save first/primary servicegroup pointer for later */ if(svc->servicegroups_ptr) mac->servicegroup_ptr = (servicegroup *)svc->servicegroups_ptr->object_ptr; -#endif return OK; } @@ -400,11 +364,9 @@ int grab_contact_macros_r(nagios_macros *mac, contact *cntct) { if(cntct == NULL) return ERROR; -#ifdef NSCORE /* save pointer to first/primary contactgroup for later */ if(cntct->contactgroups_ptr) mac->contactgroup_ptr = (contactgroup *)cntct->contactgroups_ptr->object_ptr; -#endif return OK; } @@ -413,6 +375,60 @@ int grab_contact_macros(contact *cntct) { return grab_contact_macros_r(&global_macros, cntct); } +int grab_argv_macros_r(nagios_macros *mac, char *check_command) { + char *cmd_ptr = check_command; + char temp_arg[MAX_COMMAND_BUFFER] = ""; + char *arg_buffer = NULL; + int macro_options = STRIP_ILLEGAL_MACRO_CHARS | ESCAPE_MACRO_CHARS; + register int x = 0; + register int y = 0; + register int arg_index = 0; + + /* clear the argv macros */ + clear_argv_macros_r(mac); + + /* make sure we've got all the requirements */ + if(cmd_ptr == NULL || cmd_ptr[0] == '\0') + return ERROR; + + /* skip the command name (we're about to get the arguments)... */ + for(arg_index = 0;; arg_index++) { + if(cmd_ptr[arg_index] == '!' || cmd_ptr[arg_index] == '\x0') + break; + } + + /* get each command argument */ + for(x = 0; x < MAX_COMMAND_ARGUMENTS; x++) { + /* we reached the end of the arguments... */ + if(cmd_ptr[arg_index] == '\x0') + break; + + /* get the next argument */ + /* can't use strtok(), as that's used in process_macros... */ + for(arg_index++, y = 0; y < (int)sizeof(temp_arg) - 1; arg_index++) { + + /* handle escaped argument delimiters */ + if(cmd_ptr[arg_index] == '\\' && cmd_ptr[arg_index+1] == '!') { + arg_index++; + } else if(cmd_ptr[arg_index] == '!' || cmd_ptr[arg_index] == '\x0') { + /* end of argument */ + break; + } + + /* copy the character */ + temp_arg[y] = cmd_ptr[arg_index]; + y++; + } + temp_arg[y] = '\x0'; + + process_macros_r(mac, temp_arg, &arg_buffer, macro_options); + + mac->argv[x] = arg_buffer; + } + + return OK; + + } /******************************************************************/ /******************* MACRO GENERATION FUNCTIONS *******************/ @@ -441,9 +457,11 @@ int grab_macro_value_r(nagios_macros *mac, char *macro_buffer, char **output, in /* clear the old macro value */ my_free(*output); - if(macro_buffer == NULL || clean_options == NULL || free_macro == NULL) + if(macro_buffer == NULL || free_macro == NULL) return ERROR; + if(clean_options) + *clean_options = 0; /* * We handle argv and user macros first, since those are by far @@ -491,9 +509,6 @@ int grab_macro_value_r(nagios_macros *mac, char *macro_buffer, char **output, in if((buf = (char *)strdup(macro_buffer)) == NULL) return ERROR; - /* BY DEFAULT, TELL CALLER TO FREE MACRO BUFFER WHEN DONE */ - *free_macro = TRUE; - /* macro name is at start of buffer */ macro_name = buf; @@ -517,15 +532,17 @@ int grab_macro_value_r(nagios_macros *mac, char *macro_buffer, char **output, in } } - if((mkey = find_macro_key(macro_name))) { + if ((mkey = find_macro_key(macro_name))) { log_debug_info(DEBUGL_MACROS, 2, " macros[%d] (%s) match.\n", mkey->code, macro_x_names[mkey->code]); - if(mkey->clean_options) { - *clean_options |= mkey->clean_options; - log_debug_info(DEBUGL_MACROS, 2, " New clean options: %d\n", *clean_options); - } /* get the macro value */ result = grab_macrox_value_r(mac, mkey->code, arg[0], arg[1], output, free_macro); + + /* Return the macro attributes */ + + if(clean_options) { + *clean_options = mkey->options; + } } /***** CONTACT ADDRESS MACROS *****/ /* NOTE: the code below should be broken out into a separate function */ @@ -562,12 +579,8 @@ int grab_macro_value_r(nagios_macros *mac, char *macro_buffer, char **output, in /* concatenate macro values for all contactgroup members */ for(temp_contactsmember = temp_contactgroup->members; temp_contactsmember != NULL; temp_contactsmember = temp_contactsmember->next) { -#ifdef NSCORE if((temp_contact = temp_contactsmember->contact_ptr) == NULL) continue; - if((temp_contact = find_contact(temp_contactsmember->contact_name)) == NULL) - continue; -#endif /* get the macro value for this contact */ grab_contact_address_macro(x, temp_contact, &temp_buffer); @@ -667,8 +680,7 @@ int grab_macrox_value_r(nagios_macros *mac, int macro_type, char *arg1, char *ar if(output == NULL || free_macro == NULL) return ERROR; - /* BY DEFAULT, TELL CALLER TO FREE MACRO BUFFER WHEN DONE */ - *free_macro = TRUE; + *free_macro = FALSE; /* handle the macro */ switch(macro_type) { @@ -676,6 +688,8 @@ int grab_macrox_value_r(nagios_macros *mac, int macro_type, char *arg1, char *ar /***************/ /* HOST MACROS */ /***************/ + case MACRO_HOSTGROUPNAMES: + *free_macro = TRUE; case MACRO_HOSTNAME: case MACRO_HOSTALIAS: case MACRO_HOSTADDRESS: @@ -709,7 +723,6 @@ int grab_macrox_value_r(nagios_macros *mac, int macro_type, char *arg1, char *ar case MACRO_HOSTNOTIFICATIONID: case MACRO_HOSTEVENTID: case MACRO_LASTHOSTEVENTID: - case MACRO_HOSTGROUPNAMES: case MACRO_HOSTACKAUTHORNAME: case MACRO_HOSTACKAUTHORALIAS: case MACRO_MAXHOSTATTEMPTS: @@ -722,14 +735,21 @@ int grab_macrox_value_r(nagios_macros *mac, int macro_type, char *arg1, char *ar case MACRO_LASTHOSTPROBLEMID: case MACRO_LASTHOSTSTATE: case MACRO_LASTHOSTSTATEID: + case MACRO_HOSTIMPORTANCE: + case MACRO_HOSTANDSERVICESIMPORTANCE: /* a standard host macro */ if(arg2 == NULL) { /* find the host for on-demand macros */ if(arg1) { - if((temp_host = find_host(arg1)) == NULL) + if((temp_host = find_host(arg1)) == NULL) { + if (macro_type == MACRO_HOSTSTATEID) { + *output = strdup("2"); + return OK; + } return ERROR; + } } /* else use saved host pointer */ @@ -751,13 +771,8 @@ int grab_macrox_value_r(nagios_macros *mac, int macro_type, char *arg1, char *ar /* concatenate macro values for all hostgroup members */ for(temp_hostsmember = temp_hostgroup->members; temp_hostsmember != NULL; temp_hostsmember = temp_hostsmember->next) { -#ifdef NSCORE if((temp_host = temp_hostsmember->host_ptr) == NULL) continue; -#else - if((temp_host = find_host(temp_hostsmember->host_name)) == NULL) - continue; -#endif /* get the macro value for this host */ grab_standard_host_macro_r(mac, macro_type, temp_host, &temp_buffer, &free_sub_macro); @@ -783,12 +798,14 @@ int grab_macrox_value_r(nagios_macros *mac, int macro_type, char *arg1, char *ar /********************/ /* HOSTGROUP MACROS */ /********************/ + case MACRO_HOSTGROUPMEMBERS: + case MACRO_HOSTGROUPMEMBERADDRESSES: + *free_macro = TRUE; case MACRO_HOSTGROUPNAME: case MACRO_HOSTGROUPALIAS: case MACRO_HOSTGROUPNOTES: case MACRO_HOSTGROUPNOTESURL: case MACRO_HOSTGROUPACTIONURL: - case MACRO_HOSTGROUPMEMBERS: /* a standard hostgroup macro */ /* use the saved hostgroup pointer */ @@ -810,6 +827,8 @@ int grab_macrox_value_r(nagios_macros *mac, int macro_type, char *arg1, char *ar /******************/ /* SERVICE MACROS */ /******************/ + case MACRO_SERVICEGROUPNAMES: + *free_macro = TRUE; case MACRO_SERVICEDESC: case MACRO_SERVICESTATE: case MACRO_SERVICESTATEID: @@ -842,7 +861,6 @@ int grab_macrox_value_r(nagios_macros *mac, int macro_type, char *arg1, char *ar case MACRO_SERVICENOTIFICATIONID: case MACRO_SERVICEEVENTID: case MACRO_LASTSERVICEEVENTID: - case MACRO_SERVICEGROUPNAMES: case MACRO_SERVICEACKAUTHORNAME: case MACRO_SERVICEACKAUTHORALIAS: case MACRO_MAXSERVICEATTEMPTS: @@ -851,6 +869,7 @@ int grab_macrox_value_r(nagios_macros *mac, int macro_type, char *arg1, char *ar case MACRO_LASTSERVICEPROBLEMID: case MACRO_LASTSERVICESTATE: case MACRO_LASTSERVICESTATEID: + case MACRO_SERVICEIMPORTANCE: /* use saved service pointer */ if(arg1 == NULL && arg2 == NULL) { @@ -887,21 +906,22 @@ int grab_macrox_value_r(nagios_macros *mac, int macro_type, char *arg1, char *ar /* else we have a service macro with a servicegroup name and a delimiter... */ else if(arg1 && arg2) { - if((temp_servicegroup = find_servicegroup(arg1)) == NULL) + if((temp_servicegroup = find_servicegroup(arg1)) == NULL) { + if (macro_type == MACRO_SERVICESTATEID) { + *output = strdup("3"); + return OK; + } return ERROR; + } delimiter_len = strlen(arg2); + *free_macro = TRUE; /* concatenate macro values for all servicegroup members */ for(temp_servicesmember = temp_servicegroup->members; temp_servicesmember != NULL; temp_servicesmember = temp_servicesmember->next) { -#ifdef NSCORE if((temp_service = temp_servicesmember->service_ptr) == NULL) continue; -#else - if((temp_service = find_service(temp_servicesmember->host_name, temp_servicesmember->service_description)) == NULL) - continue; -#endif /* get the macro value for this service */ grab_standard_service_macro_r(mac, macro_type, temp_service, &temp_buffer, &free_sub_macro); @@ -930,12 +950,13 @@ int grab_macrox_value_r(nagios_macros *mac, int macro_type, char *arg1, char *ar /***********************/ /* SERVICEGROUP MACROS */ /***********************/ - case MACRO_SERVICEGROUPNAME: - case MACRO_SERVICEGROUPALIAS: + case MACRO_SERVICEGROUPMEMBERS: case MACRO_SERVICEGROUPNOTES: case MACRO_SERVICEGROUPNOTESURL: case MACRO_SERVICEGROUPACTIONURL: - case MACRO_SERVICEGROUPMEMBERS: + *free_macro = TRUE; + case MACRO_SERVICEGROUPNAME: + case MACRO_SERVICEGROUPALIAS: /* a standard servicegroup macro */ /* use the saved servicegroup pointer */ if(arg1 == NULL) { @@ -956,11 +977,12 @@ int grab_macrox_value_r(nagios_macros *mac, int macro_type, char *arg1, char *ar /******************/ /* CONTACT MACROS */ /******************/ + case MACRO_CONTACTGROUPNAMES: + *free_macro = TRUE; case MACRO_CONTACTNAME: case MACRO_CONTACTALIAS: case MACRO_CONTACTEMAIL: case MACRO_CONTACTPAGER: - case MACRO_CONTACTGROUPNAMES: /* a standard contact macro */ if(arg2 == NULL) { @@ -985,17 +1007,13 @@ int grab_macrox_value_r(nagios_macros *mac, int macro_type, char *arg1, char *ar return ERROR; delimiter_len = strlen(arg2); + *free_macro = TRUE; /* concatenate macro values for all contactgroup members */ for(temp_contactsmember = temp_contactgroup->members; temp_contactsmember != NULL; temp_contactsmember = temp_contactsmember->next) { -#ifdef NSCORE if((temp_contact = temp_contactsmember->contact_ptr) == NULL) continue; -#else - if((temp_contact = find_contact(temp_contactsmember->contact_name)) == NULL) - continue; -#endif /* get the macro value for this contact */ grab_standard_contact_macro_r(mac, macro_type, temp_contact, &temp_buffer); @@ -1020,9 +1038,10 @@ int grab_macrox_value_r(nagios_macros *mac, int macro_type, char *arg1, char *ar /***********************/ /* CONTACTGROUP MACROS */ /***********************/ + case MACRO_CONTACTGROUPMEMBERS: + *free_macro = TRUE; case MACRO_CONTACTGROUPNAME: case MACRO_CONTACTGROUPALIAS: - case MACRO_CONTACTGROUPMEMBERS: /* a standard contactgroup macro */ /* use the saved contactgroup pointer */ if(arg1 == NULL) { @@ -1064,6 +1083,7 @@ int grab_macrox_value_r(nagios_macros *mac, int macro_type, char *arg1, char *ar case MACRO_SHORTDATETIME: case MACRO_DATE: case MACRO_TIME: + *free_macro = TRUE; case MACRO_TIMET: case MACRO_ISVALIDTIME: case MACRO_NEXTVALIDTIME: @@ -1311,13 +1331,8 @@ int grab_custom_macro_value_r(nagios_macros *mac, char *macro_name, char *arg1, /* concatenate macro values for all hostgroup members */ for(temp_hostsmember = temp_hostgroup->members; temp_hostsmember != NULL; temp_hostsmember = temp_hostsmember->next) { -#ifdef NSCORE if((temp_host = temp_hostsmember->host_ptr) == NULL) continue; -#else - if((temp_host = find_host(temp_hostsmember->host_name)) == NULL) - continue; -#endif /* get the macro value for this host */ grab_custom_macro_value_r(mac, macro_name, temp_host->name, NULL, &temp_buffer); @@ -1375,13 +1390,8 @@ int grab_custom_macro_value_r(nagios_macros *mac, char *macro_name, char *arg1, /* concatenate macro values for all servicegroup members */ for(temp_servicesmember = temp_servicegroup->members; temp_servicesmember != NULL; temp_servicesmember = temp_servicesmember->next) { -#ifdef NSCORE if((temp_service = temp_servicesmember->service_ptr) == NULL) continue; -#else - if((temp_service = find_service(temp_servicesmember->host_name, temp_servicesmember->service_description)) == NULL) - continue; -#endif /* get the macro value for this service */ grab_custom_macro_value_r(mac, macro_name, temp_service->host_name, temp_service->description, &temp_buffer); @@ -1435,13 +1445,8 @@ int grab_custom_macro_value_r(nagios_macros *mac, char *macro_name, char *arg1, /* concatenate macro values for all contactgroup members */ for(temp_contactsmember = temp_contactgroup->members; temp_contactsmember != NULL; temp_contactsmember = temp_contactsmember->next) { -#ifdef NSCORE if((temp_contact = temp_contactsmember->contact_ptr) == NULL) continue; -#else - if((temp_contact = find_contact(temp_contactsmember->contact_name)) == NULL) - continue; -#endif /* get the macro value for this contact */ grab_custom_macro_value_r(mac, macro_name, temp_contact->name, NULL, &temp_buffer); @@ -1478,8 +1483,8 @@ int grab_custom_macro_value(char *macro_name, char *arg1, char *arg2, char **out int grab_datetime_macro_r(nagios_macros *mac, int macro_type, char *arg1, char *arg2, char **output) { time_t current_time = 0L; timeperiod *temp_timeperiod = NULL; - time_t test_time = 0L; #ifdef NSCORE + time_t test_time = 0L; time_t next_valid_time = 0L; #endif @@ -1500,10 +1505,12 @@ int grab_datetime_macro_r(nagios_macros *mac, int macro_type, char *arg1, char * return ERROR; /* what timestamp should we use? */ +#ifdef NSCORE if(arg2) test_time = (time_t)strtoul(arg2, NULL, 0); else test_time = current_time; +#endif break; default: @@ -1542,19 +1549,19 @@ int grab_datetime_macro_r(nagios_macros *mac, int macro_type, char *arg1, char * break; case MACRO_TIMET: - asprintf(output, "%lu", (unsigned long)current_time); + *output = (char *)mkstr("%lu", (unsigned long)current_time); break; #ifdef NSCORE case MACRO_ISVALIDTIME: - asprintf(output, "%d", (check_time_against_period(test_time, temp_timeperiod) == OK) ? 1 : 0); + *output = (char *)mkstr("%d", (check_time_against_period(test_time, temp_timeperiod) == OK) ? 1 : 0); break; case MACRO_NEXTVALIDTIME: get_next_valid_time(test_time, &next_valid_time, temp_timeperiod); if(next_valid_time == test_time && check_time_against_period(test_time, temp_timeperiod) == ERROR) next_valid_time = (time_t)0L; - asprintf(output, "%lu", (unsigned long)next_valid_time); + *output = (char *)mkstr("%lu", (unsigned long)next_valid_time); break; #endif @@ -1597,83 +1604,70 @@ int grab_standard_host_macro_r(nagios_macros *mac, int macro_type, host *temp_ho if(temp_host == NULL || output == NULL || free_macro == NULL) return ERROR; - /* BY DEFAULT TELL CALLER TO FREE MACRO BUFFER WHEN DONE */ - *free_macro = TRUE; - /* get the macro */ switch(macro_type) { case MACRO_HOSTNAME: - *output = (char *)strdup(temp_host->name); + *output = temp_host->name; break; case MACRO_HOSTDISPLAYNAME: if(temp_host->display_name) - *output = (char *)strdup(temp_host->display_name); + *output = temp_host->display_name; break; case MACRO_HOSTALIAS: - *output = (char *)strdup(temp_host->alias); + *output = temp_host->alias; break; case MACRO_HOSTADDRESS: - *output = (char *)strdup(temp_host->address); + *output = temp_host->address; break; #ifdef NSCORE case MACRO_HOSTSTATE: - if(temp_host->current_state == HOST_DOWN) - *output = (char *)strdup("DOWN"); - else if(temp_host->current_state == HOST_UNREACHABLE) - *output = (char *)strdup("UNREACHABLE"); - else - *output = (char *)strdup("UP"); + *output = (char *)host_state_name(temp_host->current_state); break; case MACRO_HOSTSTATEID: - asprintf(output, "%d", temp_host->current_state); + *output = (char *)mkstr("%d", temp_host->current_state); break; case MACRO_LASTHOSTSTATE: - if(temp_host->last_state == HOST_DOWN) - *output = (char *)strdup("DOWN"); - else if(temp_host->last_state == HOST_UNREACHABLE) - *output = (char *)strdup("UNREACHABLE"); - else - *output = (char *)strdup("UP"); + *output = (char *)host_state_name(temp_host->last_state); break; case MACRO_LASTHOSTSTATEID: - asprintf(output, "%d", temp_host->last_state); + *output = (char *)mkstr("%d", temp_host->last_state); break; case MACRO_HOSTCHECKTYPE: - asprintf(output, "%s", (temp_host->check_type == HOST_CHECK_PASSIVE) ? "PASSIVE" : "ACTIVE"); + *output = (char *)check_type_name(temp_host->check_type); break; case MACRO_HOSTSTATETYPE: - asprintf(output, "%s", (temp_host->state_type == HARD_STATE) ? "HARD" : "SOFT"); + *output = (char *)state_type_name(temp_host->state_type); break; case MACRO_HOSTOUTPUT: if(temp_host->plugin_output) - *output = (char *)strdup(temp_host->plugin_output); + *output = temp_host->plugin_output; break; case MACRO_LONGHOSTOUTPUT: if(temp_host->long_plugin_output) - *output = (char *)strdup(temp_host->long_plugin_output); + *output = temp_host->long_plugin_output; break; case MACRO_HOSTPERFDATA: if(temp_host->perf_data) - *output = (char *)strdup(temp_host->perf_data); + *output = temp_host->perf_data; break; #endif case MACRO_HOSTCHECKCOMMAND: - if(temp_host->host_check_command) - *output = (char *)strdup(temp_host->host_check_command); + if(temp_host->check_command) + *output = temp_host->check_command; break; #ifdef NSCORE case MACRO_HOSTATTEMPT: - asprintf(output, "%d", temp_host->current_attempt); + *output = (char *)mkstr("%d", temp_host->current_attempt); break; case MACRO_MAXHOSTATTEMPTS: - asprintf(output, "%d", temp_host->max_attempts); + *output = (char *)mkstr("%d", temp_host->max_attempts); break; case MACRO_HOSTDOWNTIME: - asprintf(output, "%d", temp_host->scheduled_downtime_depth); + *output = (char *)mkstr("%d", temp_host->scheduled_downtime_depth); break; case MACRO_HOSTPERCENTCHANGE: - asprintf(output, "%.2f", temp_host->percent_state_change); + *output = (char *)mkstr("%.2f", temp_host->percent_state_change); break; case MACRO_HOSTDURATIONSEC: case MACRO_HOSTDURATION: @@ -1681,7 +1675,7 @@ int grab_standard_host_macro_r(nagios_macros *mac, int macro_type, host *temp_ho duration = (unsigned long)(current_time - temp_host->last_state_change); if(macro_type == MACRO_HOSTDURATIONSEC) - asprintf(output, "%lu", duration); + *output = (char *)mkstr("%lu", duration); else { days = duration / 86400; @@ -1691,60 +1685,60 @@ int grab_standard_host_macro_r(nagios_macros *mac, int macro_type, host *temp_ho minutes = duration / 60; duration -= (minutes * 60); seconds = duration; - asprintf(output, "%dd %dh %dm %ds", days, hours, minutes, seconds); + *output = (char *)mkstr("%dd %dh %dm %ds", days, hours, minutes, seconds); } break; case MACRO_HOSTEXECUTIONTIME: - asprintf(output, "%.3f", temp_host->execution_time); + *output = (char *)mkstr("%.3f", temp_host->execution_time); break; case MACRO_HOSTLATENCY: - asprintf(output, "%.3f", temp_host->latency); + *output = (char *)mkstr("%.3f", temp_host->latency); break; case MACRO_LASTHOSTCHECK: - asprintf(output, "%lu", (unsigned long)temp_host->last_check); + *output = (char *)mkstr("%lu", (unsigned long)temp_host->last_check); break; case MACRO_LASTHOSTSTATECHANGE: - asprintf(output, "%lu", (unsigned long)temp_host->last_state_change); + *output = (char *)mkstr("%lu", (unsigned long)temp_host->last_state_change); break; case MACRO_LASTHOSTUP: - asprintf(output, "%lu", (unsigned long)temp_host->last_time_up); + *output = (char *)mkstr("%lu", (unsigned long)temp_host->last_time_up); break; case MACRO_LASTHOSTDOWN: - asprintf(output, "%lu", (unsigned long)temp_host->last_time_down); + *output = (char *)mkstr("%lu", (unsigned long)temp_host->last_time_down); break; case MACRO_LASTHOSTUNREACHABLE: - asprintf(output, "%lu", (unsigned long)temp_host->last_time_unreachable); + *output = (char *)mkstr("%lu", (unsigned long)temp_host->last_time_unreachable); break; case MACRO_HOSTNOTIFICATIONNUMBER: - asprintf(output, "%d", temp_host->current_notification_number); + *output = (char *)mkstr("%d", temp_host->current_notification_number); break; case MACRO_HOSTNOTIFICATIONID: - asprintf(output, "%lu", temp_host->current_notification_id); + *output = (char *)mkstr("%lu", temp_host->current_notification_id); break; case MACRO_HOSTEVENTID: - asprintf(output, "%lu", temp_host->current_event_id); + *output = (char *)mkstr("%lu", temp_host->current_event_id); break; case MACRO_LASTHOSTEVENTID: - asprintf(output, "%lu", temp_host->last_event_id); + *output = (char *)mkstr("%lu", temp_host->last_event_id); break; case MACRO_HOSTPROBLEMID: - asprintf(output, "%lu", temp_host->current_problem_id); + *output = (char *)mkstr("%lu", temp_host->current_problem_id); break; case MACRO_LASTHOSTPROBLEMID: - asprintf(output, "%lu", temp_host->last_problem_id); + *output = (char *)mkstr("%lu", temp_host->last_problem_id); break; #endif case MACRO_HOSTACTIONURL: if(temp_host->action_url) - *output = (char *)strdup(temp_host->action_url); + *output = temp_host->action_url; break; case MACRO_HOSTNOTESURL: if(temp_host->notes_url) - *output = (char *)strdup(temp_host->notes_url); + *output = temp_host->notes_url; break; case MACRO_HOSTNOTES: if(temp_host->notes) - *output = (char *)strdup(temp_host->notes); + *output = temp_host->notes; break; #ifdef NSCORE case MACRO_HOSTGROUPNAMES: @@ -1797,25 +1791,30 @@ int grab_standard_host_macro_r(nagios_macros *mac, int macro_type, host *temp_ho } /* these macros are time-intensive to compute, and will likely be used together, so save them all for future use */ - my_free(mac->x[MACRO_TOTALHOSTSERVICES]); - asprintf(&mac->x[MACRO_TOTALHOSTSERVICES], "%d", total_host_services); - my_free(mac->x[MACRO_TOTALHOSTSERVICESOK]); - asprintf(&mac->x[MACRO_TOTALHOSTSERVICESOK], "%d", total_host_services_ok); - my_free(mac->x[MACRO_TOTALHOSTSERVICESWARNING]); - asprintf(&mac->x[MACRO_TOTALHOSTSERVICESWARNING], "%d", total_host_services_warning); - my_free(mac->x[MACRO_TOTALHOSTSERVICESUNKNOWN]); - asprintf(&mac->x[MACRO_TOTALHOSTSERVICESUNKNOWN], "%d", total_host_services_unknown); - my_free(mac->x[MACRO_TOTALHOSTSERVICESCRITICAL]); - asprintf(&mac->x[MACRO_TOTALHOSTSERVICESCRITICAL], "%d", total_host_services_critical); + mac->x[MACRO_TOTALHOSTSERVICES] = + (char *)mkstr("%d", total_host_services); + mac->x[MACRO_TOTALHOSTSERVICESOK] = + (char *)mkstr("%d", total_host_services_ok); + mac->x[MACRO_TOTALHOSTSERVICESWARNING] = + (char *)mkstr("%d", total_host_services_warning); + mac->x[MACRO_TOTALHOSTSERVICESUNKNOWN] = + (char *)mkstr("%d", total_host_services_unknown); + mac->x[MACRO_TOTALHOSTSERVICESCRITICAL] = + (char *)mkstr("%d", total_host_services_critical); } /* return only the macro the user requested */ *output = mac->x[macro_type]; - - /* tell caller to NOT free memory when done */ - *free_macro = FALSE; + break; + case MACRO_HOSTIMPORTANCE: + *output = (char *)mkstr("%u", temp_host->hourly_value); + break; + case MACRO_HOSTANDSERVICESIMPORTANCE: + *output = (char *)mkstr("%u", temp_host->hourly_value + + host_services_value(temp_host)); break; #endif + /***************/ /* MISC MACROS */ /***************/ @@ -1826,7 +1825,6 @@ int grab_standard_host_macro_r(nagios_macros *mac, int macro_type, host *temp_ho /* no need to do any more work - these are already precomputed elsewhere */ /* NOTE: these macros won't work as on-demand macros */ *output = mac->x[macro_type]; - *free_macro = FALSE; break; default: @@ -1840,13 +1838,13 @@ int grab_standard_host_macro_r(nagios_macros *mac, int macro_type, host *temp_ho switch(macro_type) { case MACRO_HOSTACTIONURL: case MACRO_HOSTNOTESURL: + *free_macro = TRUE; process_macros_r(mac, *output, &temp_buffer, URL_ENCODE_MACRO_CHARS); - my_free(*output); *output = temp_buffer; break; case MACRO_HOSTNOTES: + *free_macro = TRUE; process_macros_r(mac, *output, &temp_buffer, 0); - my_free(*output); *output = temp_buffer; break; default: @@ -1866,7 +1864,6 @@ int grab_standard_hostgroup_macro_r(nagios_macros *mac, int macro_type, hostgrou hostsmember *temp_hostsmember = NULL; char *temp_buffer = NULL; unsigned int temp_len = 0; - unsigned int init_len = 0; if(temp_hostgroup == NULL || output == NULL) return ERROR; @@ -1874,57 +1871,69 @@ int grab_standard_hostgroup_macro_r(nagios_macros *mac, int macro_type, hostgrou /* get the macro value */ switch(macro_type) { case MACRO_HOSTGROUPNAME: - *output = (char *)strdup(temp_hostgroup->group_name); + *output = temp_hostgroup->group_name; break; case MACRO_HOSTGROUPALIAS: if(temp_hostgroup->alias) - *output = (char *)strdup(temp_hostgroup->alias); + *output = temp_hostgroup->alias; break; case MACRO_HOSTGROUPMEMBERS: + case MACRO_HOSTGROUPMEMBERADDRESSES: /* make the calculations for total string length */ for(temp_hostsmember = temp_hostgroup->members; temp_hostsmember != NULL; temp_hostsmember = temp_hostsmember->next) { - if(temp_hostsmember->host_name == NULL) - continue; - if(temp_len == 0) { - temp_len += strlen(temp_hostsmember->host_name) + 1; + if(macro_type == MACRO_HOSTGROUPMEMBERS) { + if(temp_hostsmember->host_name != NULL) + temp_len += strlen(temp_hostsmember->host_name) + 2; } else { - temp_len += strlen(temp_hostsmember->host_name) + 2; + if(temp_hostsmember->host_ptr->address != NULL) + temp_len += strlen(temp_hostsmember->host_ptr->address) + 2; } } + if(!temp_len) { + /* empty group, so return the nul string */ + *output = calloc(1, 1); + return OK; + } + /* allocate or reallocate the memory buffer */ if(*output == NULL) { *output = (char *)malloc(temp_len); + **output = '\0'; } else { - init_len = strlen(*output); - temp_len += init_len; + temp_len += strlen(*output); *output = (char *)realloc(*output, temp_len); } - /* now fill in the string with the member names */ + /* now fill in the string with the member names or addresses */ for(temp_hostsmember = temp_hostgroup->members; temp_hostsmember != NULL; temp_hostsmember = temp_hostsmember->next) { - if(temp_hostsmember->host_name == NULL) - continue; - temp_buffer = *output + init_len; - if(init_len == 0) { /* If our buffer didn't contain anything, we just need to write "%s,%s" */ - init_len += sprintf(temp_buffer, "%s", temp_hostsmember->host_name); + if(macro_type == MACRO_HOSTGROUPMEMBERS) { + if(temp_hostsmember->host_name == NULL) + continue; } else { - init_len += sprintf(temp_buffer, ",%s", temp_hostsmember->host_name); + if(temp_hostsmember->host_ptr->address == NULL) + continue; } + if(**output != '\0') + strcat(*output, ","); + if(macro_type == MACRO_HOSTGROUPMEMBERS) + strcat(*output, temp_hostsmember->host_name); + else + strcat(*output, temp_hostsmember->host_ptr->address); } break; case MACRO_HOSTGROUPACTIONURL: if(temp_hostgroup->action_url) - *output = (char *)strdup(temp_hostgroup->action_url); + *output = temp_hostgroup->action_url; break; case MACRO_HOSTGROUPNOTESURL: if(temp_hostgroup->notes_url) - *output = (char *)strdup(temp_hostgroup->notes_url); + *output = temp_hostgroup->notes_url; break; case MACRO_HOSTGROUPNOTES: if(temp_hostgroup->notes) - *output = (char *)strdup(temp_hostgroup->notes); + *output = temp_hostgroup->notes; break; default: log_debug_info(DEBUGL_MACROS, 0, "UNHANDLED HOSTGROUP MACRO #%d! THIS IS A BUG!\n", macro_type); @@ -1938,12 +1947,10 @@ int grab_standard_hostgroup_macro_r(nagios_macros *mac, int macro_type, hostgrou case MACRO_HOSTGROUPACTIONURL: case MACRO_HOSTGROUPNOTESURL: process_macros_r(mac, *output, &temp_buffer, URL_ENCODE_MACRO_CHARS); - my_free(*output); *output = temp_buffer; break; case MACRO_HOSTGROUPNOTES: process_macros_r(mac, *output, &temp_buffer, 0); - my_free(*output); *output = temp_buffer; break; default: @@ -1977,109 +1984,92 @@ int grab_standard_service_macro_r(nagios_macros *mac, int macro_type, service *t if(temp_service == NULL || output == NULL) return ERROR; - /* BY DEFAULT TELL CALLER TO FREE MACRO BUFFER WHEN DONE */ - *free_macro = TRUE; - /* get the macro value */ switch(macro_type) { case MACRO_SERVICEDESC: - *output = (char *)strdup(temp_service->description); + *output = temp_service->description; break; case MACRO_SERVICEDISPLAYNAME: if(temp_service->display_name) - *output = (char *)strdup(temp_service->display_name); + *output = temp_service->display_name; break; #ifdef NSCORE case MACRO_SERVICEOUTPUT: if(temp_service->plugin_output) - *output = (char *)strdup(temp_service->plugin_output); + *output = temp_service->plugin_output; break; case MACRO_LONGSERVICEOUTPUT: if(temp_service->long_plugin_output) - *output = (char *)strdup(temp_service->long_plugin_output); + *output = temp_service->long_plugin_output; break; case MACRO_SERVICEPERFDATA: if(temp_service->perf_data) - *output = (char *)strdup(temp_service->perf_data); + *output = temp_service->perf_data; break; #endif case MACRO_SERVICECHECKCOMMAND: - if(temp_service->service_check_command) - *output = (char *)strdup(temp_service->service_check_command); + if(temp_service->check_command) + *output = temp_service->check_command; break; #ifdef NSCORE case MACRO_SERVICECHECKTYPE: - *output = (char *)strdup((temp_service->check_type == SERVICE_CHECK_PASSIVE) ? "PASSIVE" : "ACTIVE"); + *output = (char *)check_type_name(temp_service->check_type); break; case MACRO_SERVICESTATETYPE: - *output = (char *)strdup((temp_service->state_type == HARD_STATE) ? "HARD" : "SOFT"); + *output = (char *)state_type_name(temp_service->state_type); break; case MACRO_SERVICESTATE: - if(temp_service->current_state == STATE_OK) - *output = (char *)strdup("OK"); - else if(temp_service->current_state == STATE_WARNING) - *output = (char *)strdup("WARNING"); - else if(temp_service->current_state == STATE_CRITICAL) - *output = (char *)strdup("CRITICAL"); - else - *output = (char *)strdup("UNKNOWN"); + *output = (char *)service_state_name(temp_service->current_state); break; case MACRO_SERVICESTATEID: - asprintf(output, "%d", temp_service->current_state); + *output = (char *)mkstr("%d", temp_service->current_state); break; case MACRO_LASTSERVICESTATE: - if(temp_service->last_state == STATE_OK) - *output = (char *)strdup("OK"); - else if(temp_service->last_state == STATE_WARNING) - *output = (char *)strdup("WARNING"); - else if(temp_service->last_state == STATE_CRITICAL) - *output = (char *)strdup("CRITICAL"); - else - *output = (char *)strdup("UNKNOWN"); + *output = (char *)service_state_name(temp_service->last_state); break; case MACRO_LASTSERVICESTATEID: - asprintf(output, "%d", temp_service->last_state); + *output = (char *)mkstr("%d", temp_service->last_state); break; #endif case MACRO_SERVICEISVOLATILE: - asprintf(output, "%d", temp_service->is_volatile); + *output = (char *)mkstr("%d", temp_service->is_volatile); break; #ifdef NSCORE case MACRO_SERVICEATTEMPT: - asprintf(output, "%d", temp_service->current_attempt); + *output = (char *)mkstr("%d", temp_service->current_attempt); break; case MACRO_MAXSERVICEATTEMPTS: - asprintf(output, "%d", temp_service->max_attempts); + *output = (char *)mkstr("%d", temp_service->max_attempts); break; case MACRO_SERVICEEXECUTIONTIME: - asprintf(output, "%.3f", temp_service->execution_time); + *output = (char *)mkstr("%.3f", temp_service->execution_time); break; case MACRO_SERVICELATENCY: - asprintf(output, "%.3f", temp_service->latency); + *output = (char *)mkstr("%.3f", temp_service->latency); break; case MACRO_LASTSERVICECHECK: - asprintf(output, "%lu", (unsigned long)temp_service->last_check); + *output = (char *)mkstr("%lu", (unsigned long)temp_service->last_check); break; case MACRO_LASTSERVICESTATECHANGE: - asprintf(output, "%lu", (unsigned long)temp_service->last_state_change); + *output = (char *)mkstr("%lu", (unsigned long)temp_service->last_state_change); break; case MACRO_LASTSERVICEOK: - asprintf(output, "%lu", (unsigned long)temp_service->last_time_ok); + *output = (char *)mkstr("%lu", (unsigned long)temp_service->last_time_ok); break; case MACRO_LASTSERVICEWARNING: - asprintf(output, "%lu", (unsigned long)temp_service->last_time_warning); + *output = (char *)mkstr("%lu", (unsigned long)temp_service->last_time_warning); break; case MACRO_LASTSERVICEUNKNOWN: - asprintf(output, "%lu", (unsigned long)temp_service->last_time_unknown); + *output = (char *)mkstr("%lu", (unsigned long)temp_service->last_time_unknown); break; case MACRO_LASTSERVICECRITICAL: - asprintf(output, "%lu", (unsigned long)temp_service->last_time_critical); + *output = (char *)mkstr("%lu", (unsigned long)temp_service->last_time_critical); break; case MACRO_SERVICEDOWNTIME: - asprintf(output, "%d", temp_service->scheduled_downtime_depth); + *output = (char *)mkstr("%d", temp_service->scheduled_downtime_depth); break; case MACRO_SERVICEPERCENTCHANGE: - asprintf(output, "%.2f", temp_service->percent_state_change); + *output = (char *)mkstr("%.2f", temp_service->percent_state_change); break; case MACRO_SERVICEDURATIONSEC: case MACRO_SERVICEDURATION: @@ -2089,7 +2079,7 @@ int grab_standard_service_macro_r(nagios_macros *mac, int macro_type, service *t /* get the state duration in seconds */ if(macro_type == MACRO_SERVICEDURATIONSEC) - asprintf(output, "%lu", duration); + *output = (char *)mkstr("%lu", duration); /* get the state duration */ else { @@ -2100,40 +2090,41 @@ int grab_standard_service_macro_r(nagios_macros *mac, int macro_type, service *t minutes = duration / 60; duration -= (minutes * 60); seconds = duration; - asprintf(output, "%dd %dh %dm %ds", days, hours, minutes, seconds); + *output = (char *)mkstr("%dd %dh %dm %ds", days, hours, minutes, seconds); } break; case MACRO_SERVICENOTIFICATIONNUMBER: - asprintf(output, "%d", temp_service->current_notification_number); + *output = (char *)mkstr("%d", temp_service->current_notification_number); break; case MACRO_SERVICENOTIFICATIONID: - asprintf(output, "%lu", temp_service->current_notification_id); + *output = (char *)mkstr("%lu", temp_service->current_notification_id); break; case MACRO_SERVICEEVENTID: - asprintf(output, "%lu", temp_service->current_event_id); + *output = (char *)mkstr("%lu", temp_service->current_event_id); break; case MACRO_LASTSERVICEEVENTID: - asprintf(output, "%lu", temp_service->last_event_id); + *output = (char *)mkstr("%lu", temp_service->last_event_id); break; case MACRO_SERVICEPROBLEMID: - asprintf(output, "%lu", temp_service->current_problem_id); + *output = (char *)mkstr("%lu", temp_service->current_problem_id); break; case MACRO_LASTSERVICEPROBLEMID: - asprintf(output, "%lu", temp_service->last_problem_id); + *output = (char *)mkstr("%lu", temp_service->last_problem_id); break; #endif case MACRO_SERVICEACTIONURL: if(temp_service->action_url) - *output = (char *)strdup(temp_service->action_url); + *output = temp_service->action_url; break; case MACRO_SERVICENOTESURL: if(temp_service->notes_url) - *output = (char *)strdup(temp_service->notes_url); + *output = temp_service->notes_url; break; case MACRO_SERVICENOTES: if(temp_service->notes) - *output = (char *)strdup(temp_service->notes); + *output = temp_service->notes; break; + #ifdef NSCORE case MACRO_SERVICEGROUPNAMES: /* find all servicegroups this service is associated with */ @@ -2151,7 +2142,11 @@ int grab_standard_service_macro_r(nagios_macros *mac, int macro_type, service *t my_free(buf2); } break; + case MACRO_SERVICEIMPORTANCE: + *output = (char *)mkstr("%u", temp_service->hourly_value); + break; #endif + /***************/ /* MISC MACROS */ /***************/ @@ -2177,12 +2172,10 @@ int grab_standard_service_macro_r(nagios_macros *mac, int macro_type, service *t case MACRO_SERVICEACTIONURL: case MACRO_SERVICENOTESURL: process_macros_r(mac, *output, &temp_buffer, URL_ENCODE_MACRO_CHARS); - my_free(*output); *output = temp_buffer; break; case MACRO_SERVICENOTES: process_macros_r(mac, *output, &temp_buffer, 0); - my_free(*output); *output = temp_buffer; break; default: @@ -2210,11 +2203,11 @@ int grab_standard_servicegroup_macro_r(nagios_macros *mac, int macro_type, servi /* get the macro value */ switch(macro_type) { case MACRO_SERVICEGROUPNAME: - *output = (char *)strdup(temp_servicegroup->group_name); + *output = temp_servicegroup->group_name; break; case MACRO_SERVICEGROUPALIAS: if(temp_servicegroup->alias) - *output = (char *)strdup(temp_servicegroup->alias); + *output = temp_servicegroup->alias; break; case MACRO_SERVICEGROUPMEMBERS: /* make the calculations for total string length */ @@ -2228,6 +2221,11 @@ int grab_standard_servicegroup_macro_r(nagios_macros *mac, int macro_type, servi temp_len += strlen(temp_servicesmember->host_name) + strlen(temp_servicesmember->service_description) + 3; } } + if(!temp_len) { + /* empty group, so return the nul string */ + *output = calloc(1, 1); + return OK; + } /* allocate or reallocate the memory buffer */ if(*output == NULL) { *output = (char *)malloc(temp_len); @@ -2252,15 +2250,15 @@ int grab_standard_servicegroup_macro_r(nagios_macros *mac, int macro_type, servi break; case MACRO_SERVICEGROUPACTIONURL: if(temp_servicegroup->action_url) - *output = (char *)strdup(temp_servicegroup->action_url); + *output = temp_servicegroup->action_url; break; case MACRO_SERVICEGROUPNOTESURL: if(temp_servicegroup->notes_url) - *output = (char *)strdup(temp_servicegroup->notes_url); + *output = temp_servicegroup->notes_url; break; case MACRO_SERVICEGROUPNOTES: if(temp_servicegroup->notes) - *output = (char *)strdup(temp_servicegroup->notes); + *output = temp_servicegroup->notes; break; default: log_debug_info(DEBUGL_MACROS, 0, "UNHANDLED SERVICEGROUP MACRO #%d! THIS IS A BUG!\n", macro_type); @@ -2273,12 +2271,10 @@ int grab_standard_servicegroup_macro_r(nagios_macros *mac, int macro_type, servi case MACRO_SERVICEGROUPACTIONURL: case MACRO_SERVICEGROUPNOTESURL: process_macros_r(mac, *output, &temp_buffer, URL_ENCODE_MACRO_CHARS); - my_free(*output); *output = temp_buffer; break; case MACRO_SERVICEGROUPNOTES: process_macros_r(mac, *output, &temp_buffer, 0); - my_free(*output); *output = temp_buffer; break; default: @@ -2308,18 +2304,18 @@ int grab_standard_contact_macro_r(nagios_macros *mac, int macro_type, contact *t /* get the macro value */ switch(macro_type) { case MACRO_CONTACTNAME: - *output = (char *)strdup(temp_contact->name); + *output = temp_contact->name; break; case MACRO_CONTACTALIAS: - *output = (char *)strdup(temp_contact->alias); + *output = temp_contact->alias; break; case MACRO_CONTACTEMAIL: if(temp_contact->email) - *output = (char *)strdup(temp_contact->email); + *output = temp_contact->email; break; case MACRO_CONTACTPAGER: if(temp_contact->pager) - *output = (char *)strdup(temp_contact->pager); + *output = temp_contact->pager; break; #ifdef NSCORE case MACRO_CONTACTGROUPNAMES: @@ -2380,11 +2376,11 @@ int grab_standard_contactgroup_macro(int macro_type, contactgroup *temp_contactg /* get the macro value */ switch(macro_type) { case MACRO_CONTACTGROUPNAME: - *output = (char *)strdup(temp_contactgroup->group_name); + *output = temp_contactgroup->group_name; break; case MACRO_CONTACTGROUPALIAS: if(temp_contactgroup->alias) - *output = (char *)strdup(temp_contactgroup->alias); + *output = temp_contactgroup->alias; break; case MACRO_CONTACTGROUPMEMBERS: /* get the member list */ @@ -2424,7 +2420,7 @@ int grab_custom_object_macro_r(nagios_macros *mac, char *macro_name, customvaria if(!strcmp(macro_name, temp_customvariablesmember->variable_name)) { if(temp_customvariablesmember->variable_value) - *output = (char *)strdup(temp_customvariablesmember->variable_value); + *output = temp_customvariablesmember->variable_value; result = OK; break; } @@ -2446,64 +2442,65 @@ int grab_custom_object_macro(char *macro_name, customvariablesmember *vars, char char *clean_macro_chars(char *macro, int options) { register int x = 0; register int y = 0; - register int z = 0; register int ch = 0; register int len = 0; - register int illegal_char = 0; + char *ret = NULL; - if(macro == NULL) + if(macro == NULL || !*macro) return ""; len = (int)strlen(macro); + ret = strdup(macro); /* strip illegal characters out of macro */ if(options & STRIP_ILLEGAL_MACRO_CHARS) { - for(y = 0, x = 0; x < len; x++) { - - /*ch=(int)macro[x];*/ - /* allow non-ASCII characters (Japanese, etc) */ ch = macro[x] & 0xff; - /* illegal ASCII characters */ - if(ch < 32 || ch == 127) - continue; - - /* illegal user-specified characters */ - illegal_char = FALSE; - if(illegal_output_chars != NULL) { - for(z = 0; illegal_output_chars[z] != '\x0'; z++) { - if(ch == (int)illegal_output_chars[z]) { - illegal_char = TRUE; - break; - } - } - } - - if(illegal_char == FALSE) - macro[y++] = macro[x]; + /* illegal chars are skipped */ + if(!illegal_output_char_map[ch]) + ret[y++] = ret[x]; } - macro[y++] = '\x0'; + ret[y++] = '\x0'; } -#ifdef ON_HOLD_FOR_NOW - /* escape nasty character in macro */ - if(options & ESCAPE_MACRO_CHARS) { - } -#endif - - return macro; + return ret; } /* encodes a string in proper URL format */ char *get_url_encoded_string(char *input) { + /* From RFC 3986: + segment = *pchar + + [...] + + pchar = unreserved / pct-encoded / sub-delims / ":" / "@" + + query = *( pchar / "/" / "?" ) + + fragment = *( pchar / "/" / "?" ) + + pct-encoded = "%" HEXDIG HEXDIG + + unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" + reserved = gen-delims / sub-delims + gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@" + sub-delims = "!" / "$" / "&" / "'" / "(" / ")" + / "*" / "+" / "," / ";" / "=" + + Encode everything but "unreserved", to be on safe side. + + Another note: + nowhere in the RFC states that + is interpreted as space. Therefore, encode + space as %20 (as all other characters that should be escaped) + */ + register int x = 0; register int y = 0; char *encoded_url_string = NULL; - char temp_expansion[6] = ""; /* bail if no input */ @@ -2515,25 +2512,23 @@ char *get_url_encoded_string(char *input) { return NULL; /* check/encode all characters */ - for(x = 0, y = 0; input[x] != (char)'\x0'; x++) { + for(x = 0, y = 0; input[x]; x++) { /* alpha-numeric characters and a few other characters don't get encoded */ - if(((char)input[x] >= '0' && (char)input[x] <= '9') || ((char)input[x] >= 'A' && (char)input[x] <= 'Z') || ((char)input[x] >= (char)'a' && (char)input[x] <= (char)'z') || (char)input[x] == (char)'.' || (char)input[x] == (char)'-' || (char)input[x] == (char)'_' || (char)input[x] == (char)':' || (char)input[x] == (char)'/' || (char)input[x] == (char)'?' || (char)input[x] == (char)'=' || (char)input[x] == (char)'&') { - encoded_url_string[y] = input[x]; - y++; - } - - /* spaces are pluses */ - else if((char)input[x] <= (char)' ') { - encoded_url_string[y] = '+'; - y++; - } + if(((char)input[x] >= '0' && (char)input[x] <= '9') || + ((char)input[x] >= 'A' && (char)input[x] <= 'Z') || + ((char)input[x] >= 'a' && (char)input[x] <= 'z') || + (char)input[x] == '.' || + (char)input[x] == '-' || + (char)input[x] == '_' || + (char)input[x] == '~') + { + encoded_url_string[y++] = input[x]; + } /* anything else gets represented by its hex value */ else { - encoded_url_string[y] = '\x0'; - sprintf(temp_expansion, "%%%02X", (unsigned int)(input[x] & 0xFF)); - strcat(encoded_url_string, temp_expansion); + sprintf(&encoded_url_string[y], "%%%02X", (unsigned int)(input[x] & 0xFF)); y += 3; } } @@ -2545,12 +2540,13 @@ char *get_url_encoded_string(char *input) { } -static int macro_key_cmp(const void *a_, const void *b_) { +static int macro_key_cmp(const void *a_, const void *b_) +{ struct macro_key_code *a = (struct macro_key_code *)a_; struct macro_key_code *b = (struct macro_key_code *)b_; return strcmp(a->name, b->name); - } +} /******************************************************************/ @@ -2559,8 +2555,12 @@ static int macro_key_cmp(const void *a_, const void *b_) { /* initializes global macros */ int init_macros(void) { - init_macrox_names(); int x; + init_macrox_names(); + + for(x = 0; x < 32; x++) + illegal_output_char_map[x] = 1; + illegal_output_char_map[127] = 1; /* * non-volatile macros are free()'d when they're set. @@ -2582,20 +2582,27 @@ int init_macros(void) { * keys are so long and a binary lookup is completed in * 7 steps for up to ~200 keys, worst case. */ - for(x = 0; x < MACRO_X_COUNT; x++) { + for (x = 0; x < MACRO_X_COUNT; x++) { macro_keys[x].code = x; macro_keys[x].name = macro_x_names[x]; - macro_keys[x].clean_options = 0; - /* host/service output/perfdata and author/comment macros should get cleaned */ - if((x >= 16 && x <= 19) || (x >= 49 && x <= 52) || (x >= 99 && x <= 100) || (x >= 124 && x <= 127)) { - macro_keys[x].clean_options = (STRIP_ILLEGAL_MACRO_CHARS | ESCAPE_MACRO_CHARS); - } - /* url macros should get cleaned */ - if((x >= 125 && x <= 126) || (x >= 128 && x <= 129) || (x >= 77 && x <= 78) || (x >= 74 && x <= 75)) { - macro_keys[x].clean_options = URL_ENCODE_MACRO_CHARS; - } + /* This tells which escaping is possible to do on the macro */ + macro_keys[x].options = URL_ENCODE_MACRO_CHARS; + switch(x) { + case MACRO_HOSTOUTPUT: + case MACRO_LONGHOSTOUTPUT: + case MACRO_HOSTPERFDATA: + case MACRO_HOSTACKAUTHOR: + case MACRO_HOSTACKCOMMENT: + case MACRO_SERVICEOUTPUT: + case MACRO_LONGSERVICEOUTPUT: + case MACRO_SERVICEPERFDATA: + case MACRO_SERVICEACKAUTHOR: + case MACRO_SERVICEACKCOMMENT: + macro_keys[x].options |= STRIP_ILLEGAL_MACRO_CHARS | ESCAPE_MACRO_CHARS; + break; } + } qsort(macro_keys, x, sizeof(struct macro_key_code), macro_key_cmp); return OK; @@ -2767,6 +2774,10 @@ int init_macrox_names(void) { add_macrox_name(LASTHOSTSTATEID); add_macrox_name(LASTSERVICESTATE); add_macrox_name(LASTSERVICESTATEID); + add_macrox_name(HOSTIMPORTANCE); + add_macrox_name(SERVICEIMPORTANCE); + add_macrox_name(HOSTANDSERVICESIMPORTANCE); + add_macrox_name(HOSTGROUPMEMBERADDRESSES); return OK; } @@ -2829,83 +2840,46 @@ void copy_constant_macros(char **dest) { } #undef cp_macro -/* clear all macros that are not "constant" (i.e. they change throughout the course of monitoring) */ -int clear_volatile_macros_r(nagios_macros *mac) { +static void clear_custom_vars(customvariablesmember **vars) { customvariablesmember *this_customvariablesmember = NULL; customvariablesmember *next_customvariablesmember = NULL; + + for(this_customvariablesmember = *vars; + this_customvariablesmember != NULL; + this_customvariablesmember = next_customvariablesmember) { + next_customvariablesmember = this_customvariablesmember->next; + my_free(this_customvariablesmember->variable_name); + my_free(this_customvariablesmember->variable_value); + my_free(this_customvariablesmember); + } + *vars = NULL; + } + +/* clear all macros that are not "constant" (i.e. they change throughout the course of monitoring) */ +int clear_volatile_macros_r(nagios_macros *mac) { register int x = 0; - for(x = 0; x < MACRO_X_COUNT; x++) { - switch(x) { + log_debug_info(DEBUGL_FUNCTIONS, 0, "clear_volatile_macros_r()\n"); - case MACRO_ADMINEMAIL: - case MACRO_ADMINPAGER: - case MACRO_MAINCONFIGFILE: - case MACRO_STATUSDATAFILE: - case MACRO_RETENTIONDATAFILE: - case MACRO_OBJECTCACHEFILE: - case MACRO_TEMPFILE: - case MACRO_LOGFILE: - case MACRO_RESOURCEFILE: - case MACRO_COMMANDFILE: - case MACRO_HOSTPERFDATAFILE: - case MACRO_SERVICEPERFDATAFILE: - case MACRO_PROCESSSTARTTIME: - case MACRO_TEMPPATH: - case MACRO_EVENTSTARTTIME: - /* these don't change during the course of monitoring, so no need to free them */ - break; - default: - my_free(mac->x[x]); - break; - } - } + clear_host_macros_r(mac); + clear_service_macros_r(mac); + clear_summary_macros_r(mac); + clear_hostgroup_macros_r(mac); + clear_servicegroup_macros_r(mac); + clear_contactgroup_macros_r(mac); + clear_contact_macros_r(mac); + clear_datetime_macros_r(mac); /* contact address macros */ for(x = 0; x < MAX_CONTACT_ADDRESSES; x++) my_free(mac->contactaddress[x]); - /* clear macro pointers */ - mac->host_ptr = NULL; - mac->hostgroup_ptr = NULL; - mac->service_ptr = NULL; - mac->servicegroup_ptr = NULL; - mac->contact_ptr = NULL; - mac->contactgroup_ptr = NULL; - /* clear on-demand macro */ my_free(mac->ondemand); /* clear ARGx macros */ clear_argv_macros_r(mac); - /* clear custom host variables */ - for(this_customvariablesmember = mac->custom_host_vars; this_customvariablesmember != NULL; this_customvariablesmember = next_customvariablesmember) { - next_customvariablesmember = this_customvariablesmember->next; - my_free(this_customvariablesmember->variable_name); - my_free(this_customvariablesmember->variable_value); - my_free(this_customvariablesmember); - } - mac->custom_host_vars = NULL; - - /* clear custom service variables */ - for(this_customvariablesmember = mac->custom_service_vars; this_customvariablesmember != NULL; this_customvariablesmember = next_customvariablesmember) { - next_customvariablesmember = this_customvariablesmember->next; - my_free(this_customvariablesmember->variable_name); - my_free(this_customvariablesmember->variable_value); - my_free(this_customvariablesmember); - } - mac->custom_service_vars = NULL; - - /* clear custom contact variables */ - for(this_customvariablesmember = mac->custom_contact_vars; this_customvariablesmember != NULL; this_customvariablesmember = next_customvariablesmember) { - next_customvariablesmember = this_customvariablesmember->next; - my_free(this_customvariablesmember->variable_name); - my_free(this_customvariablesmember->variable_value); - my_free(this_customvariablesmember); - } - mac->custom_contact_vars = NULL; - return OK; } @@ -2915,59 +2889,28 @@ int clear_volatile_macros(void) { } +/* clear datetime macros */ +int clear_datetime_macros_r(nagios_macros *mac) { + my_free(mac->x[MACRO_LONGDATETIME]); + my_free(mac->x[MACRO_SHORTDATETIME]); + my_free(mac->x[MACRO_DATE]); + my_free(mac->x[MACRO_TIME]); + + return OK; + } + /* clear service macros */ int clear_service_macros_r(nagios_macros *mac) { - customvariablesmember *this_customvariablesmember = NULL; - customvariablesmember *next_customvariablesmember = NULL; - - /* FIXME: strings. make these not be strdup()'s anymore */ - my_free(mac->x[MACRO_SERVICEDESC]); - my_free(mac->x[MACRO_SERVICEDISPLAYNAME]); - my_free(mac->x[MACRO_SERVICEOUTPUT]); - my_free(mac->x[MACRO_LONGSERVICEOUTPUT]); - my_free(mac->x[MACRO_SERVICEPERFDATA]); /* these are recursive but persistent. what to do? */ - my_free(mac->x[MACRO_SERVICECHECKCOMMAND]); my_free(mac->x[MACRO_SERVICEACTIONURL]); my_free(mac->x[MACRO_SERVICENOTESURL]); my_free(mac->x[MACRO_SERVICENOTES]); - my_free(mac->x[MACRO_SERVICECHECKTYPE]); - my_free(mac->x[MACRO_SERVICESTATETYPE]); - my_free(mac->x[MACRO_SERVICESTATE]); - my_free(mac->x[MACRO_SERVICEISVOLATILE]); - my_free(mac->x[MACRO_SERVICESTATEID]); - my_free(mac->x[MACRO_SERVICEATTEMPT]); - my_free(mac->x[MACRO_MAXSERVICEATTEMPTS]); - my_free(mac->x[MACRO_SERVICEEXECUTIONTIME]); - my_free(mac->x[MACRO_SERVICELATENCY]); - my_free(mac->x[MACRO_LASTSERVICECHECK]); - my_free(mac->x[MACRO_LASTSERVICESTATECHANGE]); - my_free(mac->x[MACRO_LASTSERVICEOK]); - my_free(mac->x[MACRO_LASTSERVICEWARNING]); - my_free(mac->x[MACRO_LASTSERVICEUNKNOWN]); - my_free(mac->x[MACRO_LASTSERVICECRITICAL]); - my_free(mac->x[MACRO_SERVICEDOWNTIME]); - my_free(mac->x[MACRO_SERVICEPERCENTCHANGE]); - my_free(mac->x[MACRO_SERVICEDURATIONSEC]); - my_free(mac->x[MACRO_SERVICEDURATION]); - my_free(mac->x[MACRO_SERVICENOTIFICATIONNUMBER]); - my_free(mac->x[MACRO_SERVICENOTIFICATIONID]); - my_free(mac->x[MACRO_SERVICEEVENTID]); - my_free(mac->x[MACRO_LASTSERVICEEVENTID]); my_free(mac->x[MACRO_SERVICEGROUPNAMES]); - my_free(mac->x[MACRO_SERVICEPROBLEMID]); - my_free(mac->x[MACRO_LASTSERVICEPROBLEMID]); /* clear custom service variables */ - for(this_customvariablesmember = mac->custom_service_vars; this_customvariablesmember != NULL; this_customvariablesmember = next_customvariablesmember) { - next_customvariablesmember = this_customvariablesmember->next; - my_free(this_customvariablesmember->variable_name); - my_free(this_customvariablesmember->variable_value); - my_free(this_customvariablesmember); - } - mac->custom_service_vars = NULL; + clear_custom_vars(&(mac->custom_service_vars)); /* clear pointers */ mac->service_ptr = NULL; @@ -2981,64 +2924,17 @@ int clear_service_macros(void) { /* clear host macros */ int clear_host_macros_r(nagios_macros *mac) { - customvariablesmember *this_customvariablesmember = NULL; - customvariablesmember *next_customvariablesmember = NULL; - - /* FIXME: strings; Fix these to not be strdup()'s anymore */ - my_free(mac->x[MACRO_HOSTNAME]); - my_free(mac->x[MACRO_HOSTDISPLAYNAME]); - my_free(mac->x[MACRO_HOSTALIAS]); - my_free(mac->x[MACRO_HOSTADDRESS]); - my_free(mac->x[MACRO_HOSTOUTPUT]); - my_free(mac->x[MACRO_LONGHOSTOUTPUT]); - my_free(mac->x[MACRO_HOSTPERFDATA]); /* these are recursive but persistent. what to do? */ - my_free(mac->x[MACRO_HOSTCHECKCOMMAND]); my_free(mac->x[MACRO_HOSTACTIONURL]); my_free(mac->x[MACRO_HOSTNOTESURL]); my_free(mac->x[MACRO_HOSTNOTES]); /* numbers or by necessity autogenerated strings */ - my_free(mac->x[MACRO_HOSTSTATE]); - my_free(mac->x[MACRO_HOSTSTATEID]); - my_free(mac->x[MACRO_HOSTCHECKTYPE]); - my_free(mac->x[MACRO_HOSTSTATETYPE]); - my_free(mac->x[MACRO_HOSTATTEMPT]); - my_free(mac->x[MACRO_MAXHOSTATTEMPTS]); - my_free(mac->x[MACRO_HOSTDOWNTIME]); - my_free(mac->x[MACRO_HOSTPERCENTCHANGE]); - my_free(mac->x[MACRO_HOSTDURATIONSEC]); - my_free(mac->x[MACRO_HOSTDURATION]); - my_free(mac->x[MACRO_HOSTEXECUTIONTIME]); - my_free(mac->x[MACRO_HOSTLATENCY]); - my_free(mac->x[MACRO_LASTHOSTCHECK]); - my_free(mac->x[MACRO_LASTHOSTSTATECHANGE]); - my_free(mac->x[MACRO_LASTHOSTUP]); - my_free(mac->x[MACRO_LASTHOSTDOWN]); - my_free(mac->x[MACRO_LASTHOSTUNREACHABLE]); - my_free(mac->x[MACRO_HOSTNOTIFICATIONNUMBER]); - my_free(mac->x[MACRO_HOSTNOTIFICATIONID]); - my_free(mac->x[MACRO_HOSTEVENTID]); - my_free(mac->x[MACRO_LASTHOSTEVENTID]); my_free(mac->x[MACRO_HOSTGROUPNAMES]); - my_free(mac->x[MACRO_TOTALHOSTSERVICES]); - my_free(mac->x[MACRO_TOTALHOSTSERVICESOK]); - my_free(mac->x[MACRO_TOTALHOSTSERVICESWARNING]); - my_free(mac->x[MACRO_TOTALHOSTSERVICESUNKNOWN]); - my_free(mac->x[MACRO_TOTALHOSTSERVICESCRITICAL]); - my_free(mac->x[MACRO_HOSTPROBLEMID]); - my_free(mac->x[MACRO_LASTHOSTPROBLEMID]); - /* clear custom host variables */ - for(this_customvariablesmember = mac->custom_host_vars; this_customvariablesmember != NULL; this_customvariablesmember = next_customvariablesmember) { - next_customvariablesmember = this_customvariablesmember->next; - my_free(this_customvariablesmember->variable_name); - my_free(this_customvariablesmember->variable_value); - my_free(this_customvariablesmember); - } - mac->custom_host_vars = NULL; + clear_custom_vars(&(mac->custom_host_vars)); /* clear pointers */ mac->host_ptr = NULL; @@ -3053,17 +2949,15 @@ int clear_host_macros(void) { /* clear hostgroup macros */ int clear_hostgroup_macros_r(nagios_macros *mac) { - /* FIXME: make these not strdup()'s */ - my_free(mac->x[MACRO_HOSTGROUPNAME]); - my_free(mac->x[MACRO_HOSTGROUPALIAS]); - /* generated but persistent. what to do? */ + /* recursive but persistent. what to do? */ my_free(mac->x[MACRO_HOSTGROUPACTIONURL]); my_free(mac->x[MACRO_HOSTGROUPNOTESURL]); my_free(mac->x[MACRO_HOSTGROUPNOTES]); /* generated */ my_free(mac->x[MACRO_HOSTGROUPMEMBERS]); + my_free(mac->x[MACRO_HOSTGROUPMEMBERADDRESSES]); /* clear pointers */ mac->hostgroup_ptr = NULL; @@ -3078,11 +2972,7 @@ int clear_hostgroup_macros(void) { /* clear servicegroup macros */ int clear_servicegroup_macros_r(nagios_macros *mac) { - /* FIXME: these should not be strdup()'s */ - my_free(mac->x[MACRO_SERVICEGROUPNAME]); - my_free(mac->x[MACRO_SERVICEGROUPALIAS]); - - /* generated but persistent. what to do? */ + /* recursive but persistent. what to do? */ my_free(mac->x[MACRO_SERVICEGROUPACTIONURL]); my_free(mac->x[MACRO_SERVICEGROUPNOTESURL]); my_free(mac->x[MACRO_SERVICEGROUPNOTES]); @@ -3103,31 +2993,12 @@ int clear_servicegroup_macros(void) { /* clear contact macros */ int clear_contact_macros_r(nagios_macros *mac) { - register int x; - customvariablesmember *this_customvariablesmember = NULL; - customvariablesmember *next_customvariablesmember = NULL; - /* FIXME: these should not be strdup()'d */ - my_free(mac->x[MACRO_CONTACTNAME]); - my_free(mac->x[MACRO_CONTACTALIAS]); - my_free(mac->x[MACRO_CONTACTEMAIL]); - my_free(mac->x[MACRO_CONTACTPAGER]); - - /* generated per contact */ + /* generated */ my_free(mac->x[MACRO_CONTACTGROUPNAMES]); - /* clear contact addresses */ - for(x = 0; x < MAX_CONTACT_ADDRESSES; x++) - my_free(mac->contactaddress[x]); - /* clear custom contact variables */ - for(this_customvariablesmember = mac->custom_contact_vars; this_customvariablesmember != NULL; this_customvariablesmember = next_customvariablesmember) { - next_customvariablesmember = this_customvariablesmember->next; - my_free(this_customvariablesmember->variable_name); - my_free(this_customvariablesmember->variable_value); - my_free(this_customvariablesmember); - } - mac->custom_contact_vars = NULL; + clear_custom_vars(&(mac->custom_contact_vars)); /* clear pointers */ mac->contact_ptr = NULL; @@ -3142,8 +3013,7 @@ int clear_contact_macros(void) { /* clear contactgroup macros */ int clear_contactgroup_macros_r(nagios_macros *mac) { - my_free(mac->x[MACRO_CONTACTGROUPNAME]); - my_free(mac->x[MACRO_CONTACTGROUPALIAS]); + /* generated */ my_free(mac->x[MACRO_CONTACTGROUPMEMBERS]); /* clear pointers */ @@ -3156,7 +3026,6 @@ int clear_contactgroup_macros(void) { return clear_contactgroup_macros_r(&global_macros); } - /* clear summary macros */ int clear_summary_macros_r(nagios_macros *mac) { register int x; @@ -3200,24 +3069,31 @@ int set_all_macro_environment_vars(int set) { int set_macrox_environment_vars_r(nagios_macros *mac, int set) { register int x = 0; int free_macro = FALSE; - int generate_macro = TRUE; /* set each of the macrox environment variables */ for(x = 0; x < MACRO_X_COUNT; x++) { free_macro = FALSE; + /* large installations don't get all macros */ + if(use_large_installation_tweaks == TRUE) { + /* + * member macros tend to overflow the + * environment on large installations + */ + if(x == MACRO_SERVICEGROUPMEMBERS || x == MACRO_HOSTGROUPMEMBERS || x == MACRO_HOSTGROUPMEMBERADDRESSES) + continue; + + /* summary macros are CPU intensive to compute */ + if(x >= MACRO_TOTALHOSTSUP && x <= MACRO_TOTALSERVICEPROBLEMSUNHANDLED) + continue; + } + /* generate the macro value if it hasn't already been done */ /* THIS IS EXPENSIVE */ if(set == TRUE) { - generate_macro = TRUE; - - /* skip summary macro generation if lage installation tweaks are enabled */ - if((x >= MACRO_TOTALHOSTSUP && x <= MACRO_TOTALSERVICEPROBLEMSUNHANDLED) && use_large_installation_tweaks == TRUE) - generate_macro = FALSE; - - if(mac->x[x] == NULL && generate_macro == TRUE) + if(mac->x[x] == NULL) grab_macrox_value_r(mac, x, NULL, NULL, &mac->x[x], &free_macro); } @@ -3352,5 +3228,251 @@ int set_macro_environment_var(char *name, char *value, int set) { return OK; } +static int add_macrox_environment_vars_r(nagios_macros *, struct kvvec *); +static int add_argv_macro_environment_vars_r(nagios_macros *, struct kvvec *); +static int add_custom_macro_environment_vars_r(nagios_macros *, struct kvvec *); +static int add_contact_address_environment_vars_r(nagios_macros *, + struct kvvec *); + +struct kvvec * macros_to_kvv(nagios_macros *mac) { + + struct kvvec *kvvp; + + log_debug_info(DEBUGL_FUNCTIONS, 0, "macros_to_kvv()\n"); + + /* If we're not supposed to export macros as environment variables, + just return */ + if(FALSE == enable_environment_macros) return NULL; + + /* Create the kvvec to hold the macros */ + if((kvvp = calloc(1, sizeof(struct kvvec))) == NULL) return NULL; + if(!kvvec_init(kvvp, MACRO_X_COUNT + MAX_COMMAND_ARGUMENTS + MAX_CONTACT_ADDRESSES + 4)) return NULL; + + add_macrox_environment_vars_r(mac, kvvp); + add_argv_macro_environment_vars_r(mac, kvvp); + add_custom_macro_environment_vars_r(mac, kvvp); + add_contact_address_environment_vars_r(mac, kvvp); + + return kvvp; + } + +/* adds macrox environment variables */ +static int add_macrox_environment_vars_r(nagios_macros *mac, struct kvvec *kvvp) +{ + /*register*/ int x = 0; + int free_macro = FALSE; + char *envname; + + log_debug_info(DEBUGL_FUNCTIONS, 1, "add_macrox_environment_vars_r()\n"); + + /* set each of the macrox environment variables */ + for(x = 0; x < MACRO_X_COUNT; x++) { + + log_debug_info(DEBUGL_MACROS, 2, "Processing macro %d of %d\n", x, + MACRO_X_COUNT); + free_macro = FALSE; + + /* large installations don't get all macros */ + if(use_large_installation_tweaks == TRUE) { + /* + * member macros tend to overflow the + * environment on large installations + */ + if(x == MACRO_SERVICEGROUPMEMBERS || x == MACRO_HOSTGROUPMEMBERS || + x == MACRO_HOSTGROUPMEMBERADDRESSES) + continue; + + /* summary macros are CPU intensive to compute */ + if(x >= MACRO_TOTALHOSTSUP && x <= MACRO_TOTALSERVICEPROBLEMSUNHANDLED) + continue; + } + + /* generate the macro value if it hasn't already been done */ + /* THIS IS EXPENSIVE */ + if(mac->x[x] == NULL) { + log_debug_info(DEBUGL_MACROS, 2, "Grabbing value for macro: %s\n", + macro_x_names[x]); + + grab_macrox_value_r(mac, x, NULL, NULL, &mac->x[x], &free_macro); + } + + /* add the value to the kvvec */ + log_debug_info(DEBUGL_MACROS, 2, "Adding macro \"%s\" with value \"%s\" to kvvec\n", + macro_x_names[x], mac->x[x]); + /* Allocate memory for each environment variable name, but not the + values because when kvvec_destroy() is called, it is called with + KVVEC_FREE_KEYS */ + asprintf(&envname, "%s%s", MACRO_ENV_VAR_PREFIX, macro_x_names[x]); + kvvec_addkv(kvvp, envname, mac->x[x]); + } + + log_debug_info(DEBUGL_FUNCTIONS, 2, "add_macrox_environment_vars_r() end\n"); + return OK; + } + +/* adds argv macro environment variables */ +static int add_argv_macro_environment_vars_r(nagios_macros *mac, + struct kvvec *kvvp) { + char *macro_name = NULL; + register int x = 0; + + log_debug_info(DEBUGL_FUNCTIONS, 1, "add_argv_macro_environment_vars_r()\n"); + + /* set each of the argv macro environment variables */ + for(x = 0; x < MAX_COMMAND_ARGUMENTS; x++) { + /* Allocate memory for each environment variable name, but not the + values because when kvvec_destroy() is called, it is called with + KVVEC_FREE_KEYS */ + asprintf(¯o_name, "%sARG%d", MACRO_ENV_VAR_PREFIX, x + 1); + kvvec_addkv(kvvp, macro_name, mac->argv[x]); + } + + return OK; + } + +/* adds custom host/service/contact macro environment variables */ +static int add_custom_macro_environment_vars_r(nagios_macros *mac, + struct kvvec *kvvp) { + + customvariablesmember *temp_customvariablesmember = NULL; + host *temp_host = NULL; + service *temp_service = NULL; + contact *temp_contact = NULL; + char *customvarname = NULL; + char *customvarvalue = NULL; + + log_debug_info(DEBUGL_FUNCTIONS, 1, "add_custom_macro_environment_vars_r()\n"); + + /***** CUSTOM HOST VARIABLES *****/ + /* generate variables and save them for later */ + temp_host = mac->host_ptr; + if(temp_host) { + for(temp_customvariablesmember = temp_host->custom_variables; + temp_customvariablesmember != NULL; + temp_customvariablesmember = temp_customvariablesmember->next) { + asprintf(&customvarname, "%s_HOST%s", MACRO_ENV_VAR_PREFIX, + temp_customvariablesmember->variable_name); + add_custom_variable_to_object(&mac->custom_host_vars, customvarname, + temp_customvariablesmember->variable_value); + my_free(customvarname); + } + } + /* set variables */ + for(temp_customvariablesmember = mac->custom_host_vars; + temp_customvariablesmember != NULL; + temp_customvariablesmember = temp_customvariablesmember->next) { + customvarvalue = + clean_macro_chars(temp_customvariablesmember->variable_value, + STRIP_ILLEGAL_MACRO_CHARS | ESCAPE_MACRO_CHARS); + if(customvarvalue && *customvarvalue) { + my_free(temp_customvariablesmember->variable_value); + temp_customvariablesmember->variable_value = customvarvalue; + /* Allocate memory for each environment variable name, but not the + values because when kvvec_destroy() is called, it is called with + KVVEC_FREE_KEYS */ + kvvec_addkv(kvvp, strdup(temp_customvariablesmember->variable_name), + customvarvalue); + } + } + + /***** CUSTOM SERVICE VARIABLES *****/ + /* generate variables and save them for later */ + temp_service = mac->service_ptr; + if(temp_service) { + for(temp_customvariablesmember = temp_service->custom_variables; + temp_customvariablesmember != NULL; + temp_customvariablesmember = temp_customvariablesmember->next) { + asprintf(&customvarname, "%s_SERVICE%s", MACRO_ENV_VAR_PREFIX, + temp_customvariablesmember->variable_name); + add_custom_variable_to_object(&mac->custom_service_vars, + customvarname, temp_customvariablesmember->variable_value); + my_free(customvarname); + } + } + /* set variables */ + for(temp_customvariablesmember = mac->custom_service_vars; + temp_customvariablesmember != NULL; + temp_customvariablesmember = temp_customvariablesmember->next) { + customvarvalue = + clean_macro_chars(temp_customvariablesmember->variable_value, + STRIP_ILLEGAL_MACRO_CHARS | ESCAPE_MACRO_CHARS); + if(customvarvalue && *customvarvalue) { + my_free(temp_customvariablesmember->variable_value); + temp_customvariablesmember->variable_value = customvarvalue; + /* Allocate memory for each environment variable name, but not the + values because when kvvec_destroy() is called, it is called with + KVVEC_FREE_KEYS */ + kvvec_addkv(kvvp, strdup(temp_customvariablesmember->variable_name), + customvarvalue); + } + } + + /***** CUSTOM CONTACT VARIABLES *****/ + /* generate variables and save them for later */ + temp_contact = mac->contact_ptr; + if(temp_contact) { + for(temp_customvariablesmember = temp_contact->custom_variables; + temp_customvariablesmember != NULL; + temp_customvariablesmember = temp_customvariablesmember->next) { + asprintf(&customvarname, "%s_CONTACT%s", MACRO_ENV_VAR_PREFIX, + temp_customvariablesmember->variable_name); + add_custom_variable_to_object(&mac->custom_contact_vars, + customvarname, temp_customvariablesmember->variable_value); + my_free(customvarname); + } + } + /* set variables */ + for(temp_customvariablesmember = mac->custom_contact_vars; + temp_customvariablesmember != NULL; + temp_customvariablesmember = temp_customvariablesmember->next) { + customvarvalue = + clean_macro_chars(temp_customvariablesmember->variable_value, + STRIP_ILLEGAL_MACRO_CHARS | ESCAPE_MACRO_CHARS); + if(customvarvalue && *customvarvalue) { + my_free(temp_customvariablesmember->variable_value); + temp_customvariablesmember->variable_value = customvarvalue; + /* Allocate memory for each environment variable name, but not the + values because when kvvec_destroy() is called, it is called with + KVVEC_FREE_KEYS */ + kvvec_addkv(kvvp, strdup(temp_customvariablesmember->variable_name), + customvarvalue); + } + } + + return OK; + } + +/* add contact address environment variables */ +static int add_contact_address_environment_vars_r(nagios_macros *mac, + struct kvvec *kvvp) { + + char *varname = NULL; + register int x; + + log_debug_info(DEBUGL_FUNCTIONS, 1, "add_contact_address_environment_vars_r()\n"); + + /* these only get set during notifications */ + if(mac->contact_ptr == NULL) + return OK; + + asprintf(&varname, "%sCONTACTNAME", MACRO_ENV_VAR_PREFIX); + kvvec_addkv(kvvp, varname, mac->contact_ptr->name); + asprintf(&varname, "%sCONTACTALIAS", MACRO_ENV_VAR_PREFIX); + kvvec_addkv(kvvp, varname, mac->contact_ptr->alias); + asprintf(&varname, "%sCONTACTEMAIL", MACRO_ENV_VAR_PREFIX); + kvvec_addkv(kvvp, varname, mac->contact_ptr->email); + asprintf(&varname, "%sCONTACTPAGER", MACRO_ENV_VAR_PREFIX); + kvvec_addkv(kvvp, varname, mac->contact_ptr->pager); + + for(x = 0; x < MAX_CONTACT_ADDRESSES; x++) { + /* Allocate memory for each environment variable name, but not the + values because when kvvec_destroy() is called, it is called with + KVVEC_FREE_KEYS */ + asprintf(&varname, "%sCONTACTADDRESS%d", MACRO_ENV_VAR_PREFIX, x); + kvvec_addkv(kvvp, varname, mac->contact_ptr->address[x]); + } + + return OK; + } #endif diff --git a/common/objects.c b/common/objects.c index d16f75d..468ed0f 100644 --- a/common/objects.c +++ b/common/objects.c @@ -2,8 +2,6 @@ * * OBJECTS.C - Object addition and search functions for Nagios * - * Copyright (c) 1999-2008 Ethan Galstad (egalstad@nagios.org) - * Last Modified: 11-30-2008 * * License: * @@ -25,65 +23,259 @@ #include "../include/config.h" #include "../include/common.h" #include "../include/objects.h" -#include "../include/skiplist.h" - -#ifdef NSCORE -#include "../include/nagios.h" -#endif +#include "../xdata/xodtemplate.h" #ifdef NSCGI #include "../include/cgiutils.h" -#endif - -/**** IMPLEMENTATION-SPECIFIC HEADER FILES ****/ - -#ifdef USE_XODTEMPLATE /* template-based routines */ -#include "../xdata/xodtemplate.h" +#else +#include "../include/nagios.h" #endif -host *host_list = NULL, *host_list_tail = NULL; -service *service_list = NULL, *service_list_tail = NULL; -contact *contact_list = NULL, *contact_list_tail = NULL; -contactgroup *contactgroup_list = NULL, *contactgroup_list_tail = NULL; -hostgroup *hostgroup_list = NULL, *hostgroup_list_tail = NULL; -servicegroup *servicegroup_list = NULL, *servicegroup_list_tail = NULL; -command *command_list = NULL, *command_list_tail = NULL; -timeperiod *timeperiod_list = NULL, *timeperiod_list_tail = NULL; -serviceescalation *serviceescalation_list = NULL, *serviceescalation_list_tail = NULL; -servicedependency *servicedependency_list = NULL, *servicedependency_list_tail = NULL; -hostdependency *hostdependency_list = NULL, *hostdependency_list_tail = NULL; -hostescalation *hostescalation_list = NULL, *hostescalation_list_tail = NULL; -skiplist *object_skiplists[NUM_OBJECT_SKIPLISTS]; +/* + * These get created in xdata/xodtemplate.c:xodtemplate_register_objects() + * Escalations are attached to the objects they belong to. + * Dependencies are attached to the dependent end of the object chain. + */ +dkhash_table *object_hash_tables[NUM_OBJECT_SKIPLISTS]; +command *command_list = NULL; +timeperiod *timeperiod_list = NULL; +host *host_list = NULL; +service *service_list = NULL; +contact *contact_list = NULL; +hostgroup *hostgroup_list = NULL; +servicegroup *servicegroup_list = NULL; +contactgroup *contactgroup_list = NULL; +hostescalation *hostescalation_list = NULL; +serviceescalation *serviceescalation_list = NULL; +command **command_ary = NULL; +timeperiod **timeperiod_ary = NULL; +host **host_ary = NULL; +service **service_ary = NULL; +contact **contact_ary = NULL; +hostgroup **hostgroup_ary = NULL; +servicegroup **servicegroup_ary = NULL; +contactgroup **contactgroup_ary = NULL; +hostescalation **hostescalation_ary = NULL; +serviceescalation **serviceescalation_ary = NULL; +hostdependency **hostdependency_ary = NULL; +servicedependency **servicedependency_ary = NULL; -#ifdef NSCORE +#ifndef NSCGI int __nagios_object_structure_version = CURRENT_OBJECT_STRUCTURE_VERSION; -extern int use_precached_objects; + +struct flag_map { + int opt; + int ch; + const char *name; +}; + +static const struct flag_map service_flag_map[] = { + { OPT_WARNING, 'w', "warning" }, + { OPT_UNKNOWN, 'u', "unknown" }, + { OPT_CRITICAL, 'c', "critical" }, + { OPT_FLAPPING, 'f', "flapping" }, + { OPT_DOWNTIME, 's', "downtime" }, + { OPT_OK, 'o', "ok" }, + { OPT_RECOVERY, 'r', "recovery" }, + { OPT_PENDING, 'p', "pending" }, + { 0, 0, NULL }, +}; + +static const struct flag_map host_flag_map[] = { + { OPT_DOWN, 'd', "down" }, + { OPT_UNREACHABLE, 'u', "unreachable" }, + { OPT_FLAPPING, 'f', "flapping" }, + { OPT_RECOVERY, 'r', "recovery" }, + { OPT_DOWNTIME, 's', "downtime" }, + { OPT_PENDING, 'p', "pending" }, + { 0, 0, NULL }, +}; + +static const char *opts2str(int opts, const struct flag_map *map, char ok_char) +{ + int i, pos = 0; + static char buf[16]; + + if(!opts) + return "n"; + + if(opts == OPT_ALL) + return "a"; + + if(flag_isset(opts, OPT_OK)) { + flag_unset(opts, OPT_OK); + buf[pos++] = ok_char; + buf[pos++] = opts ? ',' : 0; + } + + for (i = 0; map[i].name; i++) { + if(flag_isset(opts, map[i].opt)) { + buf[pos++] = map[i].ch; + flag_unset(opts, map[i].opt); + if(!opts) + break; + buf[pos++] = ','; + } + } + buf[pos++] = 0; + return buf; +} #endif +unsigned int host_services_value(host *h) { + servicesmember *sm; + unsigned int ret = 0; + for(sm = h->services; sm; sm = sm->next) { + ret += sm->service_ptr->hourly_value; + } + return ret; + } +#ifndef NSCGI +/* Host/Service dependencies are not visible in Nagios CGIs, so we exclude them */ +static int cmp_sdep(const void *a_, const void *b_) { + const servicedependency *a = *(servicedependency **)a_; + const servicedependency *b = *(servicedependency **)b_; + int ret; + ret = a->master_service_ptr->id - b->master_service_ptr->id; + return ret ? ret : (int)(a->dependent_service_ptr->id - b->dependent_service_ptr->id); + } + +static int cmp_hdep(const void *a_, const void *b_) { + const hostdependency *a = *(const hostdependency **)a_; + const hostdependency *b = *(const hostdependency **)b_; + int ret; + ret = a->master_host_ptr->id - b->master_host_ptr->id; + return ret ? ret : (int)(a->dependent_host_ptr->id - b->dependent_host_ptr->id); + } + +static int cmp_serviceesc(const void *a_, const void *b_) { + const serviceescalation *a = *(const serviceescalation **)a_; + const serviceescalation *b = *(const serviceescalation **)b_; + return a->service_ptr->id - b->service_ptr->id; + } + +static int cmp_hostesc(const void *a_, const void *b_) { + const hostescalation *a = *(const hostescalation **)a_; + const hostescalation *b = *(const hostescalation **)b_; + return a->host_ptr->id - b->host_ptr->id; + } +#endif + +static void post_process_object_config(void) { + objectlist *list; + unsigned int i, slot; + + if(hostdependency_ary) + free(hostdependency_ary); + if(servicedependency_ary) + free(servicedependency_ary); + + hostdependency_ary = calloc(num_objects.hostdependencies, sizeof(void *)); + servicedependency_ary = calloc(num_objects.servicedependencies, sizeof(void *)); + + slot = 0; + for(i = 0; slot < num_objects.servicedependencies && i < num_objects.services; i++) { + service *s = service_ary[i]; + for(list = s->notify_deps; list; list = list->next) + servicedependency_ary[slot++] = (servicedependency *)list->object_ptr; + for(list = s->exec_deps; list; list = list->next) + servicedependency_ary[slot++] = (servicedependency *)list->object_ptr; + } + timing_point("Done post-processing servicedependencies\n"); + + slot = 0; + for(i = 0; slot < num_objects.hostdependencies && i < num_objects.hosts; i++) { + host *h = host_ary[i]; + for(list = h->notify_deps; list; list = list->next) + hostdependency_ary[slot++] = (hostdependency *)list->object_ptr; + for(list = h->exec_deps; list; list = list->next) + hostdependency_ary[slot++] = (hostdependency *)list->object_ptr; + } + timing_point("Done post-processing host dependencies\n"); + +#ifndef NSCGI + /* cgi's always get their objects in sorted order */ + if(servicedependency_ary) + qsort(servicedependency_ary, num_objects.servicedependencies, sizeof(servicedependency *), cmp_sdep); + if(hostdependency_ary) + qsort(hostdependency_ary, num_objects.hostdependencies, sizeof(hostdependency *), cmp_hdep); + if(hostescalation_ary) + qsort(hostescalation_ary, num_objects.hostescalations, sizeof(hostescalation *), cmp_hostesc); + if(serviceescalation_ary) + qsort(serviceescalation_ary, num_objects.serviceescalations, sizeof(serviceescalation *), cmp_serviceesc); + timing_point("Done post-sorting slave objects\n"); +#endif + + timeperiod_list = timeperiod_ary ? *timeperiod_ary : NULL; + command_list = command_ary ? *command_ary : NULL; + hostgroup_list = hostgroup_ary ? *hostgroup_ary : NULL; + contactgroup_list = contactgroup_ary ? *contactgroup_ary : NULL; + servicegroup_list = servicegroup_ary ? *servicegroup_ary : NULL; + contact_list = contact_ary ? *contact_ary : NULL; + host_list = host_ary ? *host_ary : NULL; + service_list = service_ary ? *service_ary : NULL; + hostescalation_list = hostescalation_ary ? *hostescalation_ary : NULL; + serviceescalation_list = serviceescalation_ary ? *serviceescalation_ary : NULL; +} + +/* simple state-name helpers, nifty to have all over the place */ +const char *service_state_name(int state) +{ + switch (state) { + case STATE_OK: return "OK"; + case STATE_WARNING: return "WARNING"; + case STATE_CRITICAL: return "CRITICAL"; + } + + return "UNKNOWN"; +} + +const char *host_state_name(int state) +{ + switch (state) { + case HOST_UP: return "UP"; + case HOST_DOWN: return "DOWN"; + case HOST_UNREACHABLE: return "UNREACHABLE"; + } + + return "(unknown)"; +} + +const char *state_type_name(int state_type) +{ + return state_type == HARD_STATE ? "HARD" : "SOFT"; +} + +const char *check_type_name(int check_type) +{ + return check_type == CHECK_TYPE_PASSIVE ? "PASSIVE" : "ACTIVE"; +} + /******************************************************************/ /******* TOP-LEVEL HOST CONFIGURATION DATA INPUT FUNCTION *********/ /******************************************************************/ /* read all host configuration data from external source */ -int read_object_config_data(char *main_config_file, int options, int cache, int precache) { +int read_object_config_data(const char *main_config_file, int options) { int result = OK; - /* initialize object skiplists */ - init_object_skiplists(); + /* reset object counts */ + memset(&num_objects, 0, sizeof(num_objects)); - /********* IMPLEMENTATION-SPECIFIC INPUT FUNCTION ********/ -#ifdef USE_XODTEMPLATE /* read in data from all text host config files (template-based) */ - result = xodtemplate_read_config_data(main_config_file, options, cache, precache); + result = xodtemplate_read_config_data(main_config_file, options); if(result != OK) return ERROR; -#endif + + /* handle any remaining config mangling */ + post_process_object_config(); + timing_point("Done post-processing configuration\n"); return result; } @@ -94,41 +286,6 @@ int read_object_config_data(char *main_config_file, int options, int cache, int /******************** SKIPLIST FUNCTIONS **************************/ /******************************************************************/ -int init_object_skiplists(void) { - int x = 0; - - for(x = 0; x < NUM_OBJECT_SKIPLISTS; x++) - object_skiplists[x] = NULL; - - object_skiplists[HOST_SKIPLIST] = skiplist_new(15, 0.5, FALSE, FALSE, skiplist_compare_host); - object_skiplists[SERVICE_SKIPLIST] = skiplist_new(15, 0.5, FALSE, FALSE, skiplist_compare_service); - - object_skiplists[COMMAND_SKIPLIST] = skiplist_new(10, 0.5, FALSE, FALSE, skiplist_compare_command); - object_skiplists[TIMEPERIOD_SKIPLIST] = skiplist_new(10, 0.5, FALSE, FALSE, skiplist_compare_timeperiod); - object_skiplists[CONTACT_SKIPLIST] = skiplist_new(10, 0.5, FALSE, FALSE, skiplist_compare_contact); - object_skiplists[CONTACTGROUP_SKIPLIST] = skiplist_new(10, 0.5, FALSE, FALSE, skiplist_compare_contactgroup); - object_skiplists[HOSTGROUP_SKIPLIST] = skiplist_new(10, 0.5, FALSE, FALSE, skiplist_compare_hostgroup); - object_skiplists[SERVICEGROUP_SKIPLIST] = skiplist_new(10, 0.5, FALSE, FALSE, skiplist_compare_servicegroup); - - object_skiplists[HOSTESCALATION_SKIPLIST] = skiplist_new(15, 0.5, TRUE, FALSE, skiplist_compare_hostescalation); - object_skiplists[SERVICEESCALATION_SKIPLIST] = skiplist_new(15, 0.5, TRUE, FALSE, skiplist_compare_serviceescalation); - object_skiplists[HOSTDEPENDENCY_SKIPLIST] = skiplist_new(15, 0.5, TRUE, FALSE, skiplist_compare_hostdependency); - object_skiplists[SERVICEDEPENDENCY_SKIPLIST] = skiplist_new(15, 0.5, TRUE, FALSE, skiplist_compare_servicedependency); - - return OK; - } - - - -int free_object_skiplists(void) { - int x = 0; - - for(x = 0; x < NUM_OBJECT_SKIPLISTS; x++) - skiplist_free(&object_skiplists[x]); - - return OK; - } - int skiplist_compare_text(const char *val1a, const char *val1b, const char *val2a, const char *val2b) { int result = 0; @@ -159,237 +316,13 @@ int skiplist_compare_text(const char *val1a, const char *val1b, const char *val2 } -int skiplist_compare_host(void *a, void *b) { - host *oa = NULL; - host *ob = NULL; - - oa = (host *)a; - ob = (host *)b; - - if(oa == NULL && ob == NULL) - return 0; - if(oa == NULL) - return 1; - if(ob == NULL) - return -1; - - return skiplist_compare_text(oa->name, NULL, ob->name, NULL); - } - - -int skiplist_compare_service(void *a, void *b) { - service *oa = NULL; - service *ob = NULL; - - oa = (service *)a; - ob = (service *)b; - - if(oa == NULL && ob == NULL) - return 0; - if(oa == NULL) - return 1; - if(ob == NULL) - return -1; - - return skiplist_compare_text(oa->host_name, oa->description, ob->host_name, ob->description); - } - - -int skiplist_compare_command(void *a, void *b) { - command *oa = NULL; - command *ob = NULL; - - oa = (command *)a; - ob = (command *)b; - - if(oa == NULL && ob == NULL) - return 0; - if(oa == NULL) - return 1; - if(ob == NULL) - return -1; - - return skiplist_compare_text(oa->name, NULL, ob->name, NULL); - } - - -int skiplist_compare_timeperiod(void *a, void *b) { - timeperiod *oa = NULL; - timeperiod *ob = NULL; - - oa = (timeperiod *)a; - ob = (timeperiod *)b; - - if(oa == NULL && ob == NULL) - return 0; - if(oa == NULL) - return 1; - if(ob == NULL) - return -1; - - return skiplist_compare_text(oa->name, NULL, ob->name, NULL); - } - - -int skiplist_compare_contact(void *a, void *b) { - contact *oa = NULL; - contact *ob = NULL; - - oa = (contact *)a; - ob = (contact *)b; - - if(oa == NULL && ob == NULL) - return 0; - if(oa == NULL) - return 1; - if(ob == NULL) - return -1; - - return skiplist_compare_text(oa->name, NULL, ob->name, NULL); - } - - -int skiplist_compare_contactgroup(void *a, void *b) { - contactgroup *oa = NULL; - contactgroup *ob = NULL; - - oa = (contactgroup *)a; - ob = (contactgroup *)b; - - if(oa == NULL && ob == NULL) - return 0; - if(oa == NULL) - return 1; - if(ob == NULL) - return -1; - - return skiplist_compare_text(oa->group_name, NULL, ob->group_name, NULL); - } - - -int skiplist_compare_hostgroup(void *a, void *b) { - hostgroup *oa = NULL; - hostgroup *ob = NULL; - - oa = (hostgroup *)a; - ob = (hostgroup *)b; - - if(oa == NULL && ob == NULL) - return 0; - if(oa == NULL) - return 1; - if(ob == NULL) - return -1; - - return skiplist_compare_text(oa->group_name, NULL, ob->group_name, NULL); - } - - -int skiplist_compare_servicegroup(void *a, void *b) { - servicegroup *oa = NULL; - servicegroup *ob = NULL; - - oa = (servicegroup *)a; - ob = (servicegroup *)b; - - if(oa == NULL && ob == NULL) - return 0; - if(oa == NULL) - return 1; - if(ob == NULL) - return -1; - - return skiplist_compare_text(oa->group_name, NULL, ob->group_name, NULL); - } - - -int skiplist_compare_hostescalation(void *a, void *b) { - hostescalation *oa = NULL; - hostescalation *ob = NULL; - - oa = (hostescalation *)a; - ob = (hostescalation *)b; - - if(oa == NULL && ob == NULL) - return 0; - if(oa == NULL) - return 1; - if(ob == NULL) - return -1; - - return skiplist_compare_text(oa->host_name, NULL, ob->host_name, NULL); - } - - -int skiplist_compare_serviceescalation(void *a, void *b) { - serviceescalation *oa = NULL; - serviceescalation *ob = NULL; - - oa = (serviceescalation *)a; - ob = (serviceescalation *)b; - - if(oa == NULL && ob == NULL) - return 0; - if(oa == NULL) - return 1; - if(ob == NULL) - return -1; - - return skiplist_compare_text(oa->host_name, oa->description, ob->host_name, ob->description); - } - - -int skiplist_compare_hostdependency(void *a, void *b) { - hostdependency *oa = NULL; - hostdependency *ob = NULL; - - oa = (hostdependency *)a; - ob = (hostdependency *)b; - - if(oa == NULL && ob == NULL) - return 0; - if(oa == NULL) - return 1; - if(ob == NULL) - return -1; - - return skiplist_compare_text(oa->dependent_host_name, NULL, ob->dependent_host_name, NULL); - } - - -int skiplist_compare_servicedependency(void *a, void *b) { - servicedependency *oa = NULL; - servicedependency *ob = NULL; - - oa = (servicedependency *)a; - ob = (servicedependency *)b; - - if(oa == NULL && ob == NULL) - return 0; - if(oa == NULL) - return 1; - if(ob == NULL) - return -1; - - return skiplist_compare_text(oa->dependent_host_name, oa->dependent_service_description, ob->dependent_host_name, ob->dependent_service_description); - } - - int get_host_count(void) { - - if(object_skiplists[HOST_SKIPLIST]) - return object_skiplists[HOST_SKIPLIST]->items; - - return 0; + return num_objects.hosts; } int get_service_count(void) { - - if(object_skiplists[SERVICE_SKIPLIST]) - return object_skiplists[SERVICE_SKIPLIST]->items; - - return 0; + return num_objects.services; } @@ -399,6 +332,71 @@ int get_service_count(void) { /**************** OBJECT ADDITION FUNCTIONS ***********************/ /******************************************************************/ +static int create_object_table(const char *name, unsigned int elems, unsigned int size, void **ptr) +{ + void *ret; + if (!elems) { + *ptr = NULL; + return OK; + } + ret = calloc(elems, size); + if (!ret) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Failed to allocate %s table with %u elements\n", name, elems); + return ERROR; + } + *ptr = ret; + return OK; +} + +#define mktable(name, id) \ + create_object_table(#name, ocount[id], sizeof(name *), (void **)&name##_ary) + +/* ocount is an array with NUM_OBJECT_TYPES members */ +int create_object_tables(unsigned int *ocount) +{ + int i; + + for (i = 0; i < NUM_HASHED_OBJECT_TYPES; i++) { + const unsigned int hash_size = ocount[i]; + if (!hash_size) + continue; + object_hash_tables[i] = dkhash_create(hash_size); + if (!object_hash_tables[i]) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Failed to create hash table with %u entries\n", hash_size); + } + } + + /* + * errors here will always lead to an early exit, so there's no need + * to free() successful allocs when later ones fail + */ + if (mktable(timeperiod, TIMEPERIOD_SKIPLIST) != OK) + return ERROR; + if (mktable(command, COMMAND_SKIPLIST) != OK) + return ERROR; + if (mktable(host, HOST_SKIPLIST) != OK) + return ERROR; + if (mktable(service, SERVICE_SKIPLIST) != OK) + return ERROR; + if (mktable(contact, CONTACT_SKIPLIST) != OK) + return ERROR; + if (mktable(hostgroup, HOSTGROUP_SKIPLIST) != OK) + return ERROR; + if (mktable(servicegroup, SERVICEGROUP_SKIPLIST) != OK) + return ERROR; + if (mktable(contactgroup, CONTACTGROUP_SKIPLIST) != OK) + return ERROR; + if (mktable(hostescalation, HOSTESCALATION_SKIPLIST) != OK) + return ERROR; + if (mktable(hostdependency, HOSTDEPENDENCY_SKIPLIST) != OK) + return ERROR; + if (mktable(serviceescalation, SERVICEESCALATION_SKIPLIST) != OK) + return ERROR; + if (mktable(servicedependency, SERVICEDEPENDENCY_SKIPLIST) != OK) + return ERROR; + + return OK; +} /* add a new timeperiod to the list in memory */ @@ -412,29 +410,27 @@ timeperiod *add_timeperiod(char *name, char *alias) { return NULL; } - /* allocate memory for the new timeperiod */ - if((new_timeperiod = calloc(1, sizeof(timeperiod))) == NULL) + new_timeperiod = calloc(1, sizeof(*new_timeperiod)); + if(!new_timeperiod) return NULL; /* copy string vars */ - if((new_timeperiod->name = (char *)strdup(name)) == NULL) - result = ERROR; - if((new_timeperiod->alias = (char *)strdup(alias)) == NULL) - result = ERROR; + new_timeperiod->name = name; + new_timeperiod->alias = alias ? alias : name; - /* add new timeperiod to skiplist */ + /* add new timeperiod to hash table */ if(result == OK) { - result = skiplist_insert(object_skiplists[TIMEPERIOD_SKIPLIST], (void *)new_timeperiod); + result = dkhash_insert(object_hash_tables[TIMEPERIOD_SKIPLIST], new_timeperiod->name, NULL, new_timeperiod); switch(result) { - case SKIPLIST_ERROR_DUPLICATE: + case DKHASH_EDUPE: logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Timeperiod '%s' has already been defined\n", name); result = ERROR; break; - case SKIPLIST_OK: + case DKHASH_OK: result = OK; break; default: - logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not add timeperiod '%s' to skiplist\n", name); + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not add timeperiod '%s' to hash table\n", name); result = ERROR; break; } @@ -442,22 +438,14 @@ timeperiod *add_timeperiod(char *name, char *alias) { /* handle errors */ if(result == ERROR) { - my_free(new_timeperiod->alias); - my_free(new_timeperiod->name); - my_free(new_timeperiod); + free(new_timeperiod); return NULL; } - /* timeperiods are registered alphabetically, so add new items to tail of list */ - if(timeperiod_list == NULL) { - timeperiod_list = new_timeperiod; - timeperiod_list_tail = timeperiod_list; - } - else { - timeperiod_list_tail->next = new_timeperiod; - timeperiod_list_tail = new_timeperiod; - } - + new_timeperiod->id = num_objects.timeperiods++; + if(new_timeperiod->id) + timeperiod_ary[new_timeperiod->id - 1]->next = new_timeperiod; + timeperiod_ary[new_timeperiod->id] = new_timeperiod; return new_timeperiod; } @@ -488,7 +476,7 @@ timeperiodexclusion *add_exclusion_to_timeperiod(timeperiod *period, char *name) /* add a new timerange to a timeperiod */ timerange *add_timerange_to_timeperiod(timeperiod *period, int day, unsigned long start_time, unsigned long end_time) { - timerange *new_timerange = NULL; + timerange *prev = NULL, *tr, *new_timerange = NULL; /* make sure we have the data we need */ if(period == NULL) @@ -498,11 +486,11 @@ timerange *add_timerange_to_timeperiod(timeperiod *period, int day, unsigned lon logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Day %d is not valid for timeperiod '%s'\n", day, period->name); return NULL; } - if(start_time < 0 || start_time > 86400) { + if(start_time > 86400) { logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Start time %lu on day %d is not valid for timeperiod '%s'\n", start_time, day, period->name); return NULL; } - if(end_time < 0 || end_time > 86400) { + if(end_time > 86400) { logit(NSLOG_CONFIG_ERROR, TRUE, "Error: End time %lu on day %d is not value for timeperiod '%s'\n", end_time, day, period->name); return NULL; } @@ -514,9 +502,26 @@ timerange *add_timerange_to_timeperiod(timeperiod *period, int day, unsigned lon new_timerange->range_start = start_time; new_timerange->range_end = end_time; - /* add the new time range to the head of the range list for this day */ - new_timerange->next = period->days[day]; - period->days[day] = new_timerange; + /* insertion-sort the new time range into the list for this day */ + if(!period->days[day] || period->days[day]->range_start > new_timerange->range_start) { + new_timerange->next = period->days[day]; + period->days[day] = new_timerange; + return new_timerange; + } + + for(tr = period->days[day]; tr; tr = tr->next) { + if(new_timerange->range_start < tr->range_start) { + new_timerange->next = tr; + prev->next = new_timerange; + break; + } + if(!tr->next) { + tr->next = new_timerange; + new_timerange->next = NULL; + break; + } + prev = tr; + } return new_timerange; } @@ -567,11 +572,11 @@ timerange *add_timerange_to_daterange(daterange *drange, unsigned long start_tim if(drange == NULL) return NULL; - if(start_time < 0 || start_time > 86400) { + if(start_time > 86400) { logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Start time %lu is not valid for timeperiod\n", start_time); return NULL; } - if(end_time < 0 || end_time > 86400) { + if(end_time > 86400) { logit(NSLOG_CONFIG_ERROR, TRUE, "Error: End time %lu is not value for timeperiod\n", end_time); return NULL; } @@ -593,19 +598,27 @@ timerange *add_timerange_to_daterange(daterange *drange, unsigned long start_tim /* add a new host definition */ -host *add_host(char *name, char *display_name, char *alias, char *address, char *check_period, int initial_state, double check_interval, double retry_interval, int max_attempts, int notify_up, int notify_down, int notify_unreachable, int notify_flapping, int notify_downtime, double notification_interval, double first_notification_delay, char *notification_period, int notifications_enabled, char *check_command, int checks_enabled, int accept_passive_checks, char *event_handler, int event_handler_enabled, int flap_detection_enabled, double low_flap_threshold, double high_flap_threshold, int flap_detection_on_up, int flap_detection_on_down, int flap_detection_on_unreachable, int stalk_on_up, int stalk_on_down, int stalk_on_unreachable, int process_perfdata, int failure_prediction_enabled, char *failure_prediction_options, int check_freshness, int freshness_threshold, char *notes, char *notes_url, char *action_url, char *icon_image, char *icon_image_alt, char *vrml_image, char *statusmap_image, int x_2d, int y_2d, int have_2d_coords, double x_3d, double y_3d, double z_3d, int have_3d_coords, int should_be_drawn, int retain_status_information, int retain_nonstatus_information, int obsess_over_host) { +host *add_host(char *name, char *display_name, char *alias, char *address, char *check_period, int initial_state, double check_interval, double retry_interval, int max_attempts, int notification_options, double notification_interval, double first_notification_delay, char *notification_period, int notifications_enabled, char *check_command, int checks_enabled, int accept_passive_checks, char *event_handler, int event_handler_enabled, int flap_detection_enabled, double low_flap_threshold, double high_flap_threshold, int flap_detection_options, int stalking_options, int process_perfdata, int check_freshness, int freshness_threshold, char *notes, char *notes_url, char *action_url, char *icon_image, char *icon_image_alt, char *vrml_image, char *statusmap_image, int x_2d, int y_2d, int have_2d_coords, double x_3d, double y_3d, double z_3d, int have_3d_coords, int should_be_drawn, int retain_status_information, int retain_nonstatus_information, int obsess, unsigned int hourly_value) { host *new_host = NULL; + timeperiod *check_tp = NULL, *notify_tp = NULL; int result = OK; -#ifdef NSCORE - int x = 0; -#endif /* make sure we have the data we need */ - if((name == NULL || !strcmp(name, "")) || (address == NULL || !strcmp(address, ""))) { - logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Host name or address is NULL\n"); + if(name == NULL || !strcmp(name, "")) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Host name is NULL\n"); return NULL; } + if(check_period && !(check_tp = find_timeperiod(check_period))) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Failed to locate check_period '%s' for host '%s'!\n", + check_period, name); + return NULL; + } + if(notification_period && !(notify_tp = find_timeperiod(notification_period))) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Failed to locate notification_period '%s' for host '%s'!\n", + notification_period, name); + return NULL; + } /* check values */ if(max_attempts <= 0) { logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Invalid max_check_attempts value for host '%s'\n", name); @@ -628,96 +641,46 @@ host *add_host(char *name, char *display_name, char *alias, char *address, char return NULL; } - /* allocate memory for a new host */ - if((new_host = (host *)calloc(1, sizeof(host))) == NULL) - return NULL; - - /* duplicate string vars */ - if((new_host->name = (char *)strdup(name)) == NULL) - result = ERROR; - if((new_host->display_name = (char *)strdup((display_name == NULL) ? name : display_name)) == NULL) - result = ERROR; - if((new_host->alias = (char *)strdup((alias == NULL) ? name : alias)) == NULL) - result = ERROR; - if((new_host->address = (char *)strdup(address)) == NULL) - result = ERROR; - if(check_period) { - if((new_host->check_period = (char *)strdup(check_period)) == NULL) - result = ERROR; - } - if(notification_period) { - if((new_host->notification_period = (char *)strdup(notification_period)) == NULL) - result = ERROR; - } - if(check_command) { - if((new_host->host_check_command = (char *)strdup(check_command)) == NULL) - result = ERROR; - } - if(event_handler) { - if((new_host->event_handler = (char *)strdup(event_handler)) == NULL) - result = ERROR; - } - if(failure_prediction_options) { - if((new_host->failure_prediction_options = (char *)strdup(failure_prediction_options)) == NULL) - result = ERROR; - } - if(notes) { - if((new_host->notes = (char *)strdup(notes)) == NULL) - result = ERROR; - } - if(notes_url) { - if((new_host->notes_url = (char *)strdup(notes_url)) == NULL) - result = ERROR; - } - if(action_url) { - if((new_host->action_url = (char *)strdup(action_url)) == NULL) - result = ERROR; - } - if(icon_image) { - if((new_host->icon_image = (char *)strdup(icon_image)) == NULL) - result = ERROR; - } - if(icon_image_alt) { - if((new_host->icon_image_alt = (char *)strdup(icon_image_alt)) == NULL) - result = ERROR; - } - if(vrml_image) { - if((new_host->vrml_image = (char *)strdup(vrml_image)) == NULL) - result = ERROR; - } - if(statusmap_image) { - if((new_host->statusmap_image = (char *)strdup(statusmap_image)) == NULL) - result = ERROR; - } + new_host = calloc(1, sizeof(*new_host)); + /* assign string vars */ + new_host->name = name; + new_host->display_name = display_name ? display_name : new_host->name; + new_host->alias = alias ? alias : new_host->name; + new_host->address = address ? address : new_host->name; + new_host->check_period = check_tp ? (char *)strdup(check_tp->name) : NULL; + new_host->notification_period = notify_tp ? (char *)strdup(notify_tp->name) : NULL; + new_host->notification_period_ptr = notify_tp; + new_host->check_period_ptr = check_tp; + new_host->check_command = check_command; + new_host->event_handler = event_handler; + new_host->notes = notes; + new_host->notes_url = notes_url; + new_host->action_url = action_url; + new_host->icon_image = icon_image; + new_host->icon_image_alt = icon_image_alt; + new_host->vrml_image = vrml_image; + new_host->statusmap_image = statusmap_image; /* duplicate non-string vars */ + new_host->hourly_value = hourly_value; new_host->max_attempts = max_attempts; new_host->check_interval = check_interval; new_host->retry_interval = retry_interval; new_host->notification_interval = notification_interval; new_host->first_notification_delay = first_notification_delay; - new_host->notify_on_recovery = (notify_up > 0) ? TRUE : FALSE; - new_host->notify_on_down = (notify_down > 0) ? TRUE : FALSE; - new_host->notify_on_unreachable = (notify_unreachable > 0) ? TRUE : FALSE; - new_host->notify_on_flapping = (notify_flapping > 0) ? TRUE : FALSE; - new_host->notify_on_downtime = (notify_downtime > 0) ? TRUE : FALSE; + new_host->notification_options = notification_options; new_host->flap_detection_enabled = (flap_detection_enabled > 0) ? TRUE : FALSE; new_host->low_flap_threshold = low_flap_threshold; new_host->high_flap_threshold = high_flap_threshold; - new_host->flap_detection_on_up = (flap_detection_on_up > 0) ? TRUE : FALSE; - new_host->flap_detection_on_down = (flap_detection_on_down > 0) ? TRUE : FALSE; - new_host->flap_detection_on_unreachable = (flap_detection_on_unreachable > 0) ? TRUE : FALSE; - new_host->stalk_on_up = (stalk_on_up > 0) ? TRUE : FALSE; - new_host->stalk_on_down = (stalk_on_down > 0) ? TRUE : FALSE; - new_host->stalk_on_unreachable = (stalk_on_unreachable > 0) ? TRUE : FALSE; + new_host->flap_detection_options = flap_detection_options; + new_host->stalking_options = stalking_options; new_host->process_performance_data = (process_perfdata > 0) ? TRUE : FALSE; new_host->check_freshness = (check_freshness > 0) ? TRUE : FALSE; new_host->freshness_threshold = freshness_threshold; new_host->checks_enabled = (checks_enabled > 0) ? TRUE : FALSE; - new_host->accept_passive_host_checks = (accept_passive_checks > 0) ? TRUE : FALSE; + new_host->accept_passive_checks = (accept_passive_checks > 0) ? TRUE : FALSE; new_host->event_handler_enabled = (event_handler_enabled > 0) ? TRUE : FALSE; - new_host->failure_prediction_enabled = (failure_prediction_enabled > 0) ? TRUE : FALSE; new_host->x_2d = x_2d; new_host->y_2d = y_2d; new_host->have_2d_coords = (have_2d_coords > 0) ? TRUE : FALSE; @@ -726,74 +689,35 @@ host *add_host(char *name, char *display_name, char *alias, char *address, char new_host->z_3d = z_3d; new_host->have_3d_coords = (have_3d_coords > 0) ? TRUE : FALSE; new_host->should_be_drawn = (should_be_drawn > 0) ? TRUE : FALSE; - new_host->obsess_over_host = (obsess_over_host > 0) ? TRUE : FALSE; + new_host->obsess = (obsess > 0) ? TRUE : FALSE; new_host->retain_status_information = (retain_status_information > 0) ? TRUE : FALSE; new_host->retain_nonstatus_information = (retain_nonstatus_information > 0) ? TRUE : FALSE; #ifdef NSCORE new_host->current_state = initial_state; - new_host->current_event_id = 0L; - new_host->last_event_id = 0L; - new_host->current_problem_id = 0L; - new_host->last_problem_id = 0L; new_host->last_state = initial_state; new_host->last_hard_state = initial_state; - new_host->check_type = HOST_CHECK_ACTIVE; - new_host->last_host_notification = (time_t)0; - new_host->next_host_notification = (time_t)0; - new_host->next_check = (time_t)0; + new_host->check_type = CHECK_TYPE_ACTIVE; new_host->should_be_scheduled = TRUE; - new_host->last_check = (time_t)0; new_host->current_attempt = (initial_state == HOST_UP) ? 1 : max_attempts; new_host->state_type = HARD_STATE; - new_host->execution_time = 0.0; - new_host->is_executing = FALSE; - new_host->latency = 0.0; - new_host->last_state_change = (time_t)0; - new_host->last_hard_state_change = (time_t)0; - new_host->last_time_up = (time_t)0; - new_host->last_time_down = (time_t)0; - new_host->last_time_unreachable = (time_t)0; - new_host->has_been_checked = FALSE; - new_host->is_being_freshened = FALSE; - new_host->problem_has_been_acknowledged = FALSE; new_host->acknowledgement_type = ACKNOWLEDGEMENT_NONE; new_host->notifications_enabled = (notifications_enabled > 0) ? TRUE : FALSE; - new_host->notified_on_down = FALSE; - new_host->notified_on_unreachable = FALSE; - new_host->current_notification_number = 0; - new_host->current_notification_id = 0L; - new_host->no_more_notifications = FALSE; - new_host->check_flapping_recovery_notification = FALSE; - new_host->scheduled_downtime_depth = 0; new_host->check_options = CHECK_OPTION_NONE; - new_host->pending_flex_downtime = 0; - for(x = 0; x < MAX_STATE_HISTORY_ENTRIES; x++) - new_host->state_history[x] = STATE_OK; - new_host->state_history_index = 0; - new_host->last_state_history_update = (time_t)0; - new_host->is_flapping = FALSE; - new_host->flapping_comment_id = 0; - new_host->percent_state_change = 0.0; - new_host->total_services = 0; - new_host->total_service_check_interval = 0L; - new_host->modified_attributes = MODATTR_NONE; - new_host->circular_path_checked = FALSE; - new_host->contains_circular_path = FALSE; #endif - /* add new host to skiplist */ + /* add new host to hash table */ if(result == OK) { - result = skiplist_insert(object_skiplists[HOST_SKIPLIST], (void *)new_host); + result = dkhash_insert(object_hash_tables[HOST_SKIPLIST], new_host->name, NULL, new_host); switch(result) { - case SKIPLIST_ERROR_DUPLICATE: + case DKHASH_EDUPE: logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Host '%s' has already been defined\n", name); result = ERROR; break; - case SKIPLIST_OK: + case DKHASH_OK: result = OK; break; default: - logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not add host '%s' to skiplist\n", name); + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not add host '%s' to hash table\n", name); result = ERROR; break; } @@ -801,41 +725,14 @@ host *add_host(char *name, char *display_name, char *alias, char *address, char /* handle errors */ if(result == ERROR) { -#ifdef NSCORE - my_free(new_host->plugin_output); - my_free(new_host->long_plugin_output); - my_free(new_host->perf_data); -#endif - my_free(new_host->statusmap_image); - my_free(new_host->vrml_image); - my_free(new_host->icon_image_alt); - my_free(new_host->icon_image); - my_free(new_host->action_url); - my_free(new_host->notes_url); - my_free(new_host->notes); - my_free(new_host->failure_prediction_options); - my_free(new_host->event_handler); - my_free(new_host->host_check_command); - my_free(new_host->notification_period); - my_free(new_host->check_period); - my_free(new_host->address); - my_free(new_host->alias); - my_free(new_host->display_name); - my_free(new_host->name); my_free(new_host); return NULL; } - /* hosts are sorted alphabetically, so add new items to tail of list */ - if(host_list == NULL) { - host_list = new_host; - host_list_tail = host_list; - } - else { - host_list_tail->next = new_host; - host_list_tail = new_host; - } - + new_host->id = num_objects.hosts++; + host_ary[new_host->id] = new_host; + if(new_host->id) + host_ary[new_host->id - 1]->next = new_host; return new_host; } @@ -879,7 +776,33 @@ hostsmember *add_parent_host_to_host(host *hst, char *host_name) { return new_hostsmember; } +servicesmember *add_parent_service_to_service(service *svc, char *host_name, char *description) { + servicesmember *sm; + if(!svc || !host_name || !description || !*host_name || !*description) + return NULL; + + if((sm = calloc(1, sizeof(*sm))) == NULL) + return NULL; + + if (strcmp(svc->host_name, host_name) == 0 && strcmp(svc->description, description) == 0) { + logit(NSLOG_CONFIG_ERROR, TRUE, + "Error: Host '%s' Service '%s' cannot be a child/parent of itself\n", + svc->host_name, svc->description); + return NULL; + } + + if ((sm->host_name = strdup(host_name)) == NULL || (sm->service_description = strdup(description)) == NULL) { + /* there was an error copying (description is NULL now) */ + my_free(sm->host_name); + free(sm); + return NULL; + } + + sm->next = svc->parents; + svc->parents = sm; + return sm; + } hostsmember *add_child_link_to_host(host *hst, host *child_ptr) { hostsmember *new_hostsmember = NULL; @@ -892,11 +815,9 @@ hostsmember *add_child_link_to_host(host *hst, host *child_ptr) { if((new_hostsmember = (hostsmember *)malloc(sizeof(hostsmember))) == NULL) return NULL; - /* initialize values */ - new_hostsmember->host_name = NULL; -#ifdef NSCORE + /* assign values */ + new_hostsmember->host_name = child_ptr->name; new_hostsmember->host_ptr = child_ptr; -#endif /* add the child entry to the host definition */ new_hostsmember->next = hst->child_hosts; @@ -918,9 +839,12 @@ servicesmember *add_service_link_to_host(host *hst, service *service_ptr) { if((new_servicesmember = (servicesmember *)calloc(1, sizeof(servicesmember))) == NULL) return NULL; - /* initialize values */ -#ifdef NSCORE + /* assign values */ + new_servicesmember->host_name = service_ptr->host_name; + new_servicesmember->service_description = service_ptr->description; new_servicesmember->service_ptr = service_ptr; +#ifndef NSCGI + hst->total_services++; #endif /* add the child entry to the host definition */ @@ -932,37 +856,59 @@ servicesmember *add_service_link_to_host(host *hst, service *service_ptr) { -/* add a new contactgroup to a host */ -contactgroupsmember *add_contactgroup_to_host(host *hst, char *group_name) { - contactgroupsmember *new_contactgroupsmember = NULL; - int result = OK; +servicesmember *add_child_link_to_service(service *svc, service *child_ptr) { + servicesmember *new_servicesmember = NULL; /* make sure we have the data we need */ - if(hst == NULL || (group_name == NULL || !strcmp(group_name, ""))) { - logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Host or contactgroup member is NULL\n"); + if(svc == NULL || child_ptr == NULL) + return NULL; + + /* allocate memory */ + if((new_servicesmember = (servicesmember *)malloc(sizeof(servicesmember))) + == NULL) return NULL; + + /* assign values */ + new_servicesmember->host_name = child_ptr->host_name; + new_servicesmember->service_description = child_ptr->description; + new_servicesmember->service_ptr = child_ptr; + + /* add the child entry to the host definition */ + new_servicesmember->next = svc->children; + svc->children = new_servicesmember; + + return new_servicesmember; + } + + + +static contactgroupsmember *add_contactgroup_to_object(contactgroupsmember **cg_list, const char *group_name) { + contactgroupsmember *cgm; + contactgroup *cg; + + if(!group_name || !*group_name) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Contact name is NULL\n"); return NULL; } - - /* allocate memory for a new member */ - if((new_contactgroupsmember = calloc(1, sizeof(contactgroupsmember))) == NULL) - return NULL; - - /* duplicate string vars */ - if((new_contactgroupsmember->group_name = (char *)strdup(group_name)) == NULL) - result = ERROR; - - /* handle errors */ - if(result == ERROR) { - my_free(new_contactgroupsmember->group_name); - my_free(new_contactgroupsmember); + if(!(cg = find_contactgroup(group_name))) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Contactgroup '%s' is not defined anywhere\n", group_name); return NULL; } + if(!(cgm = malloc(sizeof(*cgm)))) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not allocate memory for contactgroup\n"); + return NULL; + } + cgm->group_name = cg->group_name; + cgm->group_ptr = cg; + cgm->next = *cg_list; + *cg_list = cgm; - /* add the new member to the head of the member list */ - new_contactgroupsmember->next = hst->contact_groups; - hst->contact_groups = new_contactgroupsmember;; + return cgm; + } - return new_contactgroupsmember; + +/* add a new contactgroup to a host */ +contactgroupsmember *add_contactgroup_to_host(host *hst, char *group_name) { + return add_contactgroup_to_object(&hst->contact_groups, group_name); } @@ -994,41 +940,28 @@ hostgroup *add_hostgroup(char *name, char *alias, char *notes, char *notes_url, return NULL; } - /* allocate memory */ - if((new_hostgroup = (hostgroup *)calloc(1, sizeof(hostgroup))) == NULL) - return NULL; + new_hostgroup = calloc(1, sizeof(*new_hostgroup)); - /* duplicate vars */ - if((new_hostgroup->group_name = (char *)strdup(name)) == NULL) - result = ERROR; - if((new_hostgroup->alias = (char *)strdup((alias == NULL) ? name : alias)) == NULL) - result = ERROR; - if(notes) { - if((new_hostgroup->notes = (char *)strdup(notes)) == NULL) - result = ERROR; - } - if(notes_url) { - if((new_hostgroup->notes_url = (char *)strdup(notes_url)) == NULL) - result = ERROR; - } - if(action_url) { - if((new_hostgroup->action_url = (char *)strdup(action_url)) == NULL) - result = ERROR; - } + /* assign vars */ + new_hostgroup->group_name = name; + new_hostgroup->alias = alias ? alias : name; + new_hostgroup->notes = notes; + new_hostgroup->notes_url = notes_url; + new_hostgroup->action_url = action_url; - /* add new host group to skiplist */ + /* add new host group to hash table */ if(result == OK) { - result = skiplist_insert(object_skiplists[HOSTGROUP_SKIPLIST], (void *)new_hostgroup); + result = dkhash_insert(object_hash_tables[HOSTGROUP_SKIPLIST], new_hostgroup->group_name, NULL, new_hostgroup); switch(result) { - case SKIPLIST_ERROR_DUPLICATE: + case DKHASH_EDUPE: logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Hostgroup '%s' has already been defined\n", name); result = ERROR; break; - case SKIPLIST_OK: + case DKHASH_OK: result = OK; break; default: - logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not add hostgroup '%s' to skiplist\n", name); + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not add hostgroup '%s' to hash table\n", name); result = ERROR; break; } @@ -1036,22 +969,14 @@ hostgroup *add_hostgroup(char *name, char *alias, char *notes, char *notes_url, /* handle errors */ if(result == ERROR) { - my_free(new_hostgroup->alias); - my_free(new_hostgroup->group_name); - my_free(new_hostgroup); + free(new_hostgroup); return NULL; } - /* hostgroups are sorted alphabetically, so add new items to tail of list */ - if(hostgroup_list == NULL) { - hostgroup_list = new_hostgroup; - hostgroup_list_tail = hostgroup_list; - } - else { - hostgroup_list_tail->next = new_hostgroup; - hostgroup_list_tail = new_hostgroup; - } - + new_hostgroup->id = num_objects.hostgroups++; + hostgroup_ary[new_hostgroup->id] = new_hostgroup; + if(new_hostgroup->id) + hostgroup_ary[new_hostgroup->id - 1]->next = new_hostgroup; return new_hostgroup; } @@ -1061,30 +986,37 @@ hostsmember *add_host_to_hostgroup(hostgroup *temp_hostgroup, char *host_name) { hostsmember *new_member = NULL; hostsmember *last_member = NULL; hostsmember *temp_member = NULL; - int result = OK; + struct host *h; /* make sure we have the data we need */ if(temp_hostgroup == NULL || (host_name == NULL || !strcmp(host_name, ""))) { logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Hostgroup or group member is NULL\n"); return NULL; } + if (!(h = find_host(host_name))) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Failed to locate host '%s' for hostgroup '%s'\n", host_name, temp_hostgroup->group_name); + return NULL; + } /* allocate memory for a new member */ if((new_member = calloc(1, sizeof(hostsmember))) == NULL) return NULL; - /* duplicate vars */ - if((new_member->host_name = (char *)strdup(host_name)) == NULL) - result = ERROR; + /* assign vars */ + new_member->host_name = h->name; + new_member->host_ptr = h; - /* handle errors */ - if(result == ERROR) { - my_free(new_member->host_name); - my_free(new_member); - return NULL; - } + /* add (unsorted) link from the host to its group */ + prepend_object_to_objectlist(&h->hostgroups_ptr, (void *)temp_hostgroup); /* add the new member to the member list, sorted by host name */ +#ifndef NSCGI + if(use_large_installation_tweaks == TRUE) { + new_member->next = temp_hostgroup->members; + temp_hostgroup->members = new_member; + return new_member; + } +#endif last_member = temp_hostgroup->members; for(temp_member = temp_hostgroup->members; temp_member != NULL; temp_member = temp_member->next) { if(strcmp(new_member->host_name, temp_member->host_name) < 0) { @@ -1122,41 +1054,28 @@ servicegroup *add_servicegroup(char *name, char *alias, char *notes, char *notes return NULL; } - /* allocate memory */ - if((new_servicegroup = (servicegroup *)calloc(1, sizeof(servicegroup))) == NULL) - return NULL; + new_servicegroup = calloc(1, sizeof(*new_servicegroup)); /* duplicate vars */ - if((new_servicegroup->group_name = (char *)strdup(name)) == NULL) - result = ERROR; - if((new_servicegroup->alias = (char *)strdup((alias == NULL) ? name : alias)) == NULL) - result = ERROR; - if(notes) { - if((new_servicegroup->notes = (char *)strdup(notes)) == NULL) - result = ERROR; - } - if(notes_url) { - if((new_servicegroup->notes_url = (char *)strdup(notes_url)) == NULL) - result = ERROR; - } - if(action_url) { - if((new_servicegroup->action_url = (char *)strdup(action_url)) == NULL) - result = ERROR; - } + new_servicegroup->group_name = name; + new_servicegroup->alias = alias ? alias : name; + new_servicegroup->notes = notes; + new_servicegroup->notes_url = notes_url; + new_servicegroup->action_url = action_url; - /* add new service group to skiplist */ + /* add new service group to hash table */ if(result == OK) { - result = skiplist_insert(object_skiplists[SERVICEGROUP_SKIPLIST], (void *)new_servicegroup); + result = dkhash_insert(object_hash_tables[SERVICEGROUP_SKIPLIST], new_servicegroup->group_name, NULL, new_servicegroup); switch(result) { - case SKIPLIST_ERROR_DUPLICATE: + case DKHASH_EDUPE: logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Servicegroup '%s' has already been defined\n", name); result = ERROR; break; - case SKIPLIST_OK: + case DKHASH_OK: result = OK; break; default: - logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not add servicegroup '%s' to skiplist\n", name); + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not add servicegroup '%s' to hash table\n", name); result = ERROR; break; } @@ -1164,22 +1083,14 @@ servicegroup *add_servicegroup(char *name, char *alias, char *notes, char *notes /* handle errors */ if(result == ERROR) { - my_free(new_servicegroup->alias); - my_free(new_servicegroup->group_name); my_free(new_servicegroup); return NULL; } - /* servicegroups are sorted alphabetically, so add new items to tail of list */ - if(servicegroup_list == NULL) { - servicegroup_list = new_servicegroup; - servicegroup_list_tail = servicegroup_list; - } - else { - servicegroup_list_tail->next = new_servicegroup; - servicegroup_list_tail = new_servicegroup; - } - + new_servicegroup->id = num_objects.servicegroups++; + servicegroup_ary[new_servicegroup->id] = new_servicegroup; + if(new_servicegroup->id) + servicegroup_ary[new_servicegroup->id - 1]->next = new_servicegroup; return new_servicegroup; } @@ -1189,33 +1100,42 @@ servicesmember *add_service_to_servicegroup(servicegroup *temp_servicegroup, cha servicesmember *new_member = NULL; servicesmember *last_member = NULL; servicesmember *temp_member = NULL; - int result = OK; + struct service *svc; /* make sure we have the data we need */ if(temp_servicegroup == NULL || (host_name == NULL || !strcmp(host_name, "")) || (svc_description == NULL || !strcmp(svc_description, ""))) { logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Servicegroup or group member is NULL\n"); return NULL; } + if (!(svc = find_service(host_name, svc_description))) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Failed to locate service '%s' on host '%s' for servicegroup '%s'\n", svc_description, host_name, temp_servicegroup->group_name); + return NULL; + } /* allocate memory for a new member */ if((new_member = calloc(1, sizeof(servicesmember))) == NULL) return NULL; - /* duplicate vars */ - if((new_member->host_name = (char *)strdup(host_name)) == NULL) - result = ERROR; - if((new_member->service_description = (char *)strdup(svc_description)) == NULL) - result = ERROR; + /* assign vars */ + new_member->host_name = svc->host_name; + new_member->service_description = svc->description; + new_member->service_ptr = svc; - /* handle errors */ - if(result == ERROR) { - my_free(new_member->service_description); - my_free(new_member->host_name); - my_free(new_member); - return NULL; + /* add (unsorted) link from the service to its groups */ + prepend_object_to_objectlist(&svc->servicegroups_ptr, temp_servicegroup); + + /* + * add new member to member list, sorted by host name then + * service description, unless we're a large installation, in + * which case insertion-sorting will take far too long + */ +#ifndef NSCGI + if(use_large_installation_tweaks == TRUE) { + new_member->next = temp_servicegroup->members; + temp_servicegroup->members = new_member; + return new_member; } - - /* add new member to member list, sorted by host name then service description */ +#endif last_member = temp_servicegroup->members; for(temp_member = temp_servicegroup->members; temp_member != NULL; temp_member = temp_member->next) { @@ -1254,92 +1174,68 @@ servicesmember *add_service_to_servicegroup(servicegroup *temp_servicegroup, cha /* add a new contact to the list in memory */ -contact *add_contact(char *name, char *alias, char *email, char *pager, char **addresses, char *svc_notification_period, char *host_notification_period, int notify_service_ok, int notify_service_critical, int notify_service_warning, int notify_service_unknown, int notify_service_flapping, int notify_service_downtime, int notify_host_up, int notify_host_down, int notify_host_unreachable, int notify_host_flapping, int notify_host_downtime, int host_notifications_enabled, int service_notifications_enabled, int can_submit_commands, int retain_status_information, int retain_nonstatus_information) { +contact *add_contact(char *name, char *alias, char *email, char *pager, char **addresses, char *svc_notification_period, char *host_notification_period, int service_notification_options, int host_notification_options, int host_notifications_enabled, int service_notifications_enabled, int can_submit_commands, int retain_status_information, int retain_nonstatus_information, unsigned int minimum_value) { contact *new_contact = NULL; + timeperiod *htp = NULL, *stp = NULL; int x = 0; int result = OK; /* make sure we have the data we need */ - if(name == NULL || !strcmp(name, "")) { + if(name == NULL || !*name) { logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Contact name is NULL\n"); return NULL; } + if(svc_notification_period && !(stp = find_timeperiod(svc_notification_period))) { + logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Service notification period '%s' specified for contact '%s' is not defined anywhere!\n", + svc_notification_period, name); + return NULL; + } + if(host_notification_period && !(htp = find_timeperiod(host_notification_period))) { + logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Host notification period '%s' specified for contact '%s' is not defined anywhere!\n", + host_notification_period, name); + return NULL; + } - /* allocate memory for a new contact */ - if((new_contact = (contact *)calloc(1, sizeof(contact))) == NULL) + + new_contact = calloc(1, sizeof(*new_contact)); + if(!new_contact) return NULL; - /* duplicate vars */ - if((new_contact->name = (char *)strdup(name)) == NULL) - result = ERROR; - if((new_contact->alias = (char *)strdup((alias == NULL) ? name : alias)) == NULL) - result = ERROR; - if(email) { - if((new_contact->email = (char *)strdup(email)) == NULL) - result = ERROR; - } - if(pager) { - if((new_contact->pager = (char *)strdup(pager)) == NULL) - result = ERROR; - } - if(svc_notification_period) { - if((new_contact->service_notification_period = (char *)strdup(svc_notification_period)) == NULL) - result = ERROR; - } - if(host_notification_period) { - if((new_contact->host_notification_period = (char *)strdup(host_notification_period)) == NULL) - result = ERROR; - } + new_contact->host_notification_period = htp ? (char *)strdup(htp->name) : NULL; + new_contact->service_notification_period = stp ? (char *)strdup(stp->name) : NULL; + new_contact->host_notification_period_ptr = htp; + new_contact->service_notification_period_ptr = stp; + new_contact->name = name; + new_contact->alias = alias ? alias : name; + new_contact->email = email; + new_contact->pager = pager; if(addresses) { - for(x = 0; x < MAX_CONTACT_ADDRESSES; x++) { - if(addresses[x]) { - if((new_contact->address[x] = (char *)strdup(addresses[x])) == NULL) - result = ERROR; - } - } + for(x = 0; x < MAX_CONTACT_ADDRESSES; x++) + new_contact->address[x] = addresses[x]; } - new_contact->notify_on_service_recovery = (notify_service_ok > 0) ? TRUE : FALSE; - new_contact->notify_on_service_critical = (notify_service_critical > 0) ? TRUE : FALSE; - new_contact->notify_on_service_warning = (notify_service_warning > 0) ? TRUE : FALSE; - new_contact->notify_on_service_unknown = (notify_service_unknown > 0) ? TRUE : FALSE; - new_contact->notify_on_service_flapping = (notify_service_flapping > 0) ? TRUE : FALSE; - new_contact->notify_on_service_downtime = (notify_service_downtime > 0) ? TRUE : FALSE; - new_contact->notify_on_host_recovery = (notify_host_up > 0) ? TRUE : FALSE; - new_contact->notify_on_host_down = (notify_host_down > 0) ? TRUE : FALSE; - new_contact->notify_on_host_unreachable = (notify_host_unreachable > 0) ? TRUE : FALSE; - new_contact->notify_on_host_flapping = (notify_host_flapping > 0) ? TRUE : FALSE; - new_contact->notify_on_host_downtime = (notify_host_downtime > 0) ? TRUE : FALSE; + new_contact->minimum_value = minimum_value; + new_contact->service_notification_options = service_notification_options; + new_contact->host_notification_options = host_notification_options; new_contact->host_notifications_enabled = (host_notifications_enabled > 0) ? TRUE : FALSE; new_contact->service_notifications_enabled = (service_notifications_enabled > 0) ? TRUE : FALSE; new_contact->can_submit_commands = (can_submit_commands > 0) ? TRUE : FALSE; new_contact->retain_status_information = (retain_status_information > 0) ? TRUE : FALSE; new_contact->retain_nonstatus_information = (retain_nonstatus_information > 0) ? TRUE : FALSE; -#ifdef NSCORE - new_contact->last_host_notification = (time_t)0L; - new_contact->last_service_notification = (time_t)0L; - new_contact->modified_attributes = MODATTR_NONE; - new_contact->modified_host_attributes = MODATTR_NONE; - new_contact->modified_service_attributes = MODATTR_NONE; - new_contact->host_notification_period_ptr = NULL; - new_contact->service_notification_period_ptr = NULL; - new_contact->contactgroups_ptr = NULL; -#endif - - /* add new contact to skiplist */ + /* add new contact to hash table */ if(result == OK) { - result = skiplist_insert(object_skiplists[CONTACT_SKIPLIST], (void *)new_contact); + result = dkhash_insert(object_hash_tables[CONTACT_SKIPLIST], new_contact->name, NULL, new_contact); switch(result) { - case SKIPLIST_ERROR_DUPLICATE: + case DKHASH_EDUPE: logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Contact '%s' has already been defined\n", name); result = ERROR; break; - case SKIPLIST_OK: + case DKHASH_OK: result = OK; break; default: - logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not add contact '%s' to skiplist\n", name); + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not add contact '%s' to hash table\n", name); result = ERROR; break; } @@ -1347,28 +1243,14 @@ contact *add_contact(char *name, char *alias, char *email, char *pager, char **a /* handle errors */ if(result == ERROR) { - for(x = 0; x < MAX_CONTACT_ADDRESSES; x++) - my_free(new_contact->address[x]); - my_free(new_contact->name); - my_free(new_contact->alias); - my_free(new_contact->email); - my_free(new_contact->pager); - my_free(new_contact->service_notification_period); - my_free(new_contact->host_notification_period); - my_free(new_contact); + free(new_contact); return NULL; } - /* contacts are sorted alphabetically, so add new items to tail of list */ - if(contact_list == NULL) { - contact_list = new_contact; - contact_list_tail = contact_list; - } - else { - contact_list_tail->next = new_contact; - contact_list_tail = new_contact; - } - + new_contact->id = num_objects.contacts++; + contact_ary[new_contact->id] = new_contact; + if(new_contact->id) + contact_ary[new_contact->id - 1]->next = new_contact; return new_contact; } @@ -1463,29 +1345,27 @@ contactgroup *add_contactgroup(char *name, char *alias) { return NULL; } - /* allocate memory for a new contactgroup entry */ - if((new_contactgroup = calloc(1, sizeof(contactgroup))) == NULL) + new_contactgroup = calloc(1, sizeof(*new_contactgroup)); + if(!new_contactgroup) return NULL; - /* duplicate vars */ - if((new_contactgroup->group_name = (char *)strdup(name)) == NULL) - result = ERROR; - if((new_contactgroup->alias = (char *)strdup((alias == NULL) ? name : alias)) == NULL) - result = ERROR; + /* assign vars */ + new_contactgroup->group_name = name; + new_contactgroup->alias = alias ? alias : name; - /* add new contact group to skiplist */ + /* add new contact group to hash table */ if(result == OK) { - result = skiplist_insert(object_skiplists[CONTACTGROUP_SKIPLIST], (void *)new_contactgroup); + result = dkhash_insert(object_hash_tables[CONTACTGROUP_SKIPLIST], new_contactgroup->group_name, NULL, new_contactgroup); switch(result) { - case SKIPLIST_ERROR_DUPLICATE: + case DKHASH_EDUPE: logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Contactgroup '%s' has already been defined\n", name); result = ERROR; break; - case SKIPLIST_OK: + case DKHASH_OK: result = OK; break; default: - logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not add contactgroup '%s' to skiplist\n", name); + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not add contactgroup '%s' to hash table\n", name); result = ERROR; break; } @@ -1493,22 +1373,14 @@ contactgroup *add_contactgroup(char *name, char *alias) { /* handle errors */ if(result == ERROR) { - my_free(new_contactgroup->alias); - my_free(new_contactgroup->group_name); - my_free(new_contactgroup); + free(new_contactgroup); return NULL; } - /* contactgroups are sorted alphabetically, so add new items to tail of list */ - if(contactgroup_list == NULL) { - contactgroup_list = new_contactgroup; - contactgroup_list_tail = contactgroup_list; - } - else { - contactgroup_list_tail->next = new_contactgroup; - contactgroup_list_tail = new_contactgroup; - } - + new_contactgroup->id = num_objects.contactgroups++; + contactgroup_ary[new_contactgroup->id] = new_contactgroup; + if(new_contactgroup->id) + contactgroup_ary[new_contactgroup->id - 1]->next = new_contactgroup; return new_contactgroup; } @@ -1517,7 +1389,7 @@ contactgroup *add_contactgroup(char *name, char *alias) { /* add a new member to a contact group */ contactsmember *add_contact_to_contactgroup(contactgroup *grp, char *contact_name) { contactsmember *new_contactsmember = NULL; - int result = OK; + struct contact *c; /* make sure we have the data we need */ if(grp == NULL || (contact_name == NULL || !strcmp(contact_name, ""))) { @@ -1525,43 +1397,57 @@ contactsmember *add_contact_to_contactgroup(contactgroup *grp, char *contact_nam return NULL; } + if (!(c = find_contact(contact_name))) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Failed to locate contact '%s' for contactgroup '%s'\n", contact_name, grp->group_name); + return NULL; + } + /* allocate memory for a new member */ if((new_contactsmember = calloc(1, sizeof(contactsmember))) == NULL) return NULL; - /* duplicate vars */ - if((new_contactsmember->contact_name = (char *)strdup(contact_name)) == NULL) - result = ERROR; - - /* handle errors */ - if(result == ERROR) { - my_free(new_contactsmember->contact_name); - my_free(new_contactsmember); - return NULL; - } + /* assign vars */ + new_contactsmember->contact_name = c->name; + new_contactsmember->contact_ptr = c; /* add the new member to the head of the member list */ new_contactsmember->next = grp->members; grp->members = new_contactsmember; + prepend_object_to_objectlist(&c->contactgroups_ptr, (void *)grp); + return new_contactsmember; } /* add a new service to the list in memory */ -service *add_service(char *host_name, char *description, char *display_name, char *check_period, int initial_state, int max_attempts, int parallelize, int accept_passive_checks, double check_interval, double retry_interval, double notification_interval, double first_notification_delay, char *notification_period, int notify_recovery, int notify_unknown, int notify_warning, int notify_critical, int notify_flapping, int notify_downtime, int notifications_enabled, int is_volatile, char *event_handler, int event_handler_enabled, char *check_command, int checks_enabled, int flap_detection_enabled, double low_flap_threshold, double high_flap_threshold, int flap_detection_on_ok, int flap_detection_on_warning, int flap_detection_on_unknown, int flap_detection_on_critical, int stalk_on_ok, int stalk_on_warning, int stalk_on_unknown, int stalk_on_critical, int process_perfdata, int failure_prediction_enabled, char *failure_prediction_options, int check_freshness, int freshness_threshold, char *notes, char *notes_url, char *action_url, char *icon_image, char *icon_image_alt, int retain_status_information, int retain_nonstatus_information, int obsess_over_service) { +service *add_service(char *host_name, char *description, char *display_name, char *check_period, int initial_state, int max_attempts, int parallelize, int accept_passive_checks, double check_interval, double retry_interval, double notification_interval, double first_notification_delay, char *notification_period, int notification_options, int notifications_enabled, int is_volatile, char *event_handler, int event_handler_enabled, char *check_command, int checks_enabled, int flap_detection_enabled, double low_flap_threshold, double high_flap_threshold, int flap_detection_options, int stalking_options, int process_perfdata, int check_freshness, int freshness_threshold, char *notes, char *notes_url, char *action_url, char *icon_image, char *icon_image_alt, int retain_status_information, int retain_nonstatus_information, int obsess, unsigned int hourly_value) { + host *h; + timeperiod *cp = NULL, *np = NULL; service *new_service = NULL; int result = OK; -#ifdef NSCORE - int x = 0; -#endif /* make sure we have everything we need */ - if((host_name == NULL || !strcmp(host_name, "")) || (description == NULL || !strcmp(description, "")) || (check_command == NULL || !strcmp(check_command, ""))) { + if(host_name == NULL || description == NULL || !*description || check_command == NULL || !*check_command) { logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Service description, host name, or check command is NULL\n"); return NULL; } + if (!(h = find_host(host_name))) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Unable to locate host '%s' for service '%s'\n", + host_name, description); + return NULL; + } + if(notification_period && !(np = find_timeperiod(notification_period))) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: notification_period '%s' for service '%s' on host '%s' could not be found!\n", + notification_period, description, host_name); + return NULL; + } + if(check_period && !(cp = find_timeperiod(check_period))) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: check_period '%s' for service '%s' on host '%s' not found!\n", + check_period, description, host_name); + return NULL; + } /* check values */ if(max_attempts <= 0 || check_interval < 0 || retry_interval <= 0 || notification_interval < 0) { @@ -1575,34 +1461,32 @@ service *add_service(char *host_name, char *description, char *display_name, cha } /* allocate memory */ - if((new_service = (service *)calloc(1, sizeof(service))) == NULL) + new_service = calloc(1, sizeof(*new_service)); + if(!new_service) return NULL; - /* duplicate vars */ - if((new_service->host_name = (char *)strdup(host_name)) == NULL) - result = ERROR; + /* duplicate vars, but assign what we can */ + new_service->notification_period_ptr = np; + new_service->check_period_ptr = cp; + new_service->host_ptr = h; + new_service->check_period = cp ? (char *)strdup(cp->name) : NULL; + new_service->notification_period = np ? (char *)strdup(np->name) : NULL; + new_service->host_name = h->name; if((new_service->description = (char *)strdup(description)) == NULL) result = ERROR; - if((new_service->display_name = (char *)strdup((display_name == NULL) ? description : display_name)) == NULL) - result = ERROR; - if((new_service->service_check_command = (char *)strdup(check_command)) == NULL) + if(display_name) { + if((new_service->display_name = (char *)strdup(display_name)) == NULL) + result = ERROR; + } + else { + new_service->display_name = new_service->description; + } + if((new_service->check_command = (char *)strdup(check_command)) == NULL) result = ERROR; if(event_handler) { if((new_service->event_handler = (char *)strdup(event_handler)) == NULL) result = ERROR; } - if(notification_period) { - if((new_service->notification_period = (char *)strdup(notification_period)) == NULL) - result = ERROR; - } - if(check_period) { - if((new_service->check_period = (char *)strdup(check_period)) == NULL) - result = ERROR; - } - if(failure_prediction_options) { - if((new_service->failure_prediction_options = (char *)strdup(failure_prediction_options)) == NULL) - result = ERROR; - } if(notes) { if((new_service->notes = (char *)strdup(notes)) == NULL) result = ERROR; @@ -1624,103 +1508,55 @@ service *add_service(char *host_name, char *description, char *display_name, cha result = ERROR; } + new_service->hourly_value = hourly_value; new_service->check_interval = check_interval; new_service->retry_interval = retry_interval; new_service->max_attempts = max_attempts; new_service->parallelize = (parallelize > 0) ? TRUE : FALSE; new_service->notification_interval = notification_interval; new_service->first_notification_delay = first_notification_delay; - new_service->notify_on_unknown = (notify_unknown > 0) ? TRUE : FALSE; - new_service->notify_on_warning = (notify_warning > 0) ? TRUE : FALSE; - new_service->notify_on_critical = (notify_critical > 0) ? TRUE : FALSE; - new_service->notify_on_recovery = (notify_recovery > 0) ? TRUE : FALSE; - new_service->notify_on_flapping = (notify_flapping > 0) ? TRUE : FALSE; - new_service->notify_on_downtime = (notify_downtime > 0) ? TRUE : FALSE; + new_service->notification_options = notification_options; new_service->is_volatile = (is_volatile > 0) ? TRUE : FALSE; new_service->flap_detection_enabled = (flap_detection_enabled > 0) ? TRUE : FALSE; new_service->low_flap_threshold = low_flap_threshold; new_service->high_flap_threshold = high_flap_threshold; - new_service->flap_detection_on_ok = (flap_detection_on_ok > 0) ? TRUE : FALSE; - new_service->flap_detection_on_warning = (flap_detection_on_warning > 0) ? TRUE : FALSE; - new_service->flap_detection_on_unknown = (flap_detection_on_unknown > 0) ? TRUE : FALSE; - new_service->flap_detection_on_critical = (flap_detection_on_critical > 0) ? TRUE : FALSE; - new_service->stalk_on_ok = (stalk_on_ok > 0) ? TRUE : FALSE; - new_service->stalk_on_warning = (stalk_on_warning > 0) ? TRUE : FALSE; - new_service->stalk_on_unknown = (stalk_on_unknown > 0) ? TRUE : FALSE; - new_service->stalk_on_critical = (stalk_on_critical > 0) ? TRUE : FALSE; + new_service->flap_detection_options = flap_detection_options; + new_service->stalking_options = stalking_options; new_service->process_performance_data = (process_perfdata > 0) ? TRUE : FALSE; new_service->check_freshness = (check_freshness > 0) ? TRUE : FALSE; new_service->freshness_threshold = freshness_threshold; - new_service->accept_passive_service_checks = (accept_passive_checks > 0) ? TRUE : FALSE; + new_service->accept_passive_checks = (accept_passive_checks > 0) ? TRUE : FALSE; new_service->event_handler_enabled = (event_handler_enabled > 0) ? TRUE : FALSE; new_service->checks_enabled = (checks_enabled > 0) ? TRUE : FALSE; new_service->retain_status_information = (retain_status_information > 0) ? TRUE : FALSE; new_service->retain_nonstatus_information = (retain_nonstatus_information > 0) ? TRUE : FALSE; new_service->notifications_enabled = (notifications_enabled > 0) ? TRUE : FALSE; - new_service->obsess_over_service = (obsess_over_service > 0) ? TRUE : FALSE; - new_service->failure_prediction_enabled = (failure_prediction_enabled > 0) ? TRUE : FALSE; + new_service->obsess = (obsess > 0) ? TRUE : FALSE; #ifdef NSCORE - new_service->problem_has_been_acknowledged = FALSE; new_service->acknowledgement_type = ACKNOWLEDGEMENT_NONE; - new_service->check_type = SERVICE_CHECK_ACTIVE; + new_service->check_type = CHECK_TYPE_ACTIVE; new_service->current_attempt = (initial_state == STATE_OK) ? 1 : max_attempts; new_service->current_state = initial_state; - new_service->current_event_id = 0L; - new_service->last_event_id = 0L; - new_service->current_problem_id = 0L; - new_service->last_problem_id = 0L; new_service->last_state = initial_state; new_service->last_hard_state = initial_state; new_service->state_type = HARD_STATE; - new_service->host_problem_at_last_check = FALSE; - new_service->check_flapping_recovery_notification = FALSE; - new_service->next_check = (time_t)0; new_service->should_be_scheduled = TRUE; - new_service->last_check = (time_t)0; - new_service->last_notification = (time_t)0; - new_service->next_notification = (time_t)0; - new_service->no_more_notifications = FALSE; - new_service->last_state_change = (time_t)0; - new_service->last_hard_state_change = (time_t)0; - new_service->last_time_ok = (time_t)0; - new_service->last_time_warning = (time_t)0; - new_service->last_time_unknown = (time_t)0; - new_service->last_time_critical = (time_t)0; - new_service->has_been_checked = FALSE; - new_service->is_being_freshened = FALSE; - new_service->notified_on_unknown = FALSE; - new_service->notified_on_warning = FALSE; - new_service->notified_on_critical = FALSE; - new_service->current_notification_number = 0; - new_service->current_notification_id = 0L; - new_service->latency = 0.0; - new_service->execution_time = 0.0; - new_service->is_executing = FALSE; new_service->check_options = CHECK_OPTION_NONE; - new_service->scheduled_downtime_depth = 0; - new_service->pending_flex_downtime = 0; - for(x = 0; x < MAX_STATE_HISTORY_ENTRIES; x++) - new_service->state_history[x] = STATE_OK; - new_service->state_history_index = 0; - new_service->is_flapping = FALSE; - new_service->flapping_comment_id = 0; - new_service->percent_state_change = 0.0; - new_service->modified_attributes = MODATTR_NONE; #endif - /* add new service to skiplist */ + /* add new service to hash table */ if(result == OK) { - result = skiplist_insert(object_skiplists[SERVICE_SKIPLIST], (void *)new_service); + result = dkhash_insert(object_hash_tables[SERVICE_SKIPLIST], new_service->host_name, new_service->description, new_service); switch(result) { - case SKIPLIST_ERROR_DUPLICATE: + case DKHASH_EDUPE: logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Service '%s' on host '%s' has already been defined\n", description, host_name); result = ERROR; break; - case SKIPLIST_OK: + case DKHASH_OK: result = OK; break; default: - logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not add service '%s' on host '%s' to skiplist\n", description, host_name); + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not add service '%s' on host '%s' to hash table\n", description, host_name); result = ERROR; break; } @@ -1733,27 +1569,20 @@ service *add_service(char *host_name, char *description, char *display_name, cha my_free(new_service->plugin_output); my_free(new_service->long_plugin_output); #endif - my_free(new_service->failure_prediction_options); - my_free(new_service->notification_period); my_free(new_service->event_handler); - my_free(new_service->service_check_command); + my_free(new_service->check_command); my_free(new_service->description); - my_free(new_service->host_name); - my_free(new_service->display_name); - my_free(new_service); + if(display_name) + my_free(new_service->display_name); return NULL; } - /* services are sorted alphabetically, so add new items to tail of list */ - if(service_list == NULL) { - service_list = new_service; - service_list_tail = service_list; - } - else { - service_list_tail->next = new_service; - service_list_tail = new_service; - } + add_service_link_to_host(h, new_service); + new_service->id = num_objects.services++; + service_ary[new_service->id] = new_service; + if(new_service->id) + service_ary[new_service->id - 1]->next = new_service; return new_service; } @@ -1761,34 +1590,7 @@ service *add_service(char *host_name, char *description, char *display_name, cha /* adds a contact group to a service */ contactgroupsmember *add_contactgroup_to_service(service *svc, char *group_name) { - contactgroupsmember *new_contactgroupsmember = NULL; - int result = OK; - - /* bail out if we weren't given the data we need */ - if(svc == NULL || (group_name == NULL || !strcmp(group_name, ""))) { - logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Service or contactgroup name is NULL\n"); - return NULL; - } - - /* allocate memory for the contactgroups member */ - if((new_contactgroupsmember = calloc(1, sizeof(contactgroupsmember))) == NULL) - return NULL; - - /* duplicate vars */ - if((new_contactgroupsmember->group_name = (char *)strdup(group_name)) == NULL) - result = ERROR; - - /* handle errors */ - if(result == ERROR) { - my_free(new_contactgroupsmember); - return NULL; - } - - /* add this contactgroup to the service */ - new_contactgroupsmember->next = svc->contact_groups; - svc->contact_groups = new_contactgroupsmember; - - return new_contactgroupsmember; + return add_contactgroup_to_object(&svc->contact_groups, group_name); } @@ -1821,28 +1623,27 @@ command *add_command(char *name, char *value) { } /* allocate memory for the new command */ - if((new_command = (command *)calloc(1, sizeof(command))) == NULL) + new_command = calloc(1, sizeof(*new_command)); + if(!new_command) return NULL; - /* duplicate vars */ - if((new_command->name = (char *)strdup(name)) == NULL) - result = ERROR; - if((new_command->command_line = (char *)strdup(value)) == NULL) - result = ERROR; + /* assign vars */ + new_command->name = name; + new_command->command_line = value; - /* add new command to skiplist */ + /* add new command to hash table */ if(result == OK) { - result = skiplist_insert(object_skiplists[COMMAND_SKIPLIST], (void *)new_command); + result = dkhash_insert(object_hash_tables[COMMAND_SKIPLIST], new_command->name, NULL, new_command); switch(result) { - case SKIPLIST_ERROR_DUPLICATE: + case DKHASH_EDUPE: logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Command '%s' has already been defined\n", name); result = ERROR; break; - case SKIPLIST_OK: + case DKHASH_OK: result = OK; break; default: - logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not add command '%s' to skiplist\n", name); + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not add command '%s' to hash table\n", name); result = ERROR; break; } @@ -1850,97 +1651,66 @@ command *add_command(char *name, char *value) { /* handle errors */ if(result == ERROR) { - my_free(new_command->command_line); - my_free(new_command->name); my_free(new_command); return NULL; } - /* commands are sorted alphabetically, so add new items to tail of list */ - if(command_list == NULL) { - command_list = new_command; - command_list_tail = command_list; - } - else { - command_list_tail->next = new_command; - command_list_tail = new_command; - } - + new_command->id = num_objects.commands++; + command_ary[new_command->id] = new_command; + if(new_command->id) + command_ary[new_command->id - 1]->next = new_command; return new_command; } /* add a new service escalation to the list in memory */ -serviceescalation *add_serviceescalation(char *host_name, char *description, int first_notification, int last_notification, double notification_interval, char *escalation_period, int escalate_on_warning, int escalate_on_unknown, int escalate_on_critical, int escalate_on_recovery) { +serviceescalation *add_serviceescalation(char *host_name, char *description, int first_notification, int last_notification, double notification_interval, char *escalation_period, int escalation_options) { serviceescalation *new_serviceescalation = NULL; - int result = OK; + service *svc; + timeperiod *tp = NULL; /* make sure we have the data we need */ - if((host_name == NULL || !strcmp(host_name, "")) || (description == NULL || !strcmp(description, ""))) { + if(host_name == NULL || !*host_name || description == NULL || !*description) { logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Service escalation host name or description is NULL\n"); return NULL; } + if(!(svc = find_service(host_name, description))) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Service '%s' on host '%s' has an escalation but is not defined anywhere!\n", + host_name, description); + return NULL; + } + if (escalation_period && !(tp = find_timeperiod(escalation_period))) { + logit(NSLOG_VERIFICATION_ERROR, TRUE, "Error: Escalation period '%s' specified in service escalation for service '%s' on host '%s' is not defined anywhere!\n", + escalation_period, description, host_name); + return NULL ; + } -#ifdef TEST - printf("NEW SVC ESCALATION: %s/%s = %d/%d/%.3f\n", host_name, description, first_notification, last_notification, notification_interval); -#endif - - /* allocate memory for a new service escalation entry */ - if((new_serviceescalation = calloc(1, sizeof(serviceescalation))) == NULL) + new_serviceescalation = calloc(1, sizeof(*new_serviceescalation)); + if(!new_serviceescalation) return NULL; - /* duplicate vars */ - if((new_serviceescalation->host_name = (char *)strdup(host_name)) == NULL) - result = ERROR; - if((new_serviceescalation->description = (char *)strdup(description)) == NULL) - result = ERROR; - if(escalation_period) { - if((new_serviceescalation->escalation_period = (char *)strdup(escalation_period)) == NULL) - result = ERROR; + if(add_object_to_objectlist(&svc->escalation_list, new_serviceescalation) != OK) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Could not add escalation to service '%s' on host '%s'\n", + svc->host_name, svc->description); + return NULL; } + /* assign vars. object names are immutable, so no need to copy */ + new_serviceescalation->host_name = svc->host_name; + new_serviceescalation->description = svc->description; + new_serviceescalation->service_ptr = svc; + new_serviceescalation->escalation_period_ptr = tp; + if(tp) + new_serviceescalation->escalation_period = (char *)strdup(tp->name); + new_serviceescalation->first_notification = first_notification; new_serviceescalation->last_notification = last_notification; new_serviceescalation->notification_interval = (notification_interval <= 0) ? 0 : notification_interval; - new_serviceescalation->escalate_on_recovery = (escalate_on_recovery > 0) ? TRUE : FALSE; - new_serviceescalation->escalate_on_warning = (escalate_on_warning > 0) ? TRUE : FALSE; - new_serviceescalation->escalate_on_unknown = (escalate_on_unknown > 0) ? TRUE : FALSE; - new_serviceescalation->escalate_on_critical = (escalate_on_critical > 0) ? TRUE : FALSE; - - /* add new serviceescalation to skiplist */ - if(result == OK) { - result = skiplist_insert(object_skiplists[SERVICEESCALATION_SKIPLIST], (void *)new_serviceescalation); - switch(result) { - case SKIPLIST_OK: - result = OK; - break; - default: - logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not add escalation for service '%s' on host '%s' to skiplist\n", description, host_name); - result = ERROR; - break; - } - } - - /* handle errors */ - if(result == ERROR) { - my_free(new_serviceescalation->host_name); - my_free(new_serviceescalation->description); - my_free(new_serviceescalation->escalation_period); - my_free(new_serviceescalation); - return NULL; - } - - /* service escalations are sorted alphabetically, so add new items to tail of list */ - if(serviceescalation_list == NULL) { - serviceescalation_list = new_serviceescalation; - serviceescalation_list_tail = serviceescalation_list; - } - else { - serviceescalation_list_tail->next = new_serviceescalation; - serviceescalation_list_tail = new_serviceescalation; - } + new_serviceescalation->escalation_options = escalation_options; + new_serviceescalation->id = num_objects.serviceescalations++; + serviceescalation_ary[new_serviceescalation->id] = new_serviceescalation; return new_serviceescalation; } @@ -1948,35 +1718,7 @@ serviceescalation *add_serviceescalation(char *host_name, char *description, int /* adds a contact group to a service escalation */ contactgroupsmember *add_contactgroup_to_serviceescalation(serviceescalation *se, char *group_name) { - contactgroupsmember *new_contactgroupsmember = NULL; - int result = OK; - - /* bail out if we weren't given the data we need */ - if(se == NULL || (group_name == NULL || !strcmp(group_name, ""))) { - logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Service escalation or contactgroup name is NULL\n"); - return NULL; - } - - /* allocate memory for the contactgroups member */ - if((new_contactgroupsmember = (contactgroupsmember *)calloc(1, sizeof(contactgroupsmember))) == NULL) - return NULL; - - /* duplicate vars */ - if((new_contactgroupsmember->group_name = (char *)strdup(group_name)) == NULL) - result = ERROR; - - /* handle errors */ - if(result == ERROR) { - my_free(new_contactgroupsmember->group_name); - my_free(new_contactgroupsmember); - return NULL; - } - - /* add this contactgroup to the service escalation */ - new_contactgroupsmember->next = se->contact_groups; - se->contact_groups = new_contactgroupsmember; - - return new_contactgroupsmember; + return add_contactgroup_to_object(&se->contact_groups, group_name); } @@ -1990,227 +1732,175 @@ contactsmember *add_contact_to_serviceescalation(serviceescalation *se, char *co /* adds a service dependency definition */ -servicedependency *add_service_dependency(char *dependent_host_name, char *dependent_service_description, char *host_name, char *service_description, int dependency_type, int inherits_parent, int fail_on_ok, int fail_on_warning, int fail_on_unknown, int fail_on_critical, int fail_on_pending, char *dependency_period) { +servicedependency *add_service_dependency(char *dependent_host_name, char *dependent_service_description, char *host_name, char *service_description, int dependency_type, int inherits_parent, int failure_options, char *dependency_period) { servicedependency *new_servicedependency = NULL; - int result = OK; + service *parent, *child; + timeperiod *tp = NULL; + int result; /* make sure we have what we need */ - if((host_name == NULL || !strcmp(host_name, "")) || (service_description == NULL || !strcmp(service_description, ""))) { - logit(NSLOG_CONFIG_ERROR, TRUE, "Error: NULL master service description/host name in service dependency definition\n"); + parent = find_service(host_name, service_description); + if(!parent) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Master service '%s' on host '%s' is not defined anywhere!\n", + service_description, host_name); return NULL; } - if((dependent_host_name == NULL || !strcmp(dependent_host_name, "")) || (dependent_service_description == NULL || !strcmp(dependent_service_description, ""))) { - logit(NSLOG_CONFIG_ERROR, TRUE, "Error: NULL dependent service description/host name in service dependency definition\n"); + child = find_service(dependent_host_name, dependent_service_description); + if(!child) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Dependent service '%s' on host '%s' is not defined anywhere!\n", + dependent_service_description, dependent_host_name); + return NULL; + } + if (dependency_period && !(tp = find_timeperiod(dependency_period))) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Failed to locate timeperiod '%s' for dependency from service '%s' on host '%s' to service '%s' on host '%s'\n", + dependency_period, dependent_service_description, dependent_host_name, service_description, host_name); return NULL; } /* allocate memory for a new service dependency entry */ - if((new_servicedependency = (servicedependency *)calloc(1, sizeof(servicedependency))) == NULL) + if((new_servicedependency = calloc(1, sizeof(*new_servicedependency))) == NULL) return NULL; - /* duplicate vars */ - if((new_servicedependency->dependent_host_name = (char *)strdup(dependent_host_name)) == NULL) - result = ERROR; - if((new_servicedependency->dependent_service_description = (char *)strdup(dependent_service_description)) == NULL) - result = ERROR; - if((new_servicedependency->host_name = (char *)strdup(host_name)) == NULL) - result = ERROR; - if((new_servicedependency->service_description = (char *)strdup(service_description)) == NULL) - result = ERROR; - if(dependency_period) { - if((new_servicedependency->dependency_period = (char *)strdup(dependency_period)) == NULL) - result = ERROR; - } + new_servicedependency->dependent_service_ptr = child; + new_servicedependency->master_service_ptr = parent; + new_servicedependency->dependency_period_ptr = tp; + + /* assign vars. object names are immutable, so no need to copy */ + new_servicedependency->dependent_host_name = child->host_name; + new_servicedependency->dependent_service_description = child->description; + new_servicedependency->host_name = parent->host_name; + new_servicedependency->service_description = parent->description; + if (tp) + new_servicedependency->dependency_period = (char *)strdup(tp->name); new_servicedependency->dependency_type = (dependency_type == EXECUTION_DEPENDENCY) ? EXECUTION_DEPENDENCY : NOTIFICATION_DEPENDENCY; new_servicedependency->inherits_parent = (inherits_parent > 0) ? TRUE : FALSE; - new_servicedependency->fail_on_ok = (fail_on_ok == 1) ? TRUE : FALSE; - new_servicedependency->fail_on_warning = (fail_on_warning == 1) ? TRUE : FALSE; - new_servicedependency->fail_on_unknown = (fail_on_unknown == 1) ? TRUE : FALSE; - new_servicedependency->fail_on_critical = (fail_on_critical == 1) ? TRUE : FALSE; - new_servicedependency->fail_on_pending = (fail_on_pending == 1) ? TRUE : FALSE; -#ifdef NSCORE - new_servicedependency->circular_path_checked = FALSE; - new_servicedependency->contains_circular_path = FALSE; -#endif + new_servicedependency->failure_options = failure_options; - /* add new service dependency to skiplist */ - if(result == OK) { - result = skiplist_insert(object_skiplists[SERVICEDEPENDENCY_SKIPLIST], (void *)new_servicedependency); - switch(result) { - case SKIPLIST_OK: - result = OK; - break; - default: - logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not add service dependency to skiplist\n"); - result = ERROR; - break; - } - } - - /* handle errors */ - if(result == ERROR) { - my_free(new_servicedependency->host_name); - my_free(new_servicedependency->service_description); - my_free(new_servicedependency->dependent_host_name); - my_free(new_servicedependency->dependent_service_description); - my_free(new_servicedependency); - return NULL; - } - - /* service dependencies are sorted alphabetically, so add new items to tail of list */ - if(servicedependency_list == NULL) { - servicedependency_list = new_servicedependency; - servicedependency_list_tail = servicedependency_list; - } - else { - servicedependency_list_tail->next = new_servicedependency; - servicedependency_list_tail = new_servicedependency; + /* + * add new service dependency to its respective services. + * Ordering doesn't matter here as we'll have to check them + * all anyway. We avoid adding dupes though, since we can + * apparently get zillion's and zillion's of them. + */ + if(dependency_type == NOTIFICATION_DEPENDENCY) + result = prepend_unique_object_to_objectlist(&child->notify_deps, new_servicedependency, sizeof(*new_servicedependency)); + else + result = prepend_unique_object_to_objectlist(&child->exec_deps, new_servicedependency, sizeof(*new_servicedependency)); + + if(result != OK) { + free(new_servicedependency); + /* hack to avoid caller bombing out */ + return result == OBJECTLIST_DUPE ? (void *)1 : NULL; } + num_objects.servicedependencies++; return new_servicedependency; } /* adds a host dependency definition */ -hostdependency *add_host_dependency(char *dependent_host_name, char *host_name, int dependency_type, int inherits_parent, int fail_on_up, int fail_on_down, int fail_on_unreachable, int fail_on_pending, char *dependency_period) { +hostdependency *add_host_dependency(char *dependent_host_name, char *host_name, int dependency_type, int inherits_parent, int failure_options, char *dependency_period) { hostdependency *new_hostdependency = NULL; - int result = OK; + host *parent, *child; + timeperiod *tp = NULL; + int result; /* make sure we have what we need */ - if((dependent_host_name == NULL || !strcmp(dependent_host_name, "")) || (host_name == NULL || !strcmp(host_name, ""))) { - logit(NSLOG_CONFIG_ERROR, TRUE, "Error: NULL host name in host dependency definition\n"); + parent = find_host(host_name); + if (!parent) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Master host '%s' in hostdependency from '%s' to '%s' is not defined anywhere!\n", + host_name, dependent_host_name, host_name); return NULL; } + child = find_host(dependent_host_name); + if (!child) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Dependent host '%s' in hostdependency from '%s' to '%s' is not defined anywhere!\n", + dependent_host_name, dependent_host_name, host_name); + return NULL; + } + if (dependency_period && !(tp = find_timeperiod(dependency_period))) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Unable to locate dependency_period '%s' for %s->%s host dependency\n", + dependency_period, parent->name, child->name); + return NULL ; + } - /* allocate memory for a new host dependency entry */ - if((new_hostdependency = (hostdependency *)calloc(1, sizeof(hostdependency))) == NULL) + if((new_hostdependency = calloc(1, sizeof(*new_hostdependency))) == NULL) return NULL; - /* duplicate vars */ - if((new_hostdependency->dependent_host_name = (char *)strdup(dependent_host_name)) == NULL) - result = ERROR; - if((new_hostdependency->host_name = (char *)strdup(host_name)) == NULL) - result = ERROR; - if(dependency_period) { - if((new_hostdependency->dependency_period = (char *)strdup(dependency_period)) == NULL) - result = ERROR; - } + new_hostdependency->dependent_host_ptr = child; + new_hostdependency->master_host_ptr = parent; + new_hostdependency->dependency_period_ptr = tp; + + /* assign vars. Objects are immutable, so no need to copy */ + new_hostdependency->dependent_host_name = child->name; + new_hostdependency->host_name = parent->name; + if(tp) + new_hostdependency->dependency_period = (char *)strdup(tp->name); new_hostdependency->dependency_type = (dependency_type == EXECUTION_DEPENDENCY) ? EXECUTION_DEPENDENCY : NOTIFICATION_DEPENDENCY; new_hostdependency->inherits_parent = (inherits_parent > 0) ? TRUE : FALSE; - new_hostdependency->fail_on_up = (fail_on_up == 1) ? TRUE : FALSE; - new_hostdependency->fail_on_down = (fail_on_down == 1) ? TRUE : FALSE; - new_hostdependency->fail_on_unreachable = (fail_on_unreachable == 1) ? TRUE : FALSE; - new_hostdependency->fail_on_pending = (fail_on_pending == 1) ? TRUE : FALSE; -#ifdef NSCORE - new_hostdependency->circular_path_checked = FALSE; - new_hostdependency->contains_circular_path = FALSE; -#endif + new_hostdependency->failure_options = failure_options; - /* add new host dependency to skiplist */ - if(result == OK) { - result = skiplist_insert(object_skiplists[HOSTDEPENDENCY_SKIPLIST], (void *)new_hostdependency); - switch(result) { - case SKIPLIST_OK: - result = OK; - break; - default: - logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not add host dependency to skiplist\n"); - result = ERROR; - break; - } - } - - /* handle errors */ - if(result == ERROR) { - my_free(new_hostdependency->host_name); - my_free(new_hostdependency->dependent_host_name); - my_free(new_hostdependency); - return NULL; - } - - /* host dependencies are sorted alphabetically, so add new items to tail of list */ - if(hostdependency_list == NULL) { - hostdependency_list = new_hostdependency; - hostdependency_list_tail = hostdependency_list; - } - else { - hostdependency_list_tail->next = new_hostdependency; - hostdependency_list_tail = new_hostdependency; + if(dependency_type == NOTIFICATION_DEPENDENCY) + result = prepend_unique_object_to_objectlist(&child->notify_deps, new_hostdependency, sizeof(*new_hostdependency)); + else + result = prepend_unique_object_to_objectlist(&child->exec_deps, new_hostdependency, sizeof(*new_hostdependency)); + + if(result != OK) { + free(new_hostdependency); + /* hack to avoid caller bombing out */ + return result == OBJECTLIST_DUPE ? (void *)1 : NULL; } + num_objects.hostdependencies++; return new_hostdependency; } /* add a new host escalation to the list in memory */ -hostescalation *add_hostescalation(char *host_name, int first_notification, int last_notification, double notification_interval, char *escalation_period, int escalate_on_down, int escalate_on_unreachable, int escalate_on_recovery) { +hostescalation *add_hostescalation(char *host_name, int first_notification, int last_notification, double notification_interval, char *escalation_period, int escalation_options) { hostescalation *new_hostescalation = NULL; - int result = OK; + host *h; + timeperiod *tp = NULL; /* make sure we have the data we need */ - if(host_name == NULL || !strcmp(host_name, "")) { + if(host_name == NULL || !*host_name) { logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Host escalation host name is NULL\n"); return NULL; } - -#ifdef TEST - printf("NEW HST ESCALATION: %s = %d/%d/%.3f\n", host_name, first_notification, last_notification, notification_interval); -#endif - - /* allocate memory for a new host escalation entry */ - if((new_hostescalation = calloc(1, sizeof(hostescalation))) == NULL) + if (!(h = find_host(host_name))) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Host '%s' has an escalation, but is not defined anywhere!\n", host_name); + return NULL; + } + if (escalation_period && !(tp = find_timeperiod(escalation_period))) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Unable to locate timeperiod '%s' for hostescalation '%s'\n", + escalation_period, host_name); return NULL; - - /* duplicate vars */ - if((new_hostescalation->host_name = (char *)strdup(host_name)) == NULL) - result = ERROR; - if(escalation_period) { - if((new_hostescalation->escalation_period = (char *)strdup(escalation_period)) == NULL) - result = ERROR; } + new_hostescalation = calloc(1, sizeof(*new_hostescalation)); + + /* add the escalation to its host */ + if (add_object_to_objectlist(&h->escalation_list, new_hostescalation) != OK) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not add hostescalation to host '%s'\n", host_name); + free(new_hostescalation); + return NULL; + } + + /* assign vars. Object names are immutable, so no need to copy */ + new_hostescalation->host_name = h->name; + new_hostescalation->host_ptr = h; + new_hostescalation->escalation_period = tp ? (char *)strdup(tp->name) : NULL; + new_hostescalation->escalation_period_ptr = tp; new_hostescalation->first_notification = first_notification; new_hostescalation->last_notification = last_notification; new_hostescalation->notification_interval = (notification_interval <= 0) ? 0 : notification_interval; - new_hostescalation->escalate_on_recovery = (escalate_on_recovery > 0) ? TRUE : FALSE; - new_hostescalation->escalate_on_down = (escalate_on_down > 0) ? TRUE : FALSE; - new_hostescalation->escalate_on_unreachable = (escalate_on_unreachable > 0) ? TRUE : FALSE; - - /* add new hostescalation to skiplist */ - if(result == OK) { - result = skiplist_insert(object_skiplists[HOSTESCALATION_SKIPLIST], (void *)new_hostescalation); - switch(result) { - case SKIPLIST_OK: - result = OK; - break; - default: - logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not add hostescalation '%s' to skiplist\n", host_name); - result = ERROR; - break; - } - } - - /* handle errors */ - if(result == ERROR) { - my_free(new_hostescalation->host_name); - my_free(new_hostescalation->escalation_period); - my_free(new_hostescalation); - return NULL; - } - - /* host escalations are sorted alphabetically, so add new items to tail of list */ - if(hostescalation_list == NULL) { - hostescalation_list = new_hostescalation; - hostescalation_list_tail = hostescalation_list; - } - else { - hostescalation_list_tail->next = new_hostescalation; - hostescalation_list_tail = new_hostescalation; - } + new_hostescalation->escalation_options = escalation_options; + new_hostescalation->id = num_objects.hostescalations++; + hostescalation_ary[new_hostescalation->id] = new_hostescalation; return new_hostescalation; } @@ -2218,35 +1908,7 @@ hostescalation *add_hostescalation(char *host_name, int first_notification, int /* adds a contact group to a host escalation */ contactgroupsmember *add_contactgroup_to_hostescalation(hostescalation *he, char *group_name) { - contactgroupsmember *new_contactgroupsmember = NULL; - int result = OK; - - /* bail out if we weren't given the data we need */ - if(he == NULL || (group_name == NULL || !strcmp(group_name, ""))) { - logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Host escalation or contactgroup name is NULL\n"); - return NULL; - } - - /* allocate memory for the contactgroups member */ - if((new_contactgroupsmember = (contactgroupsmember *)calloc(1, sizeof(contactgroupsmember))) == NULL) - return NULL; - - /* duplicate vars */ - if((new_contactgroupsmember->group_name = (char *)strdup(group_name)) == NULL) - result = ERROR; - - /* handle errors */ - if(result == ERROR) { - my_free(new_contactgroupsmember->group_name); - my_free(new_contactgroupsmember); - return NULL; - } - - /* add this contactgroup to the host escalation */ - new_contactgroupsmember->next = he->contact_groups; - he->contact_groups = new_contactgroupsmember; - - return new_contactgroupsmember; + return add_contactgroup_to_object(&he->contact_groups, group_name); } @@ -2262,6 +1924,7 @@ contactsmember *add_contact_to_hostescalation(hostescalation *he, char *contact_ /* adds a contact to an object */ contactsmember *add_contact_to_object(contactsmember **object_ptr, char *contactname) { contactsmember *new_contactsmember = NULL; + contact *c; /* make sure we have the data we need */ if(object_ptr == NULL) { @@ -2269,26 +1932,24 @@ contactsmember *add_contact_to_object(contactsmember **object_ptr, char *contact return NULL; } - if(contactname == NULL || !strcmp(contactname, "")) { + if(contactname == NULL || !*contactname) { logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Contact name is NULL\n"); return NULL; } + if(!(c = find_contact(contactname))) { + logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Contact '%s' is not defined anywhere!\n", contactname); + return NULL; + } /* allocate memory for a new member */ if((new_contactsmember = malloc(sizeof(contactsmember))) == NULL) { logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not allocate memory for contact\n"); return NULL; } - if((new_contactsmember->contact_name = (char *)strdup(contactname)) == NULL) { - logit(NSLOG_CONFIG_ERROR, TRUE, "Error: Could not allocate memory for contact name\n"); - my_free(new_contactsmember); - return NULL; - } + new_contactsmember->contact_name = c->name; /* set initial values */ -#ifdef NSCORE - new_contactsmember->contact_ptr = NULL; -#endif + new_contactsmember->contact_ptr = c; /* add the new contact to the head of the contact list */ new_contactsmember->next = *object_ptr; @@ -2352,220 +2013,40 @@ customvariablesmember *add_custom_variable_to_object(customvariablesmember **obj /******************** OBJECT SEARCH FUNCTIONS *********************/ /******************************************************************/ -/* given a timeperiod name and a starting point, find a timeperiod from the list in memory */ -timeperiod * find_timeperiod(char *name) { - timeperiod temp_timeperiod; - - if(name == NULL) - return NULL; - - temp_timeperiod.name = name; - - return skiplist_find_first(object_skiplists[TIMEPERIOD_SKIPLIST], &temp_timeperiod, NULL); +timeperiod *find_timeperiod(const char *name) { + return dkhash_get(object_hash_tables[TIMEPERIOD_SKIPLIST], name, NULL); } - -/* given a host name, find it in the list in memory */ -host * find_host(char *name) { - host temp_host; - - if(name == NULL) - return NULL; - - temp_host.name = name; - - return skiplist_find_first(object_skiplists[HOST_SKIPLIST], &temp_host, NULL); +host *find_host(const char *name) { + return dkhash_get(object_hash_tables[HOST_SKIPLIST], name, NULL); } - -/* find a hostgroup from the list in memory */ -hostgroup * find_hostgroup(char *name) { - hostgroup temp_hostgroup; - - if(name == NULL) - return NULL; - - temp_hostgroup.group_name = name; - - return skiplist_find_first(object_skiplists[HOSTGROUP_SKIPLIST], &temp_hostgroup, NULL); +hostgroup *find_hostgroup(const char *name) { + return dkhash_get(object_hash_tables[HOSTGROUP_SKIPLIST], name, NULL); } - -/* find a servicegroup from the list in memory */ -servicegroup * find_servicegroup(char *name) { - servicegroup temp_servicegroup; - - if(name == NULL) - return NULL; - - temp_servicegroup.group_name = name; - - return skiplist_find_first(object_skiplists[SERVICEGROUP_SKIPLIST], &temp_servicegroup, NULL); +servicegroup *find_servicegroup(const char *name) { + return dkhash_get(object_hash_tables[SERVICEGROUP_SKIPLIST], name, NULL); } - -/* find a contact from the list in memory */ -contact * find_contact(char *name) { - contact temp_contact; - - if(name == NULL) - return NULL; - - temp_contact.name = name; - - return skiplist_find_first(object_skiplists[CONTACT_SKIPLIST], &temp_contact, NULL); +contact *find_contact(const char *name) { + return dkhash_get(object_hash_tables[CONTACT_SKIPLIST], name, NULL); } - -/* find a contact group from the list in memory */ -contactgroup * find_contactgroup(char *name) { - contactgroup temp_contactgroup; - - if(name == NULL) - return NULL; - - temp_contactgroup.group_name = name; - - return skiplist_find_first(object_skiplists[CONTACTGROUP_SKIPLIST], &temp_contactgroup, NULL); +contactgroup *find_contactgroup(const char *name) { + return dkhash_get(object_hash_tables[CONTACTGROUP_SKIPLIST], name, NULL); } - -/* given a command name, find a command from the list in memory */ -command * find_command(char *name) { - command temp_command; - - if(name == NULL) - return NULL; - - temp_command.name = name; - - return skiplist_find_first(object_skiplists[COMMAND_SKIPLIST], &temp_command, NULL); +command *find_command(const char *name) { + return dkhash_get(object_hash_tables[COMMAND_SKIPLIST], name, NULL); } - -/* given a host/service name, find the service in the list in memory */ -service * find_service(char *host_name, char *svc_desc) { - service temp_service; - - if(host_name == NULL || svc_desc == NULL) - return NULL; - - temp_service.host_name = host_name; - temp_service.description = svc_desc; - - return skiplist_find_first(object_skiplists[SERVICE_SKIPLIST], &temp_service, NULL); +service *find_service(const char *host_name, const char *svc_desc) { + return dkhash_get(object_hash_tables[SERVICE_SKIPLIST], host_name, svc_desc); } - -/******************************************************************/ -/******************* OBJECT TRAVERSAL FUNCTIONS *******************/ -/******************************************************************/ - -hostescalation *get_first_hostescalation_by_host(char *host_name, void **ptr) { - hostescalation temp_hostescalation; - - if(host_name == NULL) - return NULL; - - temp_hostescalation.host_name = host_name; - - return skiplist_find_first(object_skiplists[HOSTESCALATION_SKIPLIST], &temp_hostescalation, ptr); - } - - -hostescalation *get_next_hostescalation_by_host(char *host_name, void **ptr) { - hostescalation temp_hostescalation; - - if(host_name == NULL) - return NULL; - - temp_hostescalation.host_name = host_name; - - return skiplist_find_next(object_skiplists[HOSTESCALATION_SKIPLIST], &temp_hostescalation, ptr); - } - - -serviceescalation *get_first_serviceescalation_by_service(char *host_name, char *svc_description, void **ptr) { - serviceescalation temp_serviceescalation; - - if(host_name == NULL || svc_description == NULL) - return NULL; - - temp_serviceescalation.host_name = host_name; - temp_serviceescalation.description = svc_description; - - return skiplist_find_first(object_skiplists[SERVICEESCALATION_SKIPLIST], &temp_serviceescalation, ptr); - } - - -serviceescalation *get_next_serviceescalation_by_service(char *host_name, char *svc_description, void **ptr) { - serviceescalation temp_serviceescalation; - - if(host_name == NULL || svc_description == NULL) - return NULL; - - temp_serviceescalation.host_name = host_name; - temp_serviceescalation.description = svc_description; - - return skiplist_find_next(object_skiplists[SERVICEESCALATION_SKIPLIST], &temp_serviceescalation, ptr); - } - - -hostdependency *get_first_hostdependency_by_dependent_host(char *host_name, void **ptr) { - hostdependency temp_hostdependency; - - if(host_name == NULL) - return NULL; - - temp_hostdependency.dependent_host_name = host_name; - - return skiplist_find_first(object_skiplists[HOSTDEPENDENCY_SKIPLIST], &temp_hostdependency, ptr); - } - - -hostdependency *get_next_hostdependency_by_dependent_host(char *host_name, void **ptr) { - hostdependency temp_hostdependency; - - if(host_name == NULL || ptr == NULL) - return NULL; - - temp_hostdependency.dependent_host_name = host_name; - - return skiplist_find_next(object_skiplists[HOSTDEPENDENCY_SKIPLIST], &temp_hostdependency, ptr); - } - - -servicedependency *get_first_servicedependency_by_dependent_service(char *host_name, char *svc_description, void **ptr) { - servicedependency temp_servicedependency; - - if(host_name == NULL || svc_description == NULL) - return NULL; - - temp_servicedependency.dependent_host_name = host_name; - temp_servicedependency.dependent_service_description = svc_description; - - return skiplist_find_first(object_skiplists[SERVICEDEPENDENCY_SKIPLIST], &temp_servicedependency, ptr); - } - - -servicedependency *get_next_servicedependency_by_dependent_service(char *host_name, char *svc_description, void **ptr) { - servicedependency temp_servicedependency; - - if(host_name == NULL || svc_description == NULL || ptr == NULL) - return NULL; - - temp_servicedependency.dependent_host_name = host_name; - temp_servicedependency.dependent_service_description = svc_description; - - return skiplist_find_next(object_skiplists[SERVICEDEPENDENCY_SKIPLIST], &temp_servicedependency, ptr); - - return NULL; - } - - -#ifdef NSCORE /* adds a object to a list of objects */ int add_object_to_objectlist(objectlist **list, void *object_ptr) { objectlist *temp_item = NULL; @@ -2597,6 +2078,31 @@ int add_object_to_objectlist(objectlist **list, void *object_ptr) { } +/* useful when we don't care if the object is unique or not */ +int prepend_object_to_objectlist(objectlist **list, void *object_ptr) +{ + objectlist *item; + if(list == NULL || object_ptr == NULL) + return ERROR; + if((item = malloc(sizeof(*item))) == NULL) + return ERROR; + item->next = *list; + item->object_ptr = object_ptr; + *list = item; + return OK; + } + +/* useful for adding dependencies to master objects */ +int prepend_unique_object_to_objectlist(objectlist **list, void *object_ptr, size_t size) { + objectlist *l; + if(list == NULL || object_ptr == NULL) + return ERROR; + for(l = *list; l; l = l->next) { + if(!memcmp(l->object_ptr, object_ptr, size)) + return OBJECTLIST_DUPE; + } + return prepend_object_to_objectlist(list, object_ptr); +} /* frees memory allocated to a temporary object list */ int free_objectlist(objectlist **temp_list) { @@ -2616,7 +2122,6 @@ int free_objectlist(objectlist **temp_list) { return OK; } -#endif @@ -2642,13 +2147,8 @@ int is_host_immediate_child_of_host(host *parent_host, host *child_host) { else { for(temp_hostsmember = child_host->parent_hosts; temp_hostsmember != NULL; temp_hostsmember = temp_hostsmember->next) { -#ifdef NSCORE if(temp_hostsmember->host_ptr == parent_host) return TRUE; -#else - if(!strcmp(temp_hostsmember->host_name, parent_host->name)) - return TRUE; -#endif } } @@ -2665,6 +2165,14 @@ int is_host_immediate_parent_of_host(host *child_host, host *parent_host) { return FALSE; } +#ifdef NSCGI +int hostsmember_elements(hostsmember *list) +{ + int elems = 0; + for (; list; list = list->next) + elems++; + return elems; +} /* returns a count of the immediate children for a given host */ /* NOTE: This function is only used by the CGIS */ @@ -2672,27 +2180,17 @@ int number_of_immediate_child_hosts(host *hst) { int children = 0; host *temp_host = NULL; - for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) { - if(is_host_immediate_child_of_host(hst, temp_host) == TRUE) - children++; + if(hst == NULL) { + for(temp_host = host_list; temp_host != NULL; + temp_host = temp_host->next) { + if(is_host_immediate_child_of_host(hst, temp_host) == TRUE) + children++; + } + return children; } - - return children; - } - - -/* returns a count of the total children for a given host */ -/* NOTE: This function is only used by the CGIS */ -int number_of_total_child_hosts(host *hst) { - int children = 0; - host *temp_host = NULL; - - for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) { - if(is_host_immediate_child_of_host(hst, temp_host) == TRUE) - children += number_of_total_child_hosts(temp_host) + 1; + else { + return hostsmember_elements(hst->child_hosts); } - - return children; } @@ -2702,31 +2200,20 @@ int number_of_immediate_parent_hosts(host *hst) { int parents = 0; host *temp_host = NULL; - for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) { - if(is_host_immediate_parent_of_host(hst, temp_host) == TRUE) { - parents++; + if(hst == NULL) { + for(temp_host = host_list; temp_host != NULL; + temp_host = temp_host->next) { + if(is_host_immediate_parent_of_host(hst, temp_host) == TRUE) { + parents++; + } } + return parents; } - - return parents; - } - - -/* get the total number of parent hosts for a given host */ -/* NOTE: This function is only used by the CGIS */ -int number_of_total_parent_hosts(host *hst) { - int parents = 0; - host *temp_host = NULL; - - for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) { - if(is_host_immediate_parent_of_host(hst, temp_host) == TRUE) { - parents += number_of_total_parent_hosts(temp_host) + 1; - } + else { + return hostsmember_elements(hst->parent_hosts); } - - return parents; } - +#endif /* tests whether a host is a member of a particular hostgroup */ /* NOTE: This function is only used by the CGIS */ @@ -2737,13 +2224,8 @@ int is_host_member_of_hostgroup(hostgroup *group, host *hst) { return FALSE; for(temp_hostsmember = group->members; temp_hostsmember != NULL; temp_hostsmember = temp_hostsmember->next) { -#ifdef NSCORE if(temp_hostsmember->host_ptr == hst) return TRUE; -#else - if(!strcmp(temp_hostsmember->host_name, hst->name)) - return TRUE; -#endif } return FALSE; @@ -2759,13 +2241,8 @@ int is_host_member_of_servicegroup(servicegroup *group, host *hst) { return FALSE; for(temp_servicesmember = group->members; temp_servicesmember != NULL; temp_servicesmember = temp_servicesmember->next) { -#ifdef NSCORE if(temp_servicesmember->service_ptr != NULL && temp_servicesmember->service_ptr->host_ptr == hst) return TRUE; -#else - if(!strcmp(temp_servicesmember->host_name, hst->name)) - return TRUE; -#endif } return FALSE; @@ -2781,13 +2258,8 @@ int is_service_member_of_servicegroup(servicegroup *group, service *svc) { return FALSE; for(temp_servicesmember = group->members; temp_servicesmember != NULL; temp_servicesmember = temp_servicesmember->next) { -#ifdef NSCORE if(temp_servicesmember->service_ptr == svc) return TRUE; -#else - if(!strcmp(temp_servicesmember->host_name, svc->host_name) && !strcmp(temp_servicesmember->service_description, svc->description)) - return TRUE; -#endif } return FALSE; @@ -2803,21 +2275,13 @@ int is_service_member_of_servicegroup(servicegroup *group, service *svc) { */ int is_contact_member_of_contactgroup(contactgroup *group, contact *cntct) { contactsmember *member; - contact *temp_contact = NULL; if(!group || !cntct) return FALSE; /* search all contacts in this contact group */ for(member = group->members; member; member = member->next) { -#ifdef NSCORE - temp_contact = member->contact_ptr; -#else - temp_contact = find_contact(member->contact_name); -#endif - if(temp_contact == NULL) - continue; - if(temp_contact == cntct) + if (member->contact_ptr == cntct) return TRUE; } @@ -2827,7 +2291,6 @@ int is_contact_member_of_contactgroup(contactgroup *group, contact *cntct) { /* tests whether a contact is a contact for a particular host */ int is_contact_for_host(host *hst, contact *cntct) { contactsmember *temp_contactsmember = NULL; - contact *temp_contact = NULL; contactgroupsmember *temp_contactgroupsmember = NULL; contactgroup *temp_contactgroup = NULL; @@ -2837,26 +2300,13 @@ int is_contact_for_host(host *hst, contact *cntct) { /* search all individual contacts of this host */ for(temp_contactsmember = hst->contacts; temp_contactsmember != NULL; temp_contactsmember = temp_contactsmember->next) { -#ifdef NSCORE - temp_contact = temp_contactsmember->contact_ptr; -#else - temp_contact = find_contact(temp_contactsmember->contact_name); -#endif - if(temp_contact == NULL) - continue; - if(temp_contact == cntct) + if (temp_contactsmember->contact_ptr == cntct) return TRUE; } /* search all contactgroups of this host */ for(temp_contactgroupsmember = hst->contact_groups; temp_contactgroupsmember != NULL; temp_contactgroupsmember = temp_contactgroupsmember->next) { -#ifdef NSCORE temp_contactgroup = temp_contactgroupsmember->group_ptr; -#else - temp_contactgroup = find_contactgroup(temp_contactgroupsmember->group_name); -#endif - if(temp_contactgroup == NULL) - continue; if(is_contact_member_of_contactgroup(temp_contactgroup, cntct)) return TRUE; } @@ -2866,44 +2316,20 @@ int is_contact_for_host(host *hst, contact *cntct) { -/* tests whether or not a contact is an escalated contact for a particular host */ -int is_escalated_contact_for_host(host *hst, contact *cntct) { - contactsmember *temp_contactsmember = NULL; - contact *temp_contact = NULL; - hostescalation *temp_hostescalation = NULL; +/* tests whether a contactgroup is a contactgroup for a particular host */ +int is_contactgroup_for_host(host *hst, contactgroup *group) { contactgroupsmember *temp_contactgroupsmember = NULL; - contactgroup *temp_contactgroup = NULL; - void *ptr = NULL; + if(hst == NULL || group == NULL) { + return FALSE; + } - /* search all host escalations */ - for(temp_hostescalation = get_first_hostescalation_by_host(hst->name, &ptr); temp_hostescalation != NULL; temp_hostescalation = get_next_hostescalation_by_host(hst->name, &ptr)) { - - /* search all contacts of this host escalation */ - for(temp_contactsmember = temp_hostescalation->contacts; temp_contactsmember != NULL; temp_contactsmember = temp_contactsmember->next) { -#ifdef NSCORE - temp_contact = temp_contactsmember->contact_ptr; -#else - temp_contact = find_contact(temp_contactsmember->contact_name); -#endif - if(temp_contact == NULL) - continue; - if(temp_contact == cntct) - return TRUE; - } - - /* search all contactgroups of this host escalation */ - for(temp_contactgroupsmember = temp_hostescalation->contact_groups; temp_contactgroupsmember != NULL; temp_contactgroupsmember = temp_contactgroupsmember->next) { -#ifdef NSCORE - temp_contactgroup = temp_contactgroupsmember->group_ptr; -#else - temp_contactgroup = find_contactgroup(temp_contactgroupsmember->group_name); -#endif - if(temp_contactgroup == NULL) - continue; - if(is_contact_member_of_contactgroup(temp_contactgroup, cntct)) - return TRUE; - + /* search all contactgroups of this host */ + for(temp_contactgroupsmember = hst->contact_groups; + temp_contactgroupsmember != NULL; + temp_contactgroupsmember = temp_contactgroupsmember->next) { + if(temp_contactgroupsmember->group_ptr == group) { + return TRUE; } } @@ -2911,10 +2337,85 @@ int is_escalated_contact_for_host(host *hst, contact *cntct) { } + +/* tests whether a contact is an escalated contact for a particular host */ +int is_escalated_contact_for_host(host *hst, contact *cntct) { + hostescalation *temp_hostescalation = NULL; + objectlist *list; + + /* search all host escalations */ + for(list = hst->escalation_list; list; list = list->next) { + temp_hostescalation = (hostescalation *)list->object_ptr; + + if(is_contact_for_host_escalation(temp_hostescalation, cntct) == TRUE) { + return TRUE; + } + } + + return FALSE; + } + + + +/* tests whether a contact is an contact for a particular host escalation */ +int is_contact_for_host_escalation(hostescalation *escalation, contact *cntct) { + contactsmember *temp_contactsmember = NULL; + contactgroupsmember *temp_contactgroupsmember = NULL; + contactgroup *temp_contactgroup = NULL; + + if(escalation == NULL || cntct == NULL) { + return FALSE; + } + + /* search all contacts of this host escalation */ + for(temp_contactsmember = escalation->contacts; + temp_contactsmember != NULL; + temp_contactsmember = temp_contactsmember->next) { + if(temp_contactsmember->contact_ptr == cntct) + return TRUE; + } + + /* search all contactgroups of this host escalation */ + for(temp_contactgroupsmember = escalation->contact_groups; + temp_contactgroupsmember != NULL; + temp_contactgroupsmember = temp_contactgroupsmember->next) { + temp_contactgroup = temp_contactgroupsmember->group_ptr; + if(is_contact_member_of_contactgroup(temp_contactgroup, cntct)) + return TRUE; + } + + return FALSE; + } + + + +/* tests whether a contactgroup is a contactgroup for a particular + host escalation */ +int is_contactgroup_for_host_escalation(hostescalation *escalation, + contactgroup *group) { + contactgroupsmember *temp_contactgroupsmember = NULL; + + if(escalation == NULL || group == NULL) { + return FALSE; + } + + /* search all contactgroups of this host escalation */ + for(temp_contactgroupsmember = escalation->contact_groups; + temp_contactgroupsmember != NULL; + temp_contactgroupsmember = temp_contactgroupsmember->next) { + if(temp_contactgroupsmember->group_ptr == group) { + return TRUE; + } + } + + return FALSE; + } + + + /* tests whether a contact is a contact for a particular service */ int is_contact_for_service(service *svc, contact *cntct) { contactsmember *temp_contactsmember = NULL; - contact *temp_contact = NULL; contactgroupsmember *temp_contactgroupsmember = NULL; contactgroup *temp_contactgroup = NULL; @@ -2923,25 +2424,13 @@ int is_contact_for_service(service *svc, contact *cntct) { /* search all individual contacts of this service */ for(temp_contactsmember = svc->contacts; temp_contactsmember != NULL; temp_contactsmember = temp_contactsmember->next) { -#ifdef NSCORE - temp_contact = temp_contactsmember->contact_ptr; -#else - temp_contact = find_contact(temp_contactsmember->contact_name); -#endif - - if(temp_contact == cntct) + if(temp_contactsmember->contact_ptr == cntct) return TRUE; } /* search all contactgroups of this service */ for(temp_contactgroupsmember = svc->contact_groups; temp_contactgroupsmember != NULL; temp_contactgroupsmember = temp_contactgroupsmember->next) { -#ifdef NSCORE temp_contactgroup = temp_contactgroupsmember->group_ptr; -#else - temp_contactgroup = find_contactgroup(temp_contactgroupsmember->group_name); -#endif - if(temp_contactgroup == NULL) - continue; if(is_contact_member_of_contactgroup(temp_contactgroup, cntct)) return TRUE; @@ -2952,42 +2441,39 @@ int is_contact_for_service(service *svc, contact *cntct) { -/* tests whether or not a contact is an escalated contact for a particular service */ +/* tests whether a contactgroup is a contactgroup for a particular service */ +int is_contactgroup_for_service(service *svc, contactgroup *group) { + contactgroupsmember *temp_contactgroupsmember = NULL; + + if(svc == NULL || group == NULL) + return FALSE; + + /* search all contactgroups of this service */ + for(temp_contactgroupsmember = svc->contact_groups; + temp_contactgroupsmember != NULL; + temp_contactgroupsmember = temp_contactgroupsmember->next) { + if(temp_contactgroupsmember->group_ptr == group) { + return TRUE; + } + } + + return FALSE; + } + + + +/* tests whether a contact is an escalated contact for a particular service */ int is_escalated_contact_for_service(service *svc, contact *cntct) { serviceescalation *temp_serviceescalation = NULL; - contactsmember *temp_contactsmember = NULL; - contact *temp_contact = NULL; - contactgroupsmember *temp_contactgroupsmember = NULL; - contactgroup *temp_contactgroup = NULL; - void *ptr = NULL; + objectlist *list; /* search all the service escalations */ - for(temp_serviceescalation = get_first_serviceescalation_by_service(svc->host_name, svc->description, &ptr); temp_serviceescalation != NULL; temp_serviceescalation = get_next_serviceescalation_by_service(svc->host_name, svc->description, &ptr)) { + for(list = svc->escalation_list; list; list = list->next) { + temp_serviceescalation = (serviceescalation *)list->object_ptr; - /* search all contacts of this service escalation */ - for(temp_contactsmember = temp_serviceescalation->contacts; temp_contactsmember != NULL; temp_contactsmember = temp_contactsmember->next) { -#ifdef NSCORE - temp_contact = temp_contactsmember->contact_ptr; -#else - temp_contact = find_contact(temp_contactsmember->contact_name); -#endif - if(temp_contact == NULL) - continue; - if(temp_contact == cntct) - return TRUE; - } - - /* search all contactgroups of this service escalation */ - for(temp_contactgroupsmember = temp_serviceescalation->contact_groups; temp_contactgroupsmember != NULL; temp_contactgroupsmember = temp_contactgroupsmember->next) { -#ifdef NSCORE - temp_contactgroup = temp_contactgroupsmember->group_ptr; -#else - temp_contactgroup = find_contactgroup(temp_contactgroupsmember->group_name); -#endif - if(temp_contactgroup == NULL) - continue; - if(is_contact_member_of_contactgroup(temp_contactgroup, cntct)) - return TRUE; + if(is_contact_for_service_escalation(temp_serviceescalation, + cntct) == TRUE) { + return TRUE; } } @@ -2995,52 +2481,28 @@ int is_escalated_contact_for_service(service *svc, contact *cntct) { } -#ifdef NSCORE -/* checks to see if there exists a circular dependency for a service */ -int check_for_circular_servicedependency_path(servicedependency *root_dep, servicedependency *dep, int dependency_type) { - servicedependency *temp_sd = NULL; +/* tests whether a contact is an contact for a particular service escalation */ +int is_contact_for_service_escalation(serviceescalation *escalation, + contact *cntct) { + contactsmember *temp_contactsmember = NULL; + contactgroupsmember *temp_contactgroupsmember = NULL; + contactgroup *temp_contactgroup = NULL; - if(root_dep == NULL || dep == NULL) - return FALSE; - - /* this is not the proper dependency type */ - if(root_dep->dependency_type != dependency_type || dep->dependency_type != dependency_type) - return FALSE; - - /* don't go into a loop, don't bother checking anymore if we know this dependency already has a loop */ - if(root_dep->contains_circular_path == TRUE) - return TRUE; - - /* dependency has already been checked - there is a path somewhere, but it may not be for this particular dep... */ - /* this should speed up detection for some loops */ - if(dep->circular_path_checked == TRUE) - return FALSE; - - /* set the check flag so we don't get into an infinite loop */ - dep->circular_path_checked = TRUE; - - /* is this service dependent on the root service? */ - if(dep != root_dep) { - if(root_dep->dependent_service_ptr == dep->master_service_ptr) { - root_dep->contains_circular_path = TRUE; - dep->contains_circular_path = TRUE; + /* search all contacts of this service escalation */ + for(temp_contactsmember = escalation->contacts; + temp_contactsmember != NULL; + temp_contactsmember = temp_contactsmember->next) { + if(temp_contactsmember->contact_ptr == cntct) return TRUE; - } } - /* notification dependencies are ok at this point as long as they don't inherit */ - if(dependency_type == NOTIFICATION_DEPENDENCY && dep->inherits_parent == FALSE) - return FALSE; - - /* check all parent dependencies */ - for(temp_sd = servicedependency_list; temp_sd != NULL; temp_sd = temp_sd->next) { - - /* only check parent dependencies */ - if(dep->master_service_ptr != temp_sd->dependent_service_ptr) - continue; - - if(check_for_circular_servicedependency_path(root_dep, temp_sd, dependency_type) == TRUE) + /* search all contactgroups of this service escalation */ + for(temp_contactgroupsmember =escalation->contact_groups; + temp_contactgroupsmember != NULL; + temp_contactgroupsmember = temp_contactgroupsmember->next) { + temp_contactgroup = temp_contactgroupsmember->group_ptr; + if(is_contact_member_of_contactgroup(temp_contactgroup, cntct)) return TRUE; } @@ -3048,59 +2510,29 @@ int check_for_circular_servicedependency_path(servicedependency *root_dep, servi } -/* checks to see if there exists a circular dependency for a host */ -int check_for_circular_hostdependency_path(hostdependency *root_dep, hostdependency *dep, int dependency_type) { - hostdependency *temp_hd = NULL; - if(root_dep == NULL || dep == NULL) +/* tests whether a contactgroup is a contactgroup for a particular + service escalation */ +int is_contactgroup_for_service_escalation(serviceescalation *escalation, + contactgroup *group) { + contactgroupsmember *temp_contactgroupsmember = NULL; + + if(escalation == NULL || group == NULL) { return FALSE; + } - /* this is not the proper dependency type */ - if(root_dep->dependency_type != dependency_type || dep->dependency_type != dependency_type) - return FALSE; - - /* don't go into a loop, don't bother checking anymore if we know this dependency already has a loop */ - if(root_dep->contains_circular_path == TRUE) - return TRUE; - - /* dependency has already been checked - there is a path somewhere, but it may not be for this particular dep... */ - /* this should speed up detection for some loops */ - if(dep->circular_path_checked == TRUE) - return FALSE; - - /* set the check flag so we don't get into an infinite loop */ - dep->circular_path_checked = TRUE; - - /* is this host dependent on the root host? */ - if(dep != root_dep) { - if(root_dep->dependent_host_ptr == dep->master_host_ptr) { - root_dep->contains_circular_path = TRUE; - dep->contains_circular_path = TRUE; + /* search all contactgroups of this service escalation */ + for(temp_contactgroupsmember = escalation->contact_groups; + temp_contactgroupsmember != NULL; + temp_contactgroupsmember = temp_contactgroupsmember->next) { + if(temp_contactgroupsmember->group_ptr == group) { return TRUE; } } - /* notification dependencies are ok at this point as long as they don't inherit */ - if(dependency_type == NOTIFICATION_DEPENDENCY && dep->inherits_parent == FALSE) - return FALSE; - - /* check all parent dependencies */ - for(temp_hd = hostdependency_list; temp_hd != NULL; temp_hd = temp_hd->next) { - - /* only check parent dependencies */ - if(dep->master_host_ptr != temp_hd->dependent_host_ptr) - continue; - - if(check_for_circular_hostdependency_path(root_dep, temp_hd, dependency_type) == TRUE) - return TRUE; - } - return FALSE; } -#endif - - /******************************************************************/ @@ -3110,55 +2542,40 @@ int check_for_circular_hostdependency_path(hostdependency *root_dep, hostdepende /* free all allocated memory for objects */ int free_object_data(void) { - timeperiod *this_timeperiod = NULL; - timeperiod *next_timeperiod = NULL; daterange *this_daterange = NULL; daterange *next_daterange = NULL; timerange *this_timerange = NULL; timerange *next_timerange = NULL; timeperiodexclusion *this_timeperiodexclusion = NULL; timeperiodexclusion *next_timeperiodexclusion = NULL; - host *this_host = NULL; - host *next_host = NULL; hostsmember *this_hostsmember = NULL; hostsmember *next_hostsmember = NULL; - hostgroup *this_hostgroup = NULL; - hostgroup *next_hostgroup = NULL; - servicegroup *this_servicegroup = NULL; - servicegroup *next_servicegroup = NULL; servicesmember *this_servicesmember = NULL; servicesmember *next_servicesmember = NULL; - contact *this_contact = NULL; - contact *next_contact = NULL; - contactgroup *this_contactgroup = NULL; - contactgroup *next_contactgroup = NULL; contactsmember *this_contactsmember = NULL; contactsmember *next_contactsmember = NULL; contactgroupsmember *this_contactgroupsmember = NULL; contactgroupsmember *next_contactgroupsmember = NULL; customvariablesmember *this_customvariablesmember = NULL; customvariablesmember *next_customvariablesmember = NULL; - service *this_service = NULL; - service *next_service = NULL; - command *this_command = NULL; - command *next_command = NULL; commandsmember *this_commandsmember = NULL; commandsmember *next_commandsmember = NULL; - serviceescalation *this_serviceescalation = NULL; - serviceescalation *next_serviceescalation = NULL; - servicedependency *this_servicedependency = NULL; - servicedependency *next_servicedependency = NULL; - hostdependency *this_hostdependency = NULL; - hostdependency *next_hostdependency = NULL; - hostescalation *this_hostescalation = NULL; - hostescalation *next_hostescalation = NULL; - register int x = 0; - register int i = 0; + unsigned int i = 0, x = 0; + /* + * kill off hash tables so lingering modules don't look stuff up + * while we're busy removing it. + */ + for (i = 0; i < ARRAY_SIZE(object_hash_tables); i++) { + dkhash_table *t = object_hash_tables[i]; + object_hash_tables[i] = NULL; + dkhash_destroy(t); + } + /**** free memory for the timeperiod list ****/ - this_timeperiod = timeperiod_list; - while(this_timeperiod != NULL) { + for (i = 0; i < num_objects.timeperiods; i++) { + timeperiod *this_timeperiod = timeperiod_ary[i]; /* free the exception time ranges contained in this timeperiod */ for(x = 0; x < DATERANGE_TYPES; x++) { @@ -3189,22 +2606,19 @@ int free_object_data(void) { my_free(this_timeperiodexclusion); } - next_timeperiod = this_timeperiod->next; + if (this_timeperiod->alias != this_timeperiod->name) + my_free(this_timeperiod->alias); my_free(this_timeperiod->name); - my_free(this_timeperiod->alias); my_free(this_timeperiod); - this_timeperiod = next_timeperiod; } /* reset pointers */ - timeperiod_list = NULL; + my_free(timeperiod_ary); /**** free memory for the host list ****/ - this_host = host_list; - while(this_host != NULL) { - - next_host = this_host->next; + for (i = 0; i < num_objects.hosts; i++) { + host *this_host = host_ary[i]; /* free memory for parent hosts */ this_hostsmember = this_host->parent_hosts; @@ -3219,7 +2633,6 @@ int free_object_data(void) { this_hostsmember = this_host->child_hosts; while(this_hostsmember != NULL) { next_hostsmember = this_hostsmember->next; - my_free(this_hostsmember->host_name); my_free(this_hostsmember); this_hostsmember = next_hostsmember; } @@ -3228,8 +2641,6 @@ int free_object_data(void) { this_servicesmember = this_host->services; while(this_servicesmember != NULL) { next_servicesmember = this_servicesmember->next; - my_free(this_servicesmember->host_name); - my_free(this_servicesmember->service_description); my_free(this_servicesmember); this_servicesmember = next_servicesmember; } @@ -3238,7 +2649,6 @@ int free_object_data(void) { this_contactgroupsmember = this_host->contact_groups; while(this_contactgroupsmember != NULL) { next_contactgroupsmember = this_contactgroupsmember->next; - my_free(this_contactgroupsmember->group_name); my_free(this_contactgroupsmember); this_contactgroupsmember = next_contactgroupsmember; } @@ -3247,7 +2657,6 @@ int free_object_data(void) { this_contactsmember = this_host->contacts; while(this_contactsmember != NULL) { next_contactsmember = this_contactsmember->next; - my_free(this_contactsmember->contact_name); my_free(this_contactsmember); this_contactsmember = next_contactsmember; } @@ -3262,22 +2671,24 @@ int free_object_data(void) { this_customvariablesmember = next_customvariablesmember; } + if(this_host->display_name != this_host->name) + my_free(this_host->display_name); + if(this_host->alias != this_host->name) + my_free(this_host->alias); + if(this_host->address != this_host->name) + my_free(this_host->address); my_free(this_host->name); - my_free(this_host->display_name); - my_free(this_host->alias); - my_free(this_host->address); #ifdef NSCORE my_free(this_host->plugin_output); my_free(this_host->long_plugin_output); my_free(this_host->perf_data); - - free_objectlist(&this_host->hostgroups_ptr); #endif - my_free(this_host->check_period); - my_free(this_host->host_check_command); + free_objectlist(&this_host->hostgroups_ptr); + free_objectlist(&this_host->notify_deps); + free_objectlist(&this_host->exec_deps); + free_objectlist(&this_host->escalation_list); + my_free(this_host->check_command); my_free(this_host->event_handler); - my_free(this_host->failure_prediction_options); - my_free(this_host->notification_period); my_free(this_host->notes); my_free(this_host->notes_url); my_free(this_host->action_url); @@ -3286,71 +2697,64 @@ int free_object_data(void) { my_free(this_host->vrml_image); my_free(this_host->statusmap_image); my_free(this_host); - this_host = next_host; } /* reset pointers */ - host_list = NULL; + my_free(host_ary); /**** free memory for the host group list ****/ - this_hostgroup = hostgroup_list; - while(this_hostgroup != NULL) { + for (i = 0; i < num_objects.hostgroups; i++) { + hostgroup *this_hostgroup = hostgroup_ary[i]; /* free memory for the group members */ this_hostsmember = this_hostgroup->members; while(this_hostsmember != NULL) { next_hostsmember = this_hostsmember->next; - my_free(this_hostsmember->host_name); my_free(this_hostsmember); this_hostsmember = next_hostsmember; } - next_hostgroup = this_hostgroup->next; + if (this_hostgroup->alias != this_hostgroup->group_name) + my_free(this_hostgroup->alias); my_free(this_hostgroup->group_name); - my_free(this_hostgroup->alias); my_free(this_hostgroup->notes); my_free(this_hostgroup->notes_url); my_free(this_hostgroup->action_url); my_free(this_hostgroup); - this_hostgroup = next_hostgroup; } /* reset pointers */ - hostgroup_list = NULL; - + my_free(hostgroup_ary); /**** free memory for the service group list ****/ - this_servicegroup = servicegroup_list; - while(this_servicegroup != NULL) { + for (i = 0; i < num_objects.servicegroups; i++) { + servicegroup *this_servicegroup = servicegroup_ary[i]; /* free memory for the group members */ this_servicesmember = this_servicegroup->members; while(this_servicesmember != NULL) { next_servicesmember = this_servicesmember->next; - my_free(this_servicesmember->host_name); - my_free(this_servicesmember->service_description); my_free(this_servicesmember); this_servicesmember = next_servicesmember; } - next_servicegroup = this_servicegroup->next; + if (this_servicegroup->alias != this_servicegroup->group_name) + my_free(this_servicegroup->alias); my_free(this_servicegroup->group_name); - my_free(this_servicegroup->alias); my_free(this_servicegroup->notes); my_free(this_servicegroup->notes_url); my_free(this_servicegroup->action_url); my_free(this_servicegroup); - this_servicegroup = next_servicegroup; } /* reset pointers */ - servicegroup_list = NULL; - + my_free(servicegroup_ary); /**** free memory for the contact list ****/ - this_contact = contact_list; - while(this_contact != NULL) { + for (i = 0; i < num_objects.contacts; i++) { + int j; + contact *this_contact = contact_ary[i]; /* free memory for the host notification commands */ this_commandsmember = this_contact->host_notification_commands; @@ -3382,63 +2786,52 @@ int free_object_data(void) { this_customvariablesmember = next_customvariablesmember; } - next_contact = this_contact->next; + if (this_contact->alias != this_contact->name) + my_free(this_contact->alias); my_free(this_contact->name); - my_free(this_contact->alias); my_free(this_contact->email); my_free(this_contact->pager); - for(i = 0; i < MAX_CONTACT_ADDRESSES; i++) - my_free(this_contact->address[i]); - my_free(this_contact->host_notification_period); - my_free(this_contact->service_notification_period); + for(j = 0; j < MAX_CONTACT_ADDRESSES; j++) + my_free(this_contact->address[j]); -#ifdef NSCORE free_objectlist(&this_contact->contactgroups_ptr); -#endif - my_free(this_contact); - this_contact = next_contact; } /* reset pointers */ - contact_list = NULL; + my_free(contact_ary); /**** free memory for the contact group list ****/ - this_contactgroup = contactgroup_list; - while(this_contactgroup != NULL) { + for (i = 0; i < num_objects.contactgroups; i++) { + contactgroup *this_contactgroup = contactgroup_ary[i]; /* free memory for the group members */ this_contactsmember = this_contactgroup->members; while(this_contactsmember != NULL) { next_contactsmember = this_contactsmember->next; - my_free(this_contactsmember->contact_name); my_free(this_contactsmember); this_contactsmember = next_contactsmember; } - next_contactgroup = this_contactgroup->next; + if (this_contactgroup->alias != this_contactgroup->group_name) + my_free(this_contactgroup->alias); my_free(this_contactgroup->group_name); - my_free(this_contactgroup->alias); my_free(this_contactgroup); - this_contactgroup = next_contactgroup; } /* reset pointers */ - contactgroup_list = NULL; + my_free(contactgroup_ary); /**** free memory for the service list ****/ - this_service = service_list; - while(this_service != NULL) { - - next_service = this_service->next; + for (i = 0; i < num_objects.services; i++) { + service *this_service = service_ary[i]; /* free memory for contact groups */ this_contactgroupsmember = this_service->contact_groups; while(this_contactgroupsmember != NULL) { next_contactgroupsmember = this_contactgroupsmember->next; - my_free(this_contactgroupsmember->group_name); my_free(this_contactgroupsmember); this_contactgroupsmember = next_contactgroupsmember; } @@ -3447,7 +2840,6 @@ int free_object_data(void) { this_contactsmember = this_service->contacts; while(this_contactsmember != NULL) { next_contactsmember = this_contactsmember->next; - my_free(this_contactsmember->contact_name); my_free(this_contactsmember); this_contactsmember = next_contactsmember; } @@ -3462,10 +2854,10 @@ int free_object_data(void) { this_customvariablesmember = next_customvariablesmember; } - my_free(this_service->host_name); + if(this_service->display_name != this_service->description) + my_free(this_service->display_name); my_free(this_service->description); - my_free(this_service->display_name); - my_free(this_service->service_check_command); + my_free(this_service->check_command); #ifdef NSCORE my_free(this_service->plugin_output); my_free(this_service->long_plugin_output); @@ -3473,49 +2865,45 @@ int free_object_data(void) { my_free(this_service->event_handler_args); my_free(this_service->check_command_args); +#endif free_objectlist(&this_service->servicegroups_ptr); -#endif - my_free(this_service->notification_period); - my_free(this_service->check_period); + free_objectlist(&this_service->notify_deps); + free_objectlist(&this_service->exec_deps); + free_objectlist(&this_service->escalation_list); my_free(this_service->event_handler); - my_free(this_service->failure_prediction_options); my_free(this_service->notes); my_free(this_service->notes_url); my_free(this_service->action_url); my_free(this_service->icon_image); my_free(this_service->icon_image_alt); my_free(this_service); - this_service = next_service; } /* reset pointers */ - service_list = NULL; + my_free(service_ary); - /**** free memory for the command list ****/ - this_command = command_list; - while(this_command != NULL) { - next_command = this_command->next; + /**** free command memory ****/ + for (i = 0; i < num_objects.commands; i++) { + command *this_command = command_ary[i]; my_free(this_command->name); my_free(this_command->command_line); my_free(this_command); - this_command = next_command; } /* reset pointers */ - command_list = NULL; + my_free(command_ary); - /**** free memory for the service escalation list ****/ - this_serviceescalation = serviceescalation_list; - while(this_serviceescalation != NULL) { + /**** free service escalation memory ****/ + for (i = 0; i < num_objects.serviceescalations; i++) { + serviceescalation *this_serviceescalation = serviceescalation_ary[i]; /* free memory for the contact group members */ this_contactgroupsmember = this_serviceescalation->contact_groups; while(this_contactgroupsmember != NULL) { next_contactgroupsmember = this_contactgroupsmember->next; - my_free(this_contactgroupsmember->group_name); my_free(this_contactgroupsmember); this_contactgroupsmember = next_contactgroupsmember; } @@ -3524,64 +2912,40 @@ int free_object_data(void) { this_contactsmember = this_serviceescalation->contacts; while(this_contactsmember != NULL) { next_contactsmember = this_contactsmember->next; - my_free(this_contactsmember->contact_name); my_free(this_contactsmember); this_contactsmember = next_contactsmember; } - - next_serviceescalation = this_serviceescalation->next; - my_free(this_serviceescalation->host_name); - my_free(this_serviceescalation->description); - my_free(this_serviceescalation->escalation_period); my_free(this_serviceescalation); - this_serviceescalation = next_serviceescalation; } /* reset pointers */ - serviceescalation_list = NULL; + my_free(serviceescalation_ary); - /**** free memory for the service dependency list ****/ - this_servicedependency = servicedependency_list; - while(this_servicedependency != NULL) { - next_servicedependency = this_servicedependency->next; - my_free(this_servicedependency->dependency_period); - my_free(this_servicedependency->dependent_host_name); - my_free(this_servicedependency->dependent_service_description); - my_free(this_servicedependency->host_name); - my_free(this_servicedependency->service_description); - my_free(this_servicedependency); - this_servicedependency = next_servicedependency; + /**** free service dependency memory ****/ + if (servicedependency_ary) { + for(i = 0; i < num_objects.servicedependencies; i++) + my_free(servicedependency_ary[i]); + my_free(servicedependency_ary); } - /* reset pointers */ - servicedependency_list = NULL; - - /**** free memory for the host dependency list ****/ - this_hostdependency = hostdependency_list; - while(this_hostdependency != NULL) { - next_hostdependency = this_hostdependency->next; - my_free(this_hostdependency->dependency_period); - my_free(this_hostdependency->dependent_host_name); - my_free(this_hostdependency->host_name); - my_free(this_hostdependency); - this_hostdependency = next_hostdependency; + /**** free host dependency memory ****/ + if (hostdependency_ary) { + for(i = 0; i < num_objects.hostdependencies; i++) + my_free(hostdependency_ary[i]); + my_free(hostdependency_ary); } - /* reset pointers */ - hostdependency_list = NULL; - - /**** free memory for the host escalation list ****/ - this_hostescalation = hostescalation_list; - while(this_hostescalation != NULL) { + /**** free host escalation memory ****/ + for (i = 0; i < num_objects.hostescalations; i++) { + hostescalation *this_hostescalation = hostescalation_ary[i]; /* free memory for the contact group members */ this_contactgroupsmember = this_hostescalation->contact_groups; while(this_contactgroupsmember != NULL) { next_contactgroupsmember = this_contactgroupsmember->next; - my_free(this_contactgroupsmember->group_name); my_free(this_contactgroupsmember); this_contactgroupsmember = next_contactgroupsmember; } @@ -3590,24 +2954,585 @@ int free_object_data(void) { this_contactsmember = this_hostescalation->contacts; while(this_contactsmember != NULL) { next_contactsmember = this_contactsmember->next; - my_free(this_contactsmember->contact_name); my_free(this_contactsmember); this_contactsmember = next_contactsmember; } - - next_hostescalation = this_hostescalation->next; - my_free(this_hostescalation->host_name); - my_free(this_hostescalation->escalation_period); my_free(this_hostescalation); - this_hostescalation = next_hostescalation; } /* reset pointers */ - hostescalation_list = NULL; + my_free(hostescalation_ary); - /* free object skiplists */ - free_object_skiplists(); + /* we no longer have any objects */ + memset(&num_objects, 0, sizeof(num_objects)); return OK; } + + +/******************************************************************/ +/*********************** CACHE FUNCTIONS **************************/ +/******************************************************************/ + +#ifndef NSCGI +static const char *timerange2str(const timerange *tr) +{ + static char str[12]; + int sh, sm, eh, em; + + if(!tr) + return ""; + sh = tr->range_start / 3600; + sm = (tr->range_start / 60) % 60; + eh = tr->range_end / 3600; + em = (tr->range_end / 60) % 60; + sprintf(str, "%02d:%02d-%02d:%02d", sh, sm, eh, em); + return str; +} + +void fcache_contactlist(FILE *fp, const char *prefix, contactsmember *list) +{ + if(list) { + contactsmember *l; + fprintf(fp, "%s", prefix); + for(l = list; l; l = l->next) + fprintf(fp, "%s%c", l->contact_name, l->next ? ',' : '\n'); + } +} + +void fcache_contactgrouplist(FILE *fp, const char *prefix, contactgroupsmember *list) +{ + if(list) { + contactgroupsmember *l; + fprintf(fp, "%s", prefix); + for(l = list; l; l = l->next) + fprintf(fp, "%s%c", l->group_name, l->next ? ',' : '\n'); + } +} + +void fcache_hostlist(FILE *fp, const char *prefix, hostsmember *list) +{ + if(list) { + hostsmember *l; + fprintf(fp, "%s", prefix); + for(l = list; l; l = l->next) + fprintf(fp, "%s%c", l->host_name, l->next ? ',' : '\n'); + } +} + +void fcache_customvars(FILE *fp, customvariablesmember *cvlist) +{ + if(cvlist) { + customvariablesmember *l; + for(l = cvlist; l; l = l->next) + fprintf(fp, "\t_%s\t%s\n", l->variable_name, (l->variable_value == NULL) ? XODTEMPLATE_NULL : l->variable_value); + } +} + +void fcache_timeperiod(FILE *fp, timeperiod *temp_timeperiod) +{ + const char *days[7] = {"sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"}; + const char *months[12] = {"january", "february", "march", "april", "may", "june", "july", "august", "september", "october", "november", "december"}; + daterange *temp_daterange; + timerange *tr; + register int x; + + fprintf(fp, "define timeperiod {\n"); + fprintf(fp, "\ttimeperiod_name\t%s\n", temp_timeperiod->name); + if(temp_timeperiod->alias) + fprintf(fp, "\talias\t%s\n", temp_timeperiod->alias); + + if(temp_timeperiod->exclusions) { + timeperiodexclusion *exclude; + fprintf(fp, "\texclude\t"); + for(exclude = temp_timeperiod->exclusions; exclude; exclude = exclude->next) { + fprintf(fp, "%s%c", exclude->timeperiod_name, exclude->next ? ',' : '\n'); + } + } + + for(x = 0; x < DATERANGE_TYPES; x++) { + for(temp_daterange = temp_timeperiod->exceptions[x]; temp_daterange != NULL; temp_daterange = temp_daterange->next) { + + /* skip null entries */ + if(temp_daterange->times == NULL) + continue; + + switch(temp_daterange->type) { + case DATERANGE_CALENDAR_DATE: + fprintf(fp, "\t%d-%02d-%02d", temp_daterange->syear, temp_daterange->smon + 1, temp_daterange->smday); + if((temp_daterange->smday != temp_daterange->emday) || (temp_daterange->smon != temp_daterange->emon) || (temp_daterange->syear != temp_daterange->eyear)) + fprintf(fp, " - %d-%02d-%02d", temp_daterange->eyear, temp_daterange->emon + 1, temp_daterange->emday); + if(temp_daterange->skip_interval > 1) + fprintf(fp, " / %d", temp_daterange->skip_interval); + break; + case DATERANGE_MONTH_DATE: + fprintf(fp, "\t%s %d", months[temp_daterange->smon], temp_daterange->smday); + if((temp_daterange->smon != temp_daterange->emon) || (temp_daterange->smday != temp_daterange->emday)) { + fprintf(fp, " - %s %d", months[temp_daterange->emon], temp_daterange->emday); + if(temp_daterange->skip_interval > 1) + fprintf(fp, " / %d", temp_daterange->skip_interval); + } + break; + case DATERANGE_MONTH_DAY: + fprintf(fp, "\tday %d", temp_daterange->smday); + if(temp_daterange->smday != temp_daterange->emday) { + fprintf(fp, " - %d", temp_daterange->emday); + if(temp_daterange->skip_interval > 1) + fprintf(fp, " / %d", temp_daterange->skip_interval); + } + break; + case DATERANGE_MONTH_WEEK_DAY: + fprintf(fp, "\t%s %d %s", days[temp_daterange->swday], temp_daterange->swday_offset, months[temp_daterange->smon]); + if((temp_daterange->smon != temp_daterange->emon) || (temp_daterange->swday != temp_daterange->ewday) || (temp_daterange->swday_offset != temp_daterange->ewday_offset)) { + fprintf(fp, " - %s %d %s", days[temp_daterange->ewday], temp_daterange->ewday_offset, months[temp_daterange->emon]); + if(temp_daterange->skip_interval > 1) + fprintf(fp, " / %d", temp_daterange->skip_interval); + } + break; + case DATERANGE_WEEK_DAY: + fprintf(fp, "\t%s %d", days[temp_daterange->swday], temp_daterange->swday_offset); + if((temp_daterange->swday != temp_daterange->ewday) || (temp_daterange->swday_offset != temp_daterange->ewday_offset)) { + fprintf(fp, " - %s %d", days[temp_daterange->ewday], temp_daterange->ewday_offset); + if(temp_daterange->skip_interval > 1) + fprintf(fp, " / %d", temp_daterange->skip_interval); + } + break; + default: + break; + } + + fputc('\t', fp); + for(tr = temp_daterange->times; tr; tr = tr->next) { + fprintf(fp, "%s%c", timerange2str(tr), tr->next ? ',' : '\n'); + } + } + } + for(x = 0; x < 7; x++) { + /* skip null entries */ + if(temp_timeperiod->days[x] == NULL) + continue; + + fprintf(fp, "\t%s\t", days[x]); + for(tr = temp_timeperiod->days[x]; tr; tr = tr->next) { + fprintf(fp, "%s%c", timerange2str(tr), tr->next ? ',' : '\n'); + } + } + fprintf(fp, "\t}\n\n"); +} + +void fcache_command(FILE *fp, command *temp_command) +{ + fprintf(fp, "define command {\n\tcommand_name\t%s\n\tcommand_line\t%s\n\t}\n\n", + temp_command->name, temp_command->command_line); +} + +void fcache_contactgroup(FILE *fp, contactgroup *temp_contactgroup) +{ + fprintf(fp, "define contactgroup {\n"); + fprintf(fp, "\tcontactgroup_name\t%s\n", temp_contactgroup->group_name); + if(temp_contactgroup->alias) + fprintf(fp, "\talias\t%s\n", temp_contactgroup->alias); + fcache_contactlist(fp, "\tmembers\t", temp_contactgroup->members); + fprintf(fp, "\t}\n\n"); +} + +void fcache_hostgroup(FILE *fp, hostgroup *temp_hostgroup) +{ + fprintf(fp, "define hostgroup {\n"); + fprintf(fp, "\thostgroup_name\t%s\n", temp_hostgroup->group_name); + if(temp_hostgroup->alias) + fprintf(fp, "\talias\t%s\n", temp_hostgroup->alias); + if(temp_hostgroup->members) { + hostsmember *list; + fprintf(fp, "\tmembers\t"); + for(list = temp_hostgroup->members; list; list = list->next) + fprintf(fp, "%s%c", list->host_name, list->next ? ',' : '\n'); + } + if(temp_hostgroup->notes) + fprintf(fp, "\tnotes\t%s\n", temp_hostgroup->notes); + if(temp_hostgroup->notes_url) + fprintf(fp, "\tnotes_url\t%s\n", temp_hostgroup->notes_url); + if(temp_hostgroup->action_url) + fprintf(fp, "\taction_url\t%s\n", temp_hostgroup->action_url); + fprintf(fp, "\t}\n\n"); +} + +void fcache_servicegroup(FILE *fp, servicegroup *temp_servicegroup) +{ + fprintf(fp, "define servicegroup {\n"); + fprintf(fp, "\tservicegroup_name\t%s\n", temp_servicegroup->group_name); + if(temp_servicegroup->alias) + fprintf(fp, "\talias\t%s\n", temp_servicegroup->alias); + if(temp_servicegroup->members) { + servicesmember *list; + fprintf(fp, "\tmembers\t"); + for(list = temp_servicegroup->members; list; list = list->next) { + service *s = list->service_ptr; + fprintf(fp, "%s,%s%c", s->host_name, s->description, list->next ? ',' : '\n'); + } + } + if(temp_servicegroup->notes) + fprintf(fp, "\tnotes\t%s\n", temp_servicegroup->notes); + if(temp_servicegroup->notes_url) + fprintf(fp, "\tnotes_url\t%s\n", temp_servicegroup->notes_url); + if(temp_servicegroup->action_url) + fprintf(fp, "\taction_url\t%s\n", temp_servicegroup->action_url); + fprintf(fp, "\t}\n\n"); +} + +void fcache_contact(FILE *fp, contact *temp_contact) +{ + commandsmember *list; + int x; + + fprintf(fp, "define contact {\n"); + fprintf(fp, "\tcontact_name\t%s\n", temp_contact->name); + if(temp_contact->alias) + fprintf(fp, "\talias\t%s\n", temp_contact->alias); + if(temp_contact->service_notification_period) + fprintf(fp, "\tservice_notification_period\t%s\n", temp_contact->service_notification_period); + if(temp_contact->host_notification_period) + fprintf(fp, "\thost_notification_period\t%s\n", temp_contact->host_notification_period); + fprintf(fp, "\tservice_notification_options\t%s\n", opts2str(temp_contact->service_notification_options, service_flag_map, 'r')); + fprintf(fp, "\thost_notification_options\t%s\n", opts2str(temp_contact->host_notification_options, host_flag_map, 'r')); + if(temp_contact->service_notification_commands) { + fprintf(fp, "\tservice_notification_commands\t"); + for(list = temp_contact->service_notification_commands; list; list = list->next) { + fprintf(fp, "%s%c", list->command, list->next ? ',' : '\n'); + } + } + if(temp_contact->host_notification_commands) { + fprintf(fp, "\thost_notification_commands\t"); + for(list = temp_contact->host_notification_commands; list; list = list->next) { + fprintf(fp, "%s%c", list->command, list->next ? ',' : '\n'); + } + } + if(temp_contact->email) + fprintf(fp, "\temail\t%s\n", temp_contact->email); + if(temp_contact->pager) + fprintf(fp, "\tpager\t%s\n", temp_contact->pager); + for(x = 0; x < MAX_XODTEMPLATE_CONTACT_ADDRESSES; x++) { + if(temp_contact->address[x]) + fprintf(fp, "\taddress%d\t%s\n", x + 1, temp_contact->address[x]); + } + fprintf(fp, "\tminimum_importance\t%u\n", temp_contact->minimum_value); + fprintf(fp, "\thost_notifications_enabled\t%d\n", temp_contact->host_notifications_enabled); + fprintf(fp, "\tservice_notifications_enabled\t%d\n", temp_contact->service_notifications_enabled); + fprintf(fp, "\tcan_submit_commands\t%d\n", temp_contact->can_submit_commands); + fprintf(fp, "\tretain_status_information\t%d\n", temp_contact->retain_status_information); + fprintf(fp, "\tretain_nonstatus_information\t%d\n", temp_contact->retain_nonstatus_information); + + /* custom variables */ + fcache_customvars(fp, temp_contact->custom_variables); + fprintf(fp, "\t}\n\n"); +} + +void fcache_host(FILE *fp, host *temp_host) +{ + fprintf(fp, "define host {\n"); + fprintf(fp, "\thost_name\t%s\n", temp_host->name); + if(temp_host->display_name != temp_host->name) + fprintf(fp, "\tdisplay_name\t%s\n", temp_host->display_name); + if(temp_host->alias) + fprintf(fp, "\talias\t%s\n", temp_host->alias); + if(temp_host->address) + fprintf(fp, "\taddress\t%s\n", temp_host->address); + fcache_hostlist(fp, "\tparents\t", temp_host->parent_hosts); + if(temp_host->check_period) + fprintf(fp, "\tcheck_period\t%s\n", temp_host->check_period); + if(temp_host->check_command) + fprintf(fp, "\tcheck_command\t%s\n", temp_host->check_command); + if(temp_host->event_handler) + fprintf(fp, "\tevent_handler\t%s\n", temp_host->event_handler); + fcache_contactlist(fp, "\tcontacts\t", temp_host->contacts); + fcache_contactgrouplist(fp, "\tcontact_groups\t", temp_host->contact_groups); + if(temp_host->notification_period) + fprintf(fp, "\tnotification_period\t%s\n", temp_host->notification_period); + fprintf(fp, "\tinitial_state\t"); + if(temp_host->initial_state == HOST_DOWN) + fprintf(fp, "d\n"); + else if(temp_host->initial_state == HOST_UNREACHABLE) + fprintf(fp, "u\n"); + else + fprintf(fp, "o\n"); + fprintf(fp, "\timportance\t%u\n", temp_host->hourly_value); + fprintf(fp, "\tcheck_interval\t%f\n", temp_host->check_interval); + fprintf(fp, "\tretry_interval\t%f\n", temp_host->retry_interval); + fprintf(fp, "\tmax_check_attempts\t%d\n", temp_host->max_attempts); + fprintf(fp, "\tactive_checks_enabled\t%d\n", temp_host->checks_enabled); + fprintf(fp, "\tpassive_checks_enabled\t%d\n", temp_host->accept_passive_checks); + fprintf(fp, "\tobsess\t%d\n", temp_host->obsess); + fprintf(fp, "\tevent_handler_enabled\t%d\n", temp_host->event_handler_enabled); + fprintf(fp, "\tlow_flap_threshold\t%f\n", temp_host->low_flap_threshold); + fprintf(fp, "\thigh_flap_threshold\t%f\n", temp_host->high_flap_threshold); + fprintf(fp, "\tflap_detection_enabled\t%d\n", temp_host->flap_detection_enabled); + fprintf(fp, "\tflap_detection_options\t%s\n", opts2str(temp_host->flap_detection_options, host_flag_map, 'u')); + fprintf(fp, "\tfreshness_threshold\t%d\n", temp_host->freshness_threshold); + fprintf(fp, "\tcheck_freshness\t%d\n", temp_host->check_freshness); + fprintf(fp, "\tnotification_options\t%s\n", opts2str(temp_host->notification_options, host_flag_map, 'r')); + fprintf(fp, "\tnotifications_enabled\t%d\n", temp_host->notifications_enabled); + fprintf(fp, "\tnotification_interval\t%f\n", temp_host->notification_interval); + fprintf(fp, "\tfirst_notification_delay\t%f\n", temp_host->first_notification_delay); + fprintf(fp, "\tstalking_options\t%s\n", opts2str(temp_host->stalking_options, host_flag_map, 'u')); + fprintf(fp, "\tprocess_perf_data\t%d\n", temp_host->process_performance_data); + if(temp_host->icon_image) + fprintf(fp, "\ticon_image\t%s\n", temp_host->icon_image); + if(temp_host->icon_image_alt) + fprintf(fp, "\ticon_image_alt\t%s\n", temp_host->icon_image_alt); + if(temp_host->vrml_image) + fprintf(fp, "\tvrml_image\t%s\n", temp_host->vrml_image); + if(temp_host->statusmap_image) + fprintf(fp, "\tstatusmap_image\t%s\n", temp_host->statusmap_image); + if(temp_host->have_2d_coords == TRUE) + fprintf(fp, "\t2d_coords\t%d,%d\n", temp_host->x_2d, temp_host->y_2d); + if(temp_host->have_3d_coords == TRUE) + fprintf(fp, "\t3d_coords\t%f,%f,%f\n", temp_host->x_3d, temp_host->y_3d, temp_host->z_3d); + if(temp_host->notes) + fprintf(fp, "\tnotes\t%s\n", temp_host->notes); + if(temp_host->notes_url) + fprintf(fp, "\tnotes_url\t%s\n", temp_host->notes_url); + if(temp_host->action_url) + fprintf(fp, "\taction_url\t%s\n", temp_host->action_url); + fprintf(fp, "\tretain_status_information\t%d\n", temp_host->retain_status_information); + fprintf(fp, "\tretain_nonstatus_information\t%d\n", temp_host->retain_nonstatus_information); + + /* custom variables */ + fcache_customvars(fp, temp_host->custom_variables); + fprintf(fp, "\t}\n\n"); +} + +void fcache_service(FILE *fp, service *temp_service) +{ + fprintf(fp, "define service {\n"); + fprintf(fp, "\thost_name\t%s\n", temp_service->host_name); + fprintf(fp, "\tservice_description\t%s\n", temp_service->description); + if(temp_service->display_name != temp_service->description) + fprintf(fp, "\tdisplay_name\t%s\n", temp_service->display_name); + if(temp_service->parents) { + fprintf(fp, "\tparents\t"); + /* same-host, single-parent? */ + if(!temp_service->parents->next && temp_service->parents->service_ptr->host_ptr == temp_service->host_ptr) + fprintf(fp, "%s\n", temp_service->parents->service_ptr->description); + else { + servicesmember *sm; + for(sm = temp_service->parents; sm; sm = sm->next) { + fprintf(fp, "%s,%s%c", sm->host_name, sm->service_description, sm->next ? ',' : '\n'); + } + } + } + if(temp_service->check_period) + fprintf(fp, "\tcheck_period\t%s\n", temp_service->check_period); + if(temp_service->check_command) + fprintf(fp, "\tcheck_command\t%s\n", temp_service->check_command); + if(temp_service->event_handler) + fprintf(fp, "\tevent_handler\t%s\n", temp_service->event_handler); + fcache_contactlist(fp, "\tcontacts\t", temp_service->contacts); + fcache_contactgrouplist(fp, "\tcontact_groups\t", temp_service->contact_groups); + if(temp_service->notification_period) + fprintf(fp, "\tnotification_period\t%s\n", temp_service->notification_period); + fprintf(fp, "\tinitial_state\t"); + if(temp_service->initial_state == STATE_WARNING) + fprintf(fp, "w\n"); + else if(temp_service->initial_state == STATE_UNKNOWN) + fprintf(fp, "u\n"); + else if(temp_service->initial_state == STATE_CRITICAL) + fprintf(fp, "c\n"); + else + fprintf(fp, "o\n"); + fprintf(fp, "\timportance\t%u\n", temp_service->hourly_value); + fprintf(fp, "\tcheck_interval\t%f\n", temp_service->check_interval); + fprintf(fp, "\tretry_interval\t%f\n", temp_service->retry_interval); + fprintf(fp, "\tmax_check_attempts\t%d\n", temp_service->max_attempts); + fprintf(fp, "\tis_volatile\t%d\n", temp_service->is_volatile); + fprintf(fp, "\tparallelize_check\t%d\n", temp_service->parallelize); + fprintf(fp, "\tactive_checks_enabled\t%d\n", temp_service->checks_enabled); + fprintf(fp, "\tpassive_checks_enabled\t%d\n", temp_service->accept_passive_checks); + fprintf(fp, "\tobsess\t%d\n", temp_service->obsess); + fprintf(fp, "\tevent_handler_enabled\t%d\n", temp_service->event_handler_enabled); + fprintf(fp, "\tlow_flap_threshold\t%f\n", temp_service->low_flap_threshold); + fprintf(fp, "\thigh_flap_threshold\t%f\n", temp_service->high_flap_threshold); + fprintf(fp, "\tflap_detection_enabled\t%d\n", temp_service->flap_detection_enabled); + fprintf(fp, "\tflap_detection_options\t%s\n", opts2str(temp_service->flap_detection_options, service_flag_map, 'o')); + fprintf(fp, "\tfreshness_threshold\t%d\n", temp_service->freshness_threshold); + fprintf(fp, "\tcheck_freshness\t%d\n", temp_service->check_freshness); + fprintf(fp, "\tnotification_options\t%s\n", opts2str(temp_service->notification_options, service_flag_map, 'r')); + fprintf(fp, "\tnotifications_enabled\t%d\n", temp_service->notifications_enabled); + fprintf(fp, "\tnotification_interval\t%f\n", temp_service->notification_interval); + fprintf(fp, "\tfirst_notification_delay\t%f\n", temp_service->first_notification_delay); + fprintf(fp, "\tstalking_options\t%s\n", opts2str(temp_service->stalking_options, service_flag_map, 'o')); + fprintf(fp, "\tprocess_perf_data\t%d\n", temp_service->process_performance_data); + if(temp_service->icon_image) + fprintf(fp, "\ticon_image\t%s\n", temp_service->icon_image); + if(temp_service->icon_image_alt) + fprintf(fp, "\ticon_image_alt\t%s\n", temp_service->icon_image_alt); + if(temp_service->notes) + fprintf(fp, "\tnotes\t%s\n", temp_service->notes); + if(temp_service->notes_url) + fprintf(fp, "\tnotes_url\t%s\n", temp_service->notes_url); + if(temp_service->action_url) + fprintf(fp, "\taction_url\t%s\n", temp_service->action_url); + fprintf(fp, "\tretain_status_information\t%d\n", temp_service->retain_status_information); + fprintf(fp, "\tretain_nonstatus_information\t%d\n", temp_service->retain_nonstatus_information); + + /* custom variables */ + fcache_customvars(fp, temp_service->custom_variables); + fprintf(fp, "\t}\n\n"); +} + +void fcache_servicedependency(FILE *fp, servicedependency *temp_servicedependency) +{ + fprintf(fp, "define servicedependency {\n"); + fprintf(fp, "\thost_name\t%s\n", temp_servicedependency->host_name); + fprintf(fp, "\tservice_description\t%s\n", temp_servicedependency->service_description); + fprintf(fp, "\tdependent_host_name\t%s\n", temp_servicedependency->dependent_host_name); + fprintf(fp, "\tdependent_service_description\t%s\n", temp_servicedependency->dependent_service_description); + if(temp_servicedependency->dependency_period) + fprintf(fp, "\tdependency_period\t%s\n", temp_servicedependency->dependency_period); + fprintf(fp, "\tinherits_parent\t%d\n", temp_servicedependency->inherits_parent); + fprintf(fp, "\t%s_failure_options\t%s\n", + temp_servicedependency->dependency_type == NOTIFICATION_DEPENDENCY ? "notification" : "execution", + opts2str(temp_servicedependency->failure_options, service_flag_map, 'o')); + fprintf(fp, "\t}\n\n"); +} + +void fcache_serviceescalation(FILE *fp, serviceescalation *temp_serviceescalation) +{ + fprintf(fp, "define serviceescalation {\n"); + fprintf(fp, "\thost_name\t%s\n", temp_serviceescalation->host_name); + fprintf(fp, "\tservice_description\t%s\n", temp_serviceescalation->description); + fprintf(fp, "\tfirst_notification\t%d\n", temp_serviceescalation->first_notification); + fprintf(fp, "\tlast_notification\t%d\n", temp_serviceescalation->last_notification); + fprintf(fp, "\tnotification_interval\t%f\n", temp_serviceescalation->notification_interval); + if(temp_serviceescalation->escalation_period) + fprintf(fp, "\tescalation_period\t%s\n", temp_serviceescalation->escalation_period); + fprintf(fp, "\tescalation_options\t%s\n", opts2str(temp_serviceescalation->escalation_options, service_flag_map, 'r')); + + if(temp_serviceescalation->contacts) { + contactsmember *cl; + fprintf(fp, "\tcontacts\t"); + for(cl = temp_serviceescalation->contacts; cl; cl = cl->next) + fprintf(fp, "%s%c", cl->contact_ptr->name, cl->next ? ',' : '\n'); + } + if(temp_serviceescalation->contact_groups) { + contactgroupsmember *cgl; + fprintf(fp, "\tcontact_groups\t"); + for (cgl = temp_serviceescalation->contact_groups; cgl; cgl = cgl->next) + fprintf(fp, "%s%c", cgl->group_name, cgl->next ? ',' : '\n'); + } + fprintf(fp, "\t}\n\n"); +} + +void fcache_hostdependency(FILE *fp, hostdependency *temp_hostdependency) +{ + fprintf(fp, "define hostdependency {\n"); + fprintf(fp, "\thost_name\t%s\n", temp_hostdependency->host_name); + fprintf(fp, "\tdependent_host_name\t%s\n", temp_hostdependency->dependent_host_name); + if(temp_hostdependency->dependency_period) + fprintf(fp, "\tdependency_period\t%s\n", temp_hostdependency->dependency_period); + fprintf(fp, "\tinherits_parent\t%d\n", temp_hostdependency->inherits_parent); + fprintf(fp, "\t%s_failure_options\t%s\n", + temp_hostdependency->dependency_type == NOTIFICATION_DEPENDENCY ? "notification" : "execution", + opts2str(temp_hostdependency->failure_options, host_flag_map, 'o')); + fprintf(fp, "\t}\n\n"); +} + +void fcache_hostescalation(FILE *fp, hostescalation *temp_hostescalation) +{ + fprintf(fp, "define hostescalation {\n"); + fprintf(fp, "\thost_name\t%s\n", temp_hostescalation->host_name); + fprintf(fp, "\tfirst_notification\t%d\n", temp_hostescalation->first_notification); + fprintf(fp, "\tlast_notification\t%d\n", temp_hostescalation->last_notification); + fprintf(fp, "\tnotification_interval\t%f\n", temp_hostescalation->notification_interval); + if(temp_hostescalation->escalation_period) + fprintf(fp, "\tescalation_period\t%s\n", temp_hostescalation->escalation_period); + fprintf(fp, "\tescalation_options\t%s\n", opts2str(temp_hostescalation->escalation_options, host_flag_map, 'r')); + + fcache_contactlist(fp, "\tcontacts\t", temp_hostescalation->contacts); + fcache_contactgrouplist(fp, "\tcontact_groups\t", temp_hostescalation->contact_groups); + fprintf(fp, "\t}\n\n"); +} + +/* writes cached object definitions for use by web interface */ +int fcache_objects(char *cache_file) { + FILE *fp = NULL; + time_t current_time = 0L; + unsigned int i; + + /* some people won't want to cache their objects */ + if(!cache_file || !strcmp(cache_file, "/dev/null")) + return OK; + + time(¤t_time); + + /* open the cache file for writing */ + fp = fopen(cache_file, "w"); + if(fp == NULL) { + logit(NSLOG_CONFIG_WARNING, TRUE, "Warning: Could not open object cache file '%s' for writing!\n", cache_file); + return ERROR; + } + + /* write header to cache file */ + fprintf(fp, "########################################\n"); + fprintf(fp, "# NAGIOS OBJECT CACHE 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"); + fprintf(fp, "# Created: %s", ctime(¤t_time)); + fprintf(fp, "########################################\n\n"); + + + /* cache timeperiods */ + for(i = 0; i < num_objects.timeperiods; i++) + fcache_timeperiod(fp, timeperiod_ary[i]); + + /* cache commands */ + for(i = 0; i < num_objects.commands; i++) + fcache_command(fp, command_ary[i]); + + /* cache contactgroups */ + for(i = 0; i < num_objects.contactgroups; i++) + fcache_contactgroup(fp, contactgroup_ary[i]); + + /* cache hostgroups */ + for(i = 0; i < num_objects.hostgroups; i++) + fcache_hostgroup(fp, hostgroup_ary[i]); + + /* cache servicegroups */ + for(i = 0; i < num_objects.servicegroups; i++) + fcache_servicegroup(fp, servicegroup_ary[i]); + + /* cache contacts */ + for(i = 0; i < num_objects.contacts; i++) + fcache_contact(fp, contact_ary[i]); + + /* cache hosts */ + for(i = 0; i < num_objects.hosts; i++) + fcache_host(fp, host_ary[i]); + + /* cache services */ + for(i = 0; i < num_objects.services; i++) + fcache_service(fp, service_ary[i]); + + /* cache service dependencies */ + for(i = 0; i < num_objects.servicedependencies; i++) + fcache_servicedependency(fp, servicedependency_ary[i]); + + /* cache service escalations */ + for(i = 0; i < num_objects.serviceescalations; i++) + fcache_serviceescalation(fp, serviceescalation_ary[i]); + + /* cache host dependencies */ + for(i = 0; i < num_objects.hostdependencies; i++) + fcache_hostdependency(fp, hostdependency_ary[i]); + + /* cache host escalations */ + for(i = 0; i < num_objects.hostescalations; i++) + fcache_hostescalation(fp, hostescalation_ary[i]); + + fclose(fp); + + return OK; + } +#endif diff --git a/common/shared.c b/common/shared.c index 2e61d80..4e697c2 100644 --- a/common/shared.c +++ b/common/shared.c @@ -1,14 +1,106 @@ #include "../include/config.h" #include "../include/common.h" +#include "../include/locations.h" +#include "../include/defaults.h" /* * This file holds random utility functions shared by cgi's and - * core. + * core, as well as all global variables needed by both. */ -extern int date_format; +int date_format; +int interval_length; +char *illegal_output_chars; +char illegal_output_char_map[] = CHAR_MAP_INIT(0); +time_t program_start = 0L; +int check_external_commands; +int log_rotation_method; + +char *object_cache_file; +struct object_count num_objects; + +int process_performance_data; +char *status_file; + +int nagios_pid = 0; +int daemon_mode = FALSE; + +time_t last_log_rotation = 0L; + +int check_external_commands; + +int enable_timing_point = FALSE; /* cgi's never set this to TRUE */ + +int enable_flap_detection; +int enable_notifications; +int execute_service_checks; +int accept_passive_service_checks; +int execute_host_checks; +int accept_passive_host_checks; +int enable_event_handlers; +int obsess_over_services; +int obsess_over_hosts; + +char *config_file_dir = NULL; + +void init_shared_cfg_vars(int first_time) { + date_format = DATE_FORMAT_US; + interval_length = DEFAULT_INTERVAL_LENGTH; + if(first_time) { + /* Not sure why these are not reset in reset_variables() */ + illegal_output_chars = NULL; + } + program_start = 0L; + log_rotation_method = LOG_ROTATION_NONE; + + object_cache_file = strdup(DEFAULT_OBJECT_CACHE_FILE); + + process_performance_data = DEFAULT_PROCESS_PERFORMANCE_DATA; + status_file = NULL; + + check_external_commands = DEFAULT_CHECK_EXTERNAL_COMMANDS; + + enable_flap_detection = DEFAULT_ENABLE_FLAP_DETECTION; + enable_notifications = TRUE; + execute_service_checks = TRUE; + accept_passive_service_checks = TRUE; + execute_host_checks = TRUE; + accept_passive_host_checks = TRUE; + enable_event_handlers = TRUE; + obsess_over_services = FALSE; + obsess_over_hosts = FALSE; + + return; +} + + +/* silly debug-ish helper used to track down hotspots in config parsing */ +void timing_point(const char *fmt, ...) { + static struct timeval last = {0, 0}, first = {0, 0}; + struct timeval now; + va_list ap; + + if(!enable_timing_point) + return; + + if(first.tv_sec == 0) { + gettimeofday(&first, NULL); + last.tv_sec = first.tv_sec; + last.tv_usec = first.tv_usec; + printf("[0.0000 (+0.0000)] "); + } + else { + gettimeofday(&now, NULL); + printf("[%.4f (+%.4f)] ", tv_delta_f(&first, &now), tv_delta_f(&last, &now)); + last.tv_sec = now.tv_sec; + last.tv_usec = now.tv_usec; + } + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); + } /* fix the problem with strtok() skipping empty options between tokens */ -char *my_strtok(char *buffer, char *tokens) { +char *my_strtok(char *buffer, const char *tokens) { char *token_position = NULL; char *sequence_head = NULL; static char *my_strtok_buffer = NULL; @@ -81,7 +173,7 @@ char *my_strsep(char **stringp, const char *delim) { } /* open a file read-only via mmap() */ -mmapfile *mmap_fopen(char *filename) { +mmapfile *mmap_fopen(const char *filename) { mmapfile *new_mmapfile = NULL; int fd = 0; void *mmap_buf = NULL; @@ -400,12 +492,12 @@ void get_datetime_string(time_t * raw_time, char *buffer, int buffer_length, int month; int day; int year; - char *weekdays[7] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; - char *months[12] = { - "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sept", + const char *weekdays[7] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; + const char *months[12] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; - char *tzone = ""; + const char *tzone = ""; if(raw_time == NULL) time(&t); @@ -425,7 +517,7 @@ void get_datetime_string(time_t * raw_time, char *buffer, int buffer_length, year = tm_ptr->tm_year + 1900; #ifdef HAVE_TM_ZONE - tzone = (char *)(tm_ptr->tm_zone); + tzone = tm_ptr->tm_zone; #else tzone = (tm_ptr->tm_isdst) ? tzname[1] : tzname[0]; #endif diff --git a/common/statusdata.c b/common/statusdata.c index 87e2c7c..8d5ed2f 100644 --- a/common/statusdata.c +++ b/common/statusdata.c @@ -2,8 +2,6 @@ * * STATUSDATA.C - External status data for Nagios CGIs * - * Copyright (c) 2000-2006 Ethan Galstad (egalstad@nagios.org) - * Last Modified: 10-19-2006 * * License: * @@ -28,25 +26,15 @@ #include "../include/common.h" #include "../include/objects.h" #include "../include/statusdata.h" +#include "../xdata/xsddefault.h" /* default routines */ -#ifdef NSCORE +#ifdef NSCGI +#include "../include/cgiutils.h" +#else #include "../include/nagios.h" #include "../include/broker.h" #endif -#ifdef NSCGI -#include "../include/cgiutils.h" -#endif -/**** IMPLEMENTATION SPECIFIC HEADER FILES ****/ - -#ifdef USE_XSDDEFAULT -#include "../xdata/xsddefault.h" /* default routines */ -#endif - - -#ifdef NSCORE -extern int aggregate_status_updates; -#endif #ifdef NSCGI hoststatus *hoststatus_list = NULL; @@ -69,15 +57,8 @@ extern int use_pending_states; /******************************************************************/ /* initializes status data at program start */ -int initialize_status_data(char *config_file) { - int result = OK; - - /**** IMPLEMENTATION-SPECIFIC CALLS ****/ -#ifdef USE_XSDDEFAULT - result = xsddefault_initialize_status_data(config_file); -#endif - - return result; +int initialize_status_data(const char *cfgfile) { + return xsddefault_initialize_status_data(cfgfile); } @@ -90,33 +71,19 @@ int update_all_status_data(void) { broker_aggregated_status_data(NEBTYPE_AGGREGATEDSTATUS_STARTDUMP, NEBFLAG_NONE, NEBATTR_NONE, NULL); #endif - /**** IMPLEMENTATION-SPECIFIC CALLS ****/ -#ifdef USE_XSDDEFAULT result = xsddefault_save_status_data(); -#endif #ifdef USE_EVENT_BROKER /* send data to event broker */ broker_aggregated_status_data(NEBTYPE_AGGREGATEDSTATUS_ENDDUMP, NEBFLAG_NONE, NEBATTR_NONE, NULL); #endif - - if(result != OK) - return ERROR; - - return OK; + return result; } /* cleans up status data before program termination */ -int cleanup_status_data(char *config_file, int delete_status_data) { - int result = OK; - - /**** IMPLEMENTATION-SPECIFIC CALLS ****/ -#ifdef USE_XSDDEFAULT - result = xsddefault_cleanup_status_data(config_file, delete_status_data); -#endif - - return result; +int cleanup_status_data(int delete_status_data) { + return xsddefault_cleanup_status_data(delete_status_data); } @@ -130,12 +97,6 @@ int update_program_status(int aggregated_dump) { broker_program_status(NEBTYPE_PROGRAMSTATUS_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, NULL); #endif - /* currently a noop if aggregated updates is TRUE */ - - /* update all status data if we're not aggregating updates */ - if(aggregate_status_updates == FALSE) - update_all_status_data(); - return OK; } @@ -150,12 +111,6 @@ int update_host_status(host *hst, int aggregated_dump) { broker_host_status(NEBTYPE_HOSTSTATUS_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, hst, NULL); #endif - /* currently a noop if aggregated updates is TRUE */ - - /* update all status data if we're not aggregating updates */ - if(aggregate_status_updates == FALSE) - update_all_status_data(); - return OK; } @@ -170,12 +125,6 @@ int update_service_status(service *svc, int aggregated_dump) { broker_service_status(NEBTYPE_SERVICESTATUS_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, svc, NULL); #endif - /* currently a noop if aggregated updates is TRUE */ - - /* update all status data if we're not aggregating updates */ - if(aggregate_status_updates == FALSE) - update_all_status_data(); - return OK; } @@ -190,12 +139,6 @@ int update_contact_status(contact *cntct, int aggregated_dump) { broker_contact_status(NEBTYPE_CONTACTSTATUS_UPDATE, NEBFLAG_NONE, NEBATTR_NONE, cntct, NULL); #endif - /* currently a noop if aggregated updates is TRUE */ - - /* update all status data if we're not aggregating updates */ - if(aggregate_status_updates == FALSE) - update_all_status_data(); - return OK; } #endif @@ -212,18 +155,8 @@ int update_contact_status(contact *cntct, int aggregated_dump) { /* reads in all status data */ -int read_status_data(char *config_file, int options) { - int result = OK; - - /**** IMPLEMENTATION-SPECIFIC CALLS ****/ -#ifdef USE_XSDDEFAULT - result = xsddefault_read_status_data(config_file, options); -#endif -#ifdef USE_XSDDB - result = xsddb_read_status_data(config_file, options); -#endif - - return result; +int read_status_data(const char *status_file_name, int options) { + return xsddefault_read_status_data(status_file_name, options); } @@ -333,16 +266,16 @@ int add_host_status(hoststatus *new_hoststatus) { if(new_hoststatus != NULL) { switch(new_hoststatus->status) { case 0: - new_hoststatus->status = HOST_UP; + new_hoststatus->status = SD_HOST_UP; break; case 1: - new_hoststatus->status = HOST_DOWN; + new_hoststatus->status = SD_HOST_DOWN; break; case 2: - new_hoststatus->status = HOST_UNREACHABLE; + new_hoststatus->status = SD_HOST_UNREACHABLE; break; default: - new_hoststatus->status = HOST_UP; + new_hoststatus->status = SD_HOST_UP; break; } if(new_hoststatus->has_been_checked == FALSE) { @@ -569,7 +502,4 @@ int get_servicestatus_count(char *host_name, int type) { return count; } - - #endif - diff --git a/config.guess b/config.guess index 2b03b48..c4bd827 100755 --- a/config.guess +++ b/config.guess @@ -1,14 +1,12 @@ #! /bin/sh # Attempt to guess a canonical system name. -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, -# Inc. +# Copyright 1992-2016 Free Software Foundation, Inc. -timestamp='2006-12-08' +timestamp='2016-05-15' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but @@ -17,26 +15,22 @@ timestamp='2006-12-08' # General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA -# 02110-1301, USA. +# along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - - -# Originally written by Per Bothner . -# Please send patches to . Submit a context -# diff and a properly formatted ChangeLog entry. +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). # -# This script attempts to guess a canonical system name similar to -# config.sub. If it succeeds, it prints the system name on stdout, and -# exits with 0. Otherwise, it exits with 1. +# Originally written by Per Bothner; maintained since 2000 by Ben Elliston. # -# The plan is that this can be called by configure scripts if you -# don't specify an explicit build system type. +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess +# +# Please send patches to . + me=`echo "$0" | sed -e 's,.*/,,'` @@ -56,8 +50,7 @@ version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 -Free Software Foundation, Inc. +Copyright 1992-2016 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -139,12 +132,33 @@ UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown +case "${UNAME_SYSTEM}" in +Linux|GNU|GNU/*) + # If the system lacks a compiler, then just pick glibc. + # We could probably try harder. + LIBC=gnu + + eval $set_cc_for_build + cat <<-EOF > $dummy.c + #include + #if defined(__UCLIBC__) + LIBC=uclibc + #elif defined(__dietlibc__) + LIBC=dietlibc + #else + LIBC=gnu + #endif + EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'` + ;; +esac + # Note: order is significant - the case branches are not exclusive. case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or - # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward @@ -154,23 +168,33 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" - UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ - /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ + /sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || \ + echo unknown)` case "${UNAME_MACHINE_ARCH}" in armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; sh5el) machine=sh5le-unknown ;; + earmv*) + arch=`echo ${UNAME_MACHINE_ARCH} | sed -e 's,^e\(armv[0-9]\).*$,\1,'` + endian=`echo ${UNAME_MACHINE_ARCH} | sed -ne 's,^.*\(eb\)$,\1,p'` + machine=${arch}${endian}-unknown + ;; *) machine=${UNAME_MACHINE_ARCH}-unknown ;; esac # The Operating System including object format, if it has switched - # to ELF recently, or will in the future. + # to ELF recently (or will in the future) and ABI. case "${UNAME_MACHINE_ARCH}" in + earm*) + os=netbsdelf + ;; arm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep __ELF__ >/dev/null + | grep -q __ELF__ then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? @@ -180,7 +204,14 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in fi ;; *) - os=netbsd + os=netbsd + ;; + esac + # Determine ABI tags. + case "${UNAME_MACHINE_ARCH}" in + earm*) + expr='s/^earmv[0-9]/-eabi/;s/eb$//' + abi=`echo ${UNAME_MACHINE_ARCH} | sed -e "$expr"` ;; esac # The OS release @@ -193,18 +224,26 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in release='-gnu' ;; *) - release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + release=`echo ${UNAME_RELEASE} | sed -e 's/[-_].*//' | cut -d. -f1,2` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. - echo "${machine}-${os}${release}" + echo "${machine}-${os}${release}${abi}" + exit ;; + *:Bitrig:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} exit ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} exit ;; + *:LibertyBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-libertybsd${UNAME_RELEASE} + exit ;; *:ekkoBSD:*:*) echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} exit ;; @@ -217,13 +256,16 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:MirBSD:*:*) echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} exit ;; + *:Sortix:*:*) + echo ${UNAME_MACHINE}-unknown-sortix + exit ;; alpha:OSF1:*:*) case $UNAME_RELEASE in *4.0) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` ;; *5.*) - UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` ;; esac # According to Compaq, /usr/sbin/psrinfo has been available on @@ -233,43 +275,46 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` case "$ALPHA_CPU_TYPE" in "EV4 (21064)") - UNAME_MACHINE="alpha" ;; + UNAME_MACHINE=alpha ;; "EV4.5 (21064)") - UNAME_MACHINE="alpha" ;; + UNAME_MACHINE=alpha ;; "LCA4 (21066/21068)") - UNAME_MACHINE="alpha" ;; + UNAME_MACHINE=alpha ;; "EV5 (21164)") - UNAME_MACHINE="alphaev5" ;; + UNAME_MACHINE=alphaev5 ;; "EV5.6 (21164A)") - UNAME_MACHINE="alphaev56" ;; + UNAME_MACHINE=alphaev56 ;; "EV5.6 (21164PC)") - UNAME_MACHINE="alphapca56" ;; + UNAME_MACHINE=alphapca56 ;; "EV5.7 (21164PC)") - UNAME_MACHINE="alphapca57" ;; + UNAME_MACHINE=alphapca57 ;; "EV6 (21264)") - UNAME_MACHINE="alphaev6" ;; + UNAME_MACHINE=alphaev6 ;; "EV6.7 (21264A)") - UNAME_MACHINE="alphaev67" ;; + UNAME_MACHINE=alphaev67 ;; "EV6.8CB (21264C)") - UNAME_MACHINE="alphaev68" ;; + UNAME_MACHINE=alphaev68 ;; "EV6.8AL (21264B)") - UNAME_MACHINE="alphaev68" ;; + UNAME_MACHINE=alphaev68 ;; "EV6.8CX (21264D)") - UNAME_MACHINE="alphaev68" ;; + UNAME_MACHINE=alphaev68 ;; "EV6.9A (21264/EV69A)") - UNAME_MACHINE="alphaev69" ;; + UNAME_MACHINE=alphaev69 ;; "EV7 (21364)") - UNAME_MACHINE="alphaev7" ;; + UNAME_MACHINE=alphaev7 ;; "EV7.9 (21364A)") - UNAME_MACHINE="alphaev79" ;; + UNAME_MACHINE=alphaev79 ;; esac # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. - echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - exit ;; + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` + # Reset EXIT trap before exiting to avoid spurious non-zero exit code. + exitcode=$? + trap '' 0 + exit $exitcode ;; Alpha\ *:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # Should we change UNAME_MACHINE based on the output of uname instead @@ -295,12 +340,12 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in echo s390-ibm-zvmoe exit ;; *:OS400:*:*) - echo powerpc-ibm-os400 + echo powerpc-ibm-os400 exit ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} exit ;; - arm:riscos:*:*|arm:RISCOS:*:*) + arm*:riscos:*:*|arm*:RISCOS:*:*) echo arm-unknown-riscos exit ;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) @@ -324,14 +369,33 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in case `/usr/bin/uname -p` in sparc) echo sparc-icl-nx7; exit ;; esac ;; + s390x:SunOS:*:*) + echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; - i86pc:SunOS:5.*:*) - echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) + echo i386-pc-auroraux${UNAME_RELEASE} + exit ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + eval $set_cc_for_build + SUN_ARCH=i386 + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if [ "$CC_FOR_BUILD" != no_compiler_found ]; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH=x86_64 + fi + fi + echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize @@ -353,7 +417,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in exit ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` - test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + test "x${UNAME_RELEASE}" = x && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) echo m68k-sun-sunos${UNAME_RELEASE} @@ -375,23 +439,23 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} + echo m68k-atari-mint${UNAME_RELEASE} exit ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} - exit ;; + exit ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} + echo m68k-atari-mint${UNAME_RELEASE} exit ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) - echo m68k-milan-mint${UNAME_RELEASE} - exit ;; + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) - echo m68k-hades-mint${UNAME_RELEASE} - exit ;; + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) - echo m68k-unknown-mint${UNAME_RELEASE} - exit ;; + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; m68k:machten:*:*) echo m68k-apple-machten${UNAME_RELEASE} exit ;; @@ -461,8 +525,8 @@ EOF echo m88k-motorola-sysv3 exit ;; AViiON:dgux:*:*) - # DG/UX returns AViiON for all architectures - UNAME_PROCESSOR=`/usr/bin/uname -p` + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] then if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ @@ -475,7 +539,7 @@ EOF else echo i586-dg-dgux${UNAME_RELEASE} fi - exit ;; + exit ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 exit ;; @@ -532,15 +596,16 @@ EOF echo rs6000-ibm-aix3.2 fi exit ;; - *:AIX:*:[45]) + *:AIX:*:[4567]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi - if [ -x /usr/bin/oslevel ] ; then - IBM_REV=`/usr/bin/oslevel` + if [ -x /usr/bin/lslpp ] ; then + IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | + awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi @@ -575,58 +640,58 @@ EOF 9000/[678][0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` - sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` - case "${sc_cpu_version}" in - 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 - 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 - 532) # CPU_PA_RISC2_0 - case "${sc_kernel_bits}" in - 32) HP_ARCH="hppa2.0n" ;; - 64) HP_ARCH="hppa2.0w" ;; - '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 - esac ;; - esac + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0 + 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH=hppa2.0n ;; + 64) HP_ARCH=hppa2.0w ;; + '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20 + esac ;; + esac fi if [ "${HP_ARCH}" = "" ]; then eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c + sed 's/^ //' << EOF >$dummy.c - #define _HPUX_SOURCE - #include - #include + #define _HPUX_SOURCE + #include + #include - int main () - { - #if defined(_SC_KERNEL_BITS) - long bits = sysconf(_SC_KERNEL_BITS); - #endif - long cpu = sysconf (_SC_CPU_VERSION); + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); - switch (cpu) - { - case CPU_PA_RISC1_0: puts ("hppa1.0"); break; - case CPU_PA_RISC1_1: puts ("hppa1.1"); break; - case CPU_PA_RISC2_0: - #if defined(_SC_KERNEL_BITS) - switch (bits) - { - case 64: puts ("hppa2.0w"); break; - case 32: puts ("hppa2.0n"); break; - default: puts ("hppa2.0"); break; - } break; - #else /* !defined(_SC_KERNEL_BITS) */ - puts ("hppa2.0"); break; - #endif - default: puts ("hppa1.0"); break; - } - exit (0); - } + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } EOF - (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + (CCOPTS="" $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac - if [ ${HP_ARCH} = "hppa2.0w" ] + if [ ${HP_ARCH} = hppa2.0w ] then eval $set_cc_for_build @@ -639,12 +704,12 @@ EOF # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess # => hppa64-hp-hpux11.23 - if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | - grep __LP64__ >/dev/null + if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | + grep -q __LP64__ then - HP_ARCH="hppa2.0w" + HP_ARCH=hppa2.0w else - HP_ARCH="hppa64" + HP_ARCH=hppa64 fi fi echo ${HP_ARCH}-hp-hpux${HPUX_REV} @@ -711,22 +776,22 @@ EOF exit ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd - exit ;; + exit ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi - exit ;; + exit ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd - exit ;; + exit ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd - exit ;; + exit ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd - exit ;; + exit ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; @@ -749,15 +814,15 @@ EOF echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) - FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` - echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit ;; + FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` + FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; 5000:UNIX_System_V:4.*:*) - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` - echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} @@ -769,37 +834,51 @@ EOF echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} exit ;; *:FreeBSD:*:*) - case ${UNAME_MACHINE} in - pc98) - echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + UNAME_PROCESSOR=`/usr/bin/uname -p` + case ${UNAME_PROCESSOR} in amd64) echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; *) - echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; esac exit ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin exit ;; - i*:MINGW*:*) + *:MINGW64*:*) + echo ${UNAME_MACHINE}-pc-mingw64 + exit ;; + *:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit ;; + *:MSYS*:*) + echo ${UNAME_MACHINE}-pc-msys + exit ;; i*:windows32*:*) - # uname -m includes "-pc" on this system. - echo ${UNAME_MACHINE}-mingw32 + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 exit ;; i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 exit ;; - x86:Interix*:[3456]*) - echo i586-pc-interix${UNAME_RELEASE} - exit ;; - EM64T:Interix*:[3456]* | authenticamd:Interix*:[3456]*) - echo x86_64-unknown-interix${UNAME_RELEASE} - exit ;; + *:Interix*:*) + case ${UNAME_MACHINE} in + x86) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + authenticamd | genuineintel | EM64T) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + IA64) + echo ia64-unknown-interix${UNAME_RELEASE} + exit ;; + esac ;; [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) echo i${UNAME_MACHINE}-pc-mks exit ;; + 8664:Windows_NT:*) + echo x86_64-pc-mks + exit ;; i*:Windows_NT*:* | Pentium*:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we @@ -820,93 +899,21 @@ EOF exit ;; *:GNU:*:*) # the GNU system - echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` exit ;; *:GNU/*:*:*) # other systems with GNU libc and userland - echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} exit ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix exit ;; - arm*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + aarch64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; - avr32*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - cris:Linux:*:*) - echo cris-axis-linux-gnu - exit ;; - crisv32:Linux:*:*) - echo crisv32-axis-linux-gnu - exit ;; - frv:Linux:*:*) - echo frv-unknown-linux-gnu - exit ;; - ia64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - m32r*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - m68*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - mips:Linux:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #undef CPU - #undef mips - #undef mipsel - #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) - CPU=mipsel - #else - #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) - CPU=mips - #else - CPU= - #endif - #endif -EOF - eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' - /^CPU/{ - s: ::g - p - }'`" - test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } - ;; - mips64:Linux:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #undef CPU - #undef mips64 - #undef mips64el - #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) - CPU=mips64el - #else - #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) - CPU=mips64 - #else - CPU= - #endif - #endif -EOF - eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' - /^CPU/{ - s: ::g - p - }'`" - test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } - ;; - or32:Linux:*:*) - echo or32-unknown-linux-gnu - exit ;; - ppc:Linux:*:*) - echo powerpc-unknown-linux-gnu - exit ;; - ppc64:Linux:*:*) - echo powerpc64-unknown-linux-gnu + aarch64_be:Linux:*:*) + UNAME_MACHINE=aarch64_be + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in @@ -917,106 +924,138 @@ EOF EV6) UNAME_MACHINE=alphaev6 ;; EV67) UNAME_MACHINE=alphaev67 ;; EV68*) UNAME_MACHINE=alphaev68 ;; - esac - objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null - if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi - echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 + if test "$?" = 0 ; then LIBC=gnulibc1 ; fi + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + arc:Linux:*:* | arceb:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + arm*:Linux:*:*) + eval $set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + else + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi + else + echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf + fi + fi + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + cris:Linux:*:*) + echo ${UNAME_MACHINE}-axis-linux-${LIBC} + exit ;; + crisv32:Linux:*:*) + echo ${UNAME_MACHINE}-axis-linux-${LIBC} + exit ;; + e2k:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + frv:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + hexagon:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + i*86:Linux:*:*) + echo ${UNAME_MACHINE}-pc-linux-${LIBC} + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + k1om:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + mips:Linux:*:* | mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=${UNAME_MACHINE}el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=${UNAME_MACHINE} + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } + ;; + openrisc*:Linux:*:*) + echo or1k-unknown-linux-${LIBC} + exit ;; + or32:Linux:*:* | or1k*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + padre:Linux:*:*) + echo sparc-unknown-linux-${LIBC} + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-${LIBC} exit ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in - PA7*) echo hppa1.1-unknown-linux-gnu ;; - PA8*) echo hppa2.0-unknown-linux-gnu ;; - *) echo hppa-unknown-linux-gnu ;; + PA7*) echo hppa1.1-unknown-linux-${LIBC} ;; + PA8*) echo hppa2.0-unknown-linux-${LIBC} ;; + *) echo hppa-unknown-linux-${LIBC} ;; esac exit ;; - parisc64:Linux:*:* | hppa64:Linux:*:*) - echo hppa64-unknown-linux-gnu + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-${LIBC} + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-${LIBC} + exit ;; + ppc64le:Linux:*:*) + echo powerpc64le-unknown-linux-${LIBC} + exit ;; + ppcle:Linux:*:*) + echo powerpcle-unknown-linux-${LIBC} exit ;; s390:Linux:*:* | s390x:Linux:*:*) - echo ${UNAME_MACHINE}-ibm-linux + echo ${UNAME_MACHINE}-ibm-linux-${LIBC} exit ;; sh64*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; sh*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; sparc:Linux:*:* | sparc64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + tile*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; vax:Linux:*:*) - echo ${UNAME_MACHINE}-dec-linux-gnu + echo ${UNAME_MACHINE}-dec-linux-${LIBC} exit ;; x86_64:Linux:*:*) - echo x86_64-unknown-linux-gnu + echo ${UNAME_MACHINE}-pc-linux-${LIBC} exit ;; - xtensa:Linux:*:*) - echo xtensa-unknown-linux-gnu + xtensa*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; - i*86:Linux:*:*) - # The BFD linker knows what the default object file format is, so - # first see if it will tell us. cd to the root directory to prevent - # problems with other programs or directories called `ld' in the path. - # Set LC_ALL=C to ensure ld outputs messages in English. - ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ - | sed -ne '/supported targets:/!d - s/[ ][ ]*/ /g - s/.*supported targets: *// - s/ .*// - p'` - case "$ld_supported_targets" in - elf32-i386) - TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" - ;; - a.out-i386-linux) - echo "${UNAME_MACHINE}-pc-linux-gnuaout" - exit ;; - coff-i386) - echo "${UNAME_MACHINE}-pc-linux-gnucoff" - exit ;; - "") - # Either a pre-BFD a.out linker (linux-gnuoldld) or - # one that does not give us useful --help. - echo "${UNAME_MACHINE}-pc-linux-gnuoldld" - exit ;; - esac - # Determine whether the default compiler is a.out or elf - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #include - #ifdef __ELF__ - # ifdef __GLIBC__ - # if __GLIBC__ >= 2 - LIBC=gnu - # else - LIBC=gnulibc1 - # endif - # else - LIBC=gnulibc1 - # endif - #else - #if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC) - LIBC=gnu - #else - LIBC=gnuaout - #endif - #endif - #ifdef __dietlibc__ - LIBC=dietlibc - #endif -EOF - eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' - /^LIBC/{ - s: ::g - p - }'`" - test x"${LIBC}" != x && { - echo "${UNAME_MACHINE}-pc-linux-${LIBC}" - exit - } - test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; } - ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both @@ -1024,11 +1063,11 @@ EOF echo i386-sequent-sysv4 exit ;; i*86:UNIX_SV:4.2MP:2.*) - # Unixware is an offshoot of SVR4, but it has its own version - # number series starting with 2... - # I am not positive that other SVR4 systems won't match this, + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. - # Use sysv4.2uw... so that sysv4* matches it. + # Use sysv4.2uw... so that sysv4* matches it. echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} exit ;; i*86:OS/2:*:*) @@ -1045,7 +1084,7 @@ EOF i*86:syllable:*:*) echo ${UNAME_MACHINE}-pc-syllable exit ;; - i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) echo i386-unknown-lynxos${UNAME_RELEASE} exit ;; i*86:*DOS:*:*) @@ -1060,7 +1099,7 @@ EOF fi exit ;; i*86:*:5:[678]*) - # UnixWare 7.x, OpenUNIX and OpenServer 6. + # UnixWare 7.x, OpenUNIX and OpenServer 6. case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; @@ -1088,10 +1127,13 @@ EOF exit ;; pc:*:*:*) # Left here for compatibility: - # uname -m prints for DJGPP always 'pc', but it prints nothing about - # the processor, so we play safe by assuming i386. - echo i386-pc-msdosdjgpp - exit ;; + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configure will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp + exit ;; Intel:Mach:3*:*) echo i386-pc-mach3 exit ;; @@ -1126,8 +1168,18 @@ EOF /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4; exit; } ;; + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) echo m68k-unknown-lynxos${UNAME_RELEASE} exit ;; @@ -1140,7 +1192,7 @@ EOF rs6000:LynxOS:2.*:*) echo rs6000-unknown-lynxos${UNAME_RELEASE} exit ;; - PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) echo powerpc-unknown-lynxos${UNAME_RELEASE} exit ;; SM[BE]S:UNIX_SV:*:*) @@ -1160,10 +1212,10 @@ EOF echo ns32k-sni-sysv fi exit ;; - PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort - # says - echo i586-unisys-sysv4 - exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm @@ -1189,11 +1241,11 @@ EOF exit ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then - echo mips-nec-sysv${UNAME_RELEASE} + echo mips-nec-sysv${UNAME_RELEASE} else - echo mips-unknown-sysv${UNAME_RELEASE} + echo mips-unknown-sysv${UNAME_RELEASE} fi - exit ;; + exit ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos exit ;; @@ -1203,6 +1255,12 @@ EOF BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos exit ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; + x86_64:Haiku:*:*) + echo x86_64-unknown-haiku + exit ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux${UNAME_RELEASE} exit ;; @@ -1218,6 +1276,12 @@ EOF SX-8:SUPER-UX:*:*) echo sx8-nec-superux${UNAME_RELEASE} exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux${UNAME_RELEASE} + exit ;; + SX-ACE:SUPER-UX:*:*) + echo sxace-nec-superux${UNAME_RELEASE} + exit ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} exit ;; @@ -1226,14 +1290,36 @@ EOF exit ;; *:Darwin:*:*) UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown - case $UNAME_PROCESSOR in - unknown) UNAME_PROCESSOR=powerpc ;; - esac + eval $set_cc_for_build + if test "$UNAME_PROCESSOR" = unknown ; then + UNAME_PROCESSOR=powerpc + fi + if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then + if [ "$CC_FOR_BUILD" != no_compiler_found ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + case $UNAME_PROCESSOR in + i386) UNAME_PROCESSOR=x86_64 ;; + powerpc) UNAME_PROCESSOR=powerpc64 ;; + esac + fi + fi + elif test "$UNAME_PROCESSOR" = i386 ; then + # Avoid executing cc on OS X 10.9, as it ships with a stub + # that puts up a graphical alert prompting to install + # developer tools. Any system running Mac OS X 10.7 or + # later (Darwin 11 and later) is required to have a 64-bit + # processor. This is not true of the ARM version of Darwin + # that Apple uses in portable devices. + UNAME_PROCESSOR=x86_64 + fi echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` - if test "$UNAME_PROCESSOR" = "x86"; then + if test "$UNAME_PROCESSOR" = x86; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi @@ -1242,7 +1328,10 @@ EOF *:QNX:*:4*) echo i386-pc-qnx exit ;; - NSE-?:NONSTOP_KERNEL:*:*) + NEO-?:NONSTOP_KERNEL:*:*) + echo neo-tandem-nsk${UNAME_RELEASE} + exit ;; + NSE-*:NONSTOP_KERNEL:*:*) echo nse-tandem-nsk${UNAME_RELEASE} exit ;; NSR-?:NONSTOP_KERNEL:*:*) @@ -1261,7 +1350,7 @@ EOF # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. - if test "$cputype" = "386"; then + if test "$cputype" = 386; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" @@ -1287,13 +1376,13 @@ EOF echo pdp10-unknown-its exit ;; SEI:*:*:SEIUX) - echo mips-sei-seiux${UNAME_RELEASE} + echo mips-sei-seiux${UNAME_RELEASE} exit ;; *:DragonFly:*:*) echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit ;; *:*VMS:*:*) - UNAME_MACHINE=`(uname -p) 2>/dev/null` + UNAME_MACHINE=`(uname -p) 2>/dev/null` case "${UNAME_MACHINE}" in A*) echo alpha-dec-vms ; exit ;; I*) echo ia64-dec-vms ; exit ;; @@ -1303,179 +1392,36 @@ EOF echo i386-pc-xenix exit ;; i*86:skyos:*:*) - echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE} | sed -e 's/ .*$//'` exit ;; i*86:rdos:*:*) echo ${UNAME_MACHINE}-pc-rdos exit ;; + i*86:AROS:*:*) + echo ${UNAME_MACHINE}-pc-aros + exit ;; + x86_64:VMkernel:*:*) + echo ${UNAME_MACHINE}-unknown-esx + exit ;; + amd64:Isilon\ OneFS:*:*) + echo x86_64-unknown-onefs + exit ;; esac -#echo '(No uname command or uname output not recognized.)' 1>&2 -#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 - -eval $set_cc_for_build -cat >$dummy.c < -# include -#endif -main () -{ -#if defined (sony) -#if defined (MIPSEB) - /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, - I don't know.... */ - printf ("mips-sony-bsd\n"); exit (0); -#else -#include - printf ("m68k-sony-newsos%s\n", -#ifdef NEWSOS4 - "4" -#else - "" -#endif - ); exit (0); -#endif -#endif - -#if defined (__arm) && defined (__acorn) && defined (__unix) - printf ("arm-acorn-riscix\n"); exit (0); -#endif - -#if defined (hp300) && !defined (hpux) - printf ("m68k-hp-bsd\n"); exit (0); -#endif - -#if defined (NeXT) -#if !defined (__ARCHITECTURE__) -#define __ARCHITECTURE__ "m68k" -#endif - int version; - version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; - if (version < 4) - printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); - else - printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); - exit (0); -#endif - -#if defined (MULTIMAX) || defined (n16) -#if defined (UMAXV) - printf ("ns32k-encore-sysv\n"); exit (0); -#else -#if defined (CMU) - printf ("ns32k-encore-mach\n"); exit (0); -#else - printf ("ns32k-encore-bsd\n"); exit (0); -#endif -#endif -#endif - -#if defined (__386BSD__) - printf ("i386-pc-bsd\n"); exit (0); -#endif - -#if defined (sequent) -#if defined (i386) - printf ("i386-sequent-dynix\n"); exit (0); -#endif -#if defined (ns32000) - printf ("ns32k-sequent-dynix\n"); exit (0); -#endif -#endif - -#if defined (_SEQUENT_) - struct utsname un; - - uname(&un); - - if (strncmp(un.version, "V2", 2) == 0) { - printf ("i386-sequent-ptx2\n"); exit (0); - } - if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ - printf ("i386-sequent-ptx1\n"); exit (0); - } - printf ("i386-sequent-ptx\n"); exit (0); - -#endif - -#if defined (vax) -# if !defined (ultrix) -# include -# if defined (BSD) -# if BSD == 43 - printf ("vax-dec-bsd4.3\n"); exit (0); -# else -# if BSD == 199006 - printf ("vax-dec-bsd4.3reno\n"); exit (0); -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# endif -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# else - printf ("vax-dec-ultrix\n"); exit (0); -# endif -#endif - -#if defined (alliant) && defined (i860) - printf ("i860-alliant-bsd\n"); exit (0); -#endif - - exit (1); -} -EOF - -$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && - { echo "$SYSTEM_NAME"; exit; } - -# Apollos put the system type in the environment. - -test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } - -# Convex versions that predate uname can use getsysinfo(1) - -if [ -x /usr/convex/getsysinfo ] -then - case `getsysinfo -f cpu_type` in - c1*) - echo c1-convex-bsd - exit ;; - c2*) - if getsysinfo -f scalar_acc - then echo c32-convex-bsd - else echo c2-convex-bsd - fi - exit ;; - c34*) - echo c34-convex-bsd - exit ;; - c38*) - echo c38-convex-bsd - exit ;; - c4*) - echo c4-convex-bsd - exit ;; - esac -fi - cat >&2 < in order to provide the needed -information to handle your system. +If $0 has already been updated, send the following data and any +information you think might be pertinent to config-patches@gnu.org to +provide the necessary information to handle your system. config.guess timestamp = $timestamp diff --git a/config.sub b/config.sub index 4b8cc7b..9feb73b 100755 --- a/config.sub +++ b/config.sub @@ -1,44 +1,40 @@ #! /bin/sh # Configuration validation subroutine script. -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, -# Inc. +# Copyright 1992-2016 Free Software Foundation, Inc. -timestamp='2006-12-08' +timestamp='2016-06-20' -# This file is (in principle) common to ALL GNU software. -# The presence of a machine in this file suggests that SOME GNU software -# can handle that machine. It does not imply ALL GNU software can. -# -# This file is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA -# 02110-1301, USA. +# along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). -# Please send patches to . Submit a context -# diff and a properly formatted ChangeLog entry. +# Please send patches to . # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub + # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. @@ -57,8 +53,7 @@ timestamp='2006-12-08' me=`echo "$0" | sed -e 's,.*/,,'` usage="\ -Usage: $0 [OPTION] CPU-MFR-OPSYS - $0 [OPTION] ALIAS +Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS Canonicalize a configuration name. @@ -72,8 +67,7 @@ Report bugs and patches to ." version="\ GNU config.sub ($timestamp) -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 -Free Software Foundation, Inc. +Copyright 1992-2016 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -120,12 +114,18 @@ esac # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in - nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \ - uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \ + nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ + linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ + knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \ + kopensolaris*-gnu* | \ storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; + android-linux) + os=-linux-android + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown + ;; *) basic_machine=`echo $1 | sed 's/-[^-]*$//'` if [ $basic_machine != $1 ] @@ -148,10 +148,13 @@ case $os in -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ - -apple | -axis | -knuth | -cray) + -apple | -axis | -knuth | -cray | -microblaze*) os= basic_machine=$1 ;; + -bluegene*) + os=-cnk + ;; -sim | -cisco | -oki | -wec | -winbond) os= basic_machine=$1 @@ -166,10 +169,10 @@ case $os in os=-chorusos basic_machine=$1 ;; - -chorusrdb) - os=-chorusrdb + -chorusrdb) + os=-chorusrdb basic_machine=$1 - ;; + ;; -hiux*) os=-hiuxwe2 ;; @@ -214,6 +217,12 @@ case $os in -isc*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; + -lynx*178) + os=-lynxos178 + ;; + -lynx*5) + os=-lynxos5 + ;; -lynx*) os=-lynxos ;; @@ -238,59 +247,91 @@ case $basic_machine in # Some are omitted here because they have special meanings below. 1750a | 580 \ | a29k \ + | aarch64 | aarch64_be \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | am33_2.0 \ - | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ + | arc | arceb \ + | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ + | avr | avr32 \ + | ba \ + | be32 | be64 \ | bfin \ - | c4x | clipper \ + | c4x | c8051 | clipper \ | d10v | d30v | dlx | dsp16xx \ - | fido | fr30 | frv \ + | e2k | epiphany \ + | fido | fr30 | frv | ft32 \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | hexagon \ | i370 | i860 | i960 | ia64 \ | ip2k | iq2000 \ + | k1om \ + | le32 | le64 \ + | lm32 \ | m32c | m32r | m32rle | m68000 | m68k | m88k \ - | maxq | mb | microblaze | mcore \ + | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ - | mips64vr | mips64vrel \ + | mips64octeon | mips64octeonel \ | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ | mips64vr4100 | mips64vr4100el \ | mips64vr4300 | mips64vr4300el \ | mips64vr5000 | mips64vr5000el \ | mips64vr5900 | mips64vr5900el \ | mipsisa32 | mipsisa32el \ | mipsisa32r2 | mipsisa32r2el \ + | mipsisa32r6 | mipsisa32r6el \ | mipsisa64 | mipsisa64el \ | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64r6 | mipsisa64r6el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ + | mipsr5900 | mipsr5900el \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ + | moxie \ | mt \ | msp430 \ - | nios | nios2 \ + | nds32 | nds32le | nds32be \ + | nios | nios2 | nios2eb | nios2el \ | ns16k | ns32k \ - | or32 \ + | open8 | or1k | or1knd | or32 \ | pdp10 | pdp11 | pj | pjl \ - | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ + | powerpc | powerpc64 | powerpc64le | powerpcle \ | pyramid \ + | riscv32 | riscv64 \ + | rl78 | rx \ | score \ - | sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ - | spu | strongarm \ - | tahoe | thumb | tic4x | tic80 | tron \ - | v850 | v850e \ + | spu \ + | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ + | ubicom32 \ + | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ + | visium \ | we32k \ - | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \ - | z8k) + | x86 | xc16x | xstormy16 | xtensa \ + | z8k | z80) basic_machine=$basic_machine-unknown ;; - m6811 | m68hc11 | m6812 | m68hc12) - # Motorola 68HC11/12. + c54x) + basic_machine=tic54x-unknown + ;; + c55x) + basic_machine=tic55x-unknown + ;; + c6x) + basic_machine=tic6x-unknown + ;; + leon|leon[3-9]) + basic_machine=sparc-$basic_machine + ;; + m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) basic_machine=$basic_machine-unknown os=-none ;; @@ -300,6 +341,21 @@ case $basic_machine in basic_machine=mt-unknown ;; + strongarm | thumb | xscale) + basic_machine=arm-unknown + ;; + xgate) + basic_machine=$basic_machine-unknown + os=-none + ;; + xscaleeb) + basic_machine=armeb-unknown + ;; + + xscaleel) + basic_machine=armel-unknown + ;; + # We use `pc' rather than `unknown' # because (1) that's what they normally are, and # (2) the word "unknown" tends to confuse beginning users. @@ -314,64 +370,89 @@ case $basic_machine in # Recognize the basic CPU types with company name. 580-* \ | a29k-* \ + | aarch64-* | aarch64_be-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ - | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* | avr32-* \ + | ba-* \ + | be32-* | be64-* \ | bfin-* | bs2000-* \ - | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ - | clipper-* | craynv-* | cydra-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* \ + | c8051-* | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ - | elxsi-* \ + | e2k-* | elxsi-* \ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | hexagon-* \ | i*86-* | i860-* | i960-* | ia64-* \ | ip2k-* | iq2000-* \ + | k1om-* \ + | le32-* | le64-* \ + | lm32-* \ | m32c-* | m32r-* | m32rle-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ - | m88110-* | m88k-* | maxq-* | mcore-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ + | microblaze-* | microblazeel-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | mips16-* \ | mips64-* | mips64el-* \ - | mips64vr-* | mips64vrel-* \ + | mips64octeon-* | mips64octeonel-* \ | mips64orion-* | mips64orionel-* \ + | mips64r5900-* | mips64r5900el-* \ + | mips64vr-* | mips64vrel-* \ | mips64vr4100-* | mips64vr4100el-* \ | mips64vr4300-* | mips64vr4300el-* \ | mips64vr5000-* | mips64vr5000el-* \ | mips64vr5900-* | mips64vr5900el-* \ | mipsisa32-* | mipsisa32el-* \ | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa32r6-* | mipsisa32r6el-* \ | mipsisa64-* | mipsisa64el-* \ | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64r6-* | mipsisa64r6el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipsr5900-* | mipsr5900el-* \ | mipstx39-* | mipstx39el-* \ | mmix-* \ | mt-* \ | msp430-* \ - | nios-* | nios2-* \ + | nds32-* | nds32le-* | nds32be-* \ + | nios-* | nios2-* | nios2eb-* | nios2el-* \ | none-* | np1-* | ns16k-* | ns32k-* \ + | open8-* \ + | or1k*-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ - | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ | pyramid-* \ - | romp-* | rs6000-* \ - | sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | riscv32-* | riscv64-* \ + | rl78-* | romp-* | rs6000-* | rx-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ | sparclite-* \ - | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \ - | tahoe-* | thumb-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \ + | tahoe-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tile*-* \ | tron-* \ - | v850-* | v850e-* | vax-* \ + | ubicom32-* \ + | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ + | vax-* \ + | visium-* \ | we32k-* \ - | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \ - | xstormy16-* | xtensa-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* \ + | xstormy16-* | xtensa*-* \ | ymp-* \ - | z8k-*) + | z8k-* | z80-*) + ;; + # Recognize the basic CPU types without company name, with glob match. + xtensa*) + basic_machine=$basic_machine-unknown ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. @@ -389,7 +470,7 @@ case $basic_machine in basic_machine=a29k-amd os=-udi ;; - abacus) + abacus) basic_machine=abacus-unknown ;; adobe68k) @@ -435,6 +516,13 @@ case $basic_machine in basic_machine=m68k-apollo os=-bsd ;; + aros) + basic_machine=i386-pc + os=-aros + ;; + asmjs) + basic_machine=asmjs-unknown + ;; aux) basic_machine=m68k-apple os=-aux @@ -443,10 +531,35 @@ case $basic_machine in basic_machine=ns32k-sequent os=-dynix ;; + blackfin) + basic_machine=bfin-unknown + os=-linux + ;; + blackfin-*) + basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + bluegene*) + basic_machine=powerpc-ibm + os=-cnk + ;; + c54x-*) + basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c55x-*) + basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c6x-*) + basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; c90) basic_machine=c90-cray os=-unicos ;; + cegcc) + basic_machine=arm-unknown + os=-cegcc + ;; convex-c1) basic_machine=c1-convex os=-bsd @@ -475,8 +588,8 @@ case $basic_machine in basic_machine=craynv-cray os=-unicosmp ;; - cr16c) - basic_machine=cr16c-unknown + cr16 | cr16-*) + basic_machine=cr16-unknown os=-elf ;; crds | unos) @@ -514,6 +627,10 @@ case $basic_machine in basic_machine=m88k-motorola os=-sysv3 ;; + dicos) + basic_machine=i686-pc + os=-dicos + ;; djgpp) basic_machine=i586-pc os=-msdosdjgpp @@ -526,6 +643,14 @@ case $basic_machine in basic_machine=m68k-bull os=-sysv3 ;; + e500v[12]) + basic_machine=powerpc-unknown + os=$os"spe" + ;; + e500v[12]-*) + basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + os=$os"spe" + ;; ebmon29k) basic_machine=a29k-amd os=-ebmon @@ -629,7 +754,6 @@ case $basic_machine in i370-ibm* | ibm*) basic_machine=i370-ibm ;; -# I'm not sure what "Sysv32" means. Should this be sysv3.2? i*86v32) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv32 @@ -668,6 +792,17 @@ case $basic_machine in basic_machine=m68k-isi os=-sysv ;; + leon-*|leon[3-9]-*) + basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'` + ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; m88k-omron*) basic_machine=m88k-omron ;; @@ -679,10 +814,21 @@ case $basic_machine in basic_machine=ns32k-utek os=-sysv ;; + microblaze*) + basic_machine=microblaze-xilinx + ;; + mingw64) + basic_machine=x86_64-pc + os=-mingw64 + ;; mingw32) - basic_machine=i386-pc + basic_machine=i686-pc os=-mingw32 ;; + mingw32ce) + basic_machine=arm-unknown + os=-mingw32ce + ;; miniframe) basic_machine=m68000-convergent ;; @@ -704,6 +850,10 @@ case $basic_machine in basic_machine=powerpc-unknown os=-morphos ;; + moxiebox) + basic_machine=moxie-unknown + os=-moxiebox + ;; msdos) basic_machine=i386-pc os=-msdos @@ -711,10 +861,18 @@ case $basic_machine in ms1-*) basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` ;; + msys) + basic_machine=i686-pc + os=-msys + ;; mvs) basic_machine=i370-ibm os=-mvs ;; + nacl) + basic_machine=le32-unknown + os=-nacl + ;; ncr3000) basic_machine=i486-ncr os=-sysv4 @@ -779,6 +937,12 @@ case $basic_machine in np1) basic_machine=np1-gould ;; + neo-tandem) + basic_machine=neo-tandem + ;; + nse-tandem) + basic_machine=nse-tandem + ;; nsr-tandem) basic_machine=nsr-tandem ;; @@ -809,6 +973,14 @@ case $basic_machine in basic_machine=i860-intel os=-osf ;; + parisc) + basic_machine=hppa-unknown + os=-linux + ;; + parisc-*) + basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; pbd) basic_machine=sparc-tti ;; @@ -853,9 +1025,10 @@ case $basic_machine in ;; power) basic_machine=power-ibm ;; - ppc) basic_machine=powerpc-unknown + ppc | ppcbe) basic_machine=powerpc-unknown ;; - ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ppc-* | ppcbe-*) + basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle | ppc-le | powerpc-little) basic_machine=powerpcle-unknown @@ -880,7 +1053,11 @@ case $basic_machine in basic_machine=i586-unknown os=-pw32 ;; - rdos) + rdos | rdos64) + basic_machine=x86_64-pc + os=-rdos + ;; + rdos32) basic_machine=i386-pc os=-rdos ;; @@ -949,6 +1126,9 @@ case $basic_machine in basic_machine=i860-stratus os=-sysv4 ;; + strongarm-* | thumb-*) + basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; sun2) basic_machine=m68000-sun ;; @@ -1005,17 +1185,9 @@ case $basic_machine in basic_machine=t90-cray os=-unicos ;; - tic54x | c54x*) - basic_machine=tic54x-unknown - os=-coff - ;; - tic55x | c55x*) - basic_machine=tic55x-unknown - os=-coff - ;; - tic6x | c6x*) - basic_machine=tic6x-unknown - os=-coff + tile*) + basic_machine=$basic_machine-unknown + os=-linux-gnu ;; tx39) basic_machine=mipstx39-unknown @@ -1084,6 +1256,9 @@ case $basic_machine in xps | xps100) basic_machine=xps100-honeywell ;; + xscale-* | xscalee[bl]-*) + basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` + ;; ymp) basic_machine=ymp-cray os=-unicos @@ -1092,6 +1267,10 @@ case $basic_machine in basic_machine=z8k-unknown os=-sim ;; + z80-*-coff) + basic_machine=z80-unknown + os=-sim + ;; none) basic_machine=none-none os=-none @@ -1130,7 +1309,7 @@ case $basic_machine in we32k) basic_machine=we32k-att ;; - sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele) + sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) @@ -1177,9 +1356,12 @@ esac if [ x"$os" != x"" ] then case $os in - # First match some system type aliases - # that might get confused with valid system types. + # First match some system type aliases + # that might get confused with valid system types. # -solaris* is a basic system type, with this one exception. + -auroraux) + os=-auroraux + ;; -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; @@ -1200,29 +1382,32 @@ case $os in # Each alternative MUST END IN A *, to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ - | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ - | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ + | -sym* | -kopensolaris* | -plan9* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ - | -aos* \ + | -aos* | -aros* | -cloudabi* | -sortix* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ - | -openbsd* | -solidbsd* \ + | -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ - | -chorusos* | -chorusrdb* \ - | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ - | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \ - | -uxpv* | -beos* | -mpeix* | -udk* \ + | -chorusos* | -chorusrdb* | -cegcc* \ + | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ + | -linux-newlib* | -linux-musl* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ - | -skyos* | -haiku* | -rdos* | -toppers*) + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \ + | -onefs* | -tirtos* | -phoenix*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) @@ -1261,7 +1446,7 @@ case $os in -opened*) os=-openedition ;; - -os400*) + -os400*) os=-os400 ;; -wince*) @@ -1310,7 +1495,7 @@ case $os in -sinix*) os=-sysv4 ;; - -tpf*) + -tpf*) os=-tpf ;; -triton*) @@ -1346,12 +1531,16 @@ case $os in -aros*) os=-aros ;; - -kaos*) - os=-kaos - ;; -zvmoe) os=-zvmoe ;; + -dicos*) + os=-dicos + ;; + -nacl*) + ;; + -ios) + ;; -none) ;; *) @@ -1374,10 +1563,10 @@ else # system, and we'll never get to this point. case $basic_machine in - score-*) + score-*) os=-elf ;; - spu-*) + spu-*) os=-elf ;; *-acorn) @@ -1389,8 +1578,23 @@ case $basic_machine in arm*-semi) os=-aout ;; - c4x-* | tic4x-*) - os=-coff + c4x-* | tic4x-*) + os=-coff + ;; + c8051-*) + os=-elf + ;; + hexagon-*) + os=-elf + ;; + tic54x-*) + os=-coff + ;; + tic55x-*) + os=-coff + ;; + tic6x-*) + os=-coff ;; # This must come before the *-dec entry. pdp10-*) @@ -1410,13 +1614,13 @@ case $basic_machine in ;; m68000-sun) os=-sunos3 - # This also exists in the configure program, but was not the - # default. - # os=-sunos4 ;; m68*-cisco) os=-aout ;; + mep-*) + os=-elf + ;; mips*-cisco) os=-elf ;; @@ -1441,7 +1645,7 @@ case $basic_machine in *-ibm) os=-aix ;; - *-knuth) + *-knuth) os=-mmixware ;; *-wec) @@ -1546,7 +1750,7 @@ case $basic_machine in -sunos*) vendor=sun ;; - -aix*) + -cnk*|-aix*) vendor=ibm ;; -beos*) diff --git a/configure b/configure index e285f0c..6fd5a4b 100755 --- a/configure +++ b/configure @@ -1,81 +1,459 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.59. +# Generated by GNU Autoconf 2.69. +# +# +# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. +# # -# Copyright (C) 2003 Free Software Foundation, Inc. # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. -## --------------------- ## -## M4sh Initialization. ## -## --------------------- ## +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## -# Be Bourne compatible -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: - # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' -elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then - set -o posix -fi -DUALCASE=1; export DUALCASE # for MKS sh - -# Support unset when possible. -if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then - as_unset=unset + setopt NO_GLOB_SUBST else - as_unset=false + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac fi -# Work around bugs in pre-3.0 UWIN ksh. -$as_unset ENV MAIL MAILPATH +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. -for as_var in \ - LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ - LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ - LC_TELEPHONE LC_TIME -do - if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then - eval $as_var=C; export $as_var - else - $as_unset $as_var - fi -done +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE -# Required to use basename. -if expr a : '\(a\)' >/dev/null 2>&1; then +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# Use a proper internal environment variable to ensure we don't fall + # into an infinite loop, continuously re-executing ourselves. + if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then + _as_can_reexec=no; export _as_can_reexec; + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +as_fn_exit 255 + fi + # We don't want this to propagate to other subprocesses. + { _as_can_reexec=; unset _as_can_reexec;} +if test "x$CONFIG_SHELL" = x; then + as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi +" + as_required="as_fn_return () { (exit \$1); } +as_fn_success () { as_fn_return 0; } +as_fn_failure () { as_fn_return 1; } +as_fn_ret_success () { return 0; } +as_fn_ret_failure () { return 1; } + +exitcode=0 +as_fn_success || { exitcode=1; echo as_fn_success failed.; } +as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } +as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } +as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } +if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : + +else + exitcode=1; echo positional parameters were not saved. +fi +test x\$exitcode = x0 || exit 1 +test -x / || exit 1" + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 +test \$(( 1 + 1 )) = 2 || exit 1" + if (eval "$as_required") 2>/dev/null; then : + as_have_required=yes +else + as_have_required=no +fi + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : + +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + as_found=: + case $as_dir in #( + /*) + for as_base in sh bash ksh sh5; do + # Try only shells that exist, to save several forks. + as_shell=$as_dir/$as_base + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : + CONFIG_SHELL=$as_shell as_have_required=yes + if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : + break 2 +fi +fi + done;; + esac + as_found=false +done +$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi; } +IFS=$as_save_IFS + + + if test "x$CONFIG_SHELL" != x; then : + export CONFIG_SHELL + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +exit 255 +fi + + if test x$as_have_required = xno; then : + $as_echo "$0: This script requires a shell more modern than all" + $as_echo "$0: the shells that I found on your system." + if test x${ZSH_VERSION+set} = xset ; then + $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" + $as_echo "$0: be upgraded to zsh 4.3.4 or later." + else + $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, +$0: including any error possibly output before this +$0: message. Then install a modern shell, or manually run +$0: the script under such a shell if you do have one." + fi + exit 1 +fi +fi +fi +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +# Unset more variables known to interfere with behavior of common tools. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS + +## --------------------- ## +## M4sh Shell Functions. ## +## --------------------- ## +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi -if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi -# Name of the executable. -as_me=`$as_basename "$0" || +as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ - X"$0" : 'X\(/\)$' \| \ - . : '\(.\)' 2>/dev/null || -echo X/"$0" | - sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } - /^X\/\(\/\/\)$/{ s//\1/; q; } - /^X\/\(\/\).*/{ s//\1/; q; } - s/.*/./; q'` + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` - -# PATH needs CR, and LINENO needs CR and PATH. # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' @@ -83,146 +461,91 @@ as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits -# The user is always right. -if test "${PATH_SEPARATOR+set}" != set; then - echo "#! /bin/sh" >conf$$.sh - echo "exit 0" >>conf$$.sh - chmod +x conf$$.sh - if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then - PATH_SEPARATOR=';' - else - PATH_SEPARATOR=: - fi - rm -f conf$$.sh -fi - - as_lineno_1=$LINENO - as_lineno_2=$LINENO - as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` - test "x$as_lineno_1" != "x$as_lineno_2" && - test "x$as_lineno_3" = "x$as_lineno_2" || { - # Find who we are. Look in the path if we contain no path at all - # relative or not. - case $0 in - *[\\/]* ) as_myself=$0 ;; - *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break -done - - ;; - esac - # We did not find ourselves, most probably we were run as `sh COMMAND' - # in which case we are not to be found in the path. - if test "x$as_myself" = x; then - as_myself=$0 - fi - if test ! -f "$as_myself"; then - { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2 - { (exit 1); exit 1; }; } - fi - case $CONFIG_SHELL in - '') - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for as_base in sh bash ksh sh5; do - case $as_dir in - /*) - if ("$as_dir/$as_base" -c ' - as_lineno_1=$LINENO - as_lineno_2=$LINENO - as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` - test "x$as_lineno_1" != "x$as_lineno_2" && - test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then - $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } - $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } - CONFIG_SHELL=$as_dir/$as_base - export CONFIG_SHELL - exec "$CONFIG_SHELL" "$0" ${1+"$@"} - fi;; - esac - done -done -;; - esac - - # Create $as_me.lineno as a copy of $as_myself, but with $LINENO - # uniformly replaced by the line number. The first 'sed' inserts a - # line-number line before each line; the second 'sed' does the real - # work. The second script uses 'N' to pair each line-number line - # with the numbered line, and appends trailing '-' during - # substitution so that $LINENO is not a special case at line end. - # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the - # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) - sed '=' <$as_myself | + as_lineno_1=$LINENO as_lineno_1a=$LINENO + as_lineno_2=$LINENO as_lineno_2a=$LINENO + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno N - s,$,-, - : loop - s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop - s,-$,, - s,^['$as_cr_digits']*\n,, + s/-\n.*// ' >$as_me.lineno && - chmod +x $as_me.lineno || - { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 - { (exit 1); exit 1; }; } + chmod +x "$as_me.lineno" || + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + # If we had to re-execute with $CONFIG_SHELL, we're ensured to have + # already done that, so ensure we don't try to do so again and fall + # in an infinite loop. This has already happened in practice. + _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the - # original and so on. Autoconf is especially sensible to this). - . ./$as_me.lineno + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" # Exit status is that of the last command. exit } - -case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in - *c*,-n*) ECHO_N= ECHO_C=' -' ECHO_T=' ' ;; - *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; - *) ECHO_N= ECHO_C='\c' ECHO_T= ;; +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; esac -if expr a : '\(a\)' >/dev/null 2>&1; then - as_expr=expr -else - as_expr=false -fi - rm -f conf$$ conf$$.exe conf$$.file -echo >conf$$.file -if ln -s conf$$.file conf$$ 2>/dev/null; then - # We could just check for DJGPP; but this test a) works b) is more generic - # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). - if test -f conf$$.exe; then - # Don't use ln at all; we don't have any links - as_ln_s='cp -p' - else +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' fi -elif ln conf$$.file conf$$ 2>/dev/null; then - as_ln_s=ln else - as_ln_s='cp -p' + as_ln_s='cp -pR' fi -rm -f conf$$ conf$$.exe conf$$.file +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then - as_mkdir_p=: + as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi -as_executable_p="test -f" +as_test_x='test -x' +as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" @@ -231,38 +554,25 @@ as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" -# IFS -# We need space, tab and new line, in precisely that order. -as_nl=' -' -IFS=" $as_nl" - -# CDPATH. -$as_unset CDPATH - +test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. -# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, +# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` -exec 6>&1 - # # Initializations. # ac_default_prefix=/usr/local +ac_clean_files= ac_config_libobj_dir=. +LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= -SHELL=${CONFIG_SHELL-/bin/sh} - -# Maximum number of lines to put in a shell here document. -# This variable seems obsolete. It should probably be removed, and -# only ac_max_sed_lines should be used. -: ${ac_max_here_lines=38} # Identity of this package. PACKAGE_NAME= @@ -270,53 +580,197 @@ PACKAGE_TARNAME= PACKAGE_VERSION= PACKAGE_STRING= PACKAGE_BUGREPORT= +PACKAGE_URL= ac_unique_file="base/nagios.c" ac_default_prefix=/usr/local/nagios # Factoring default headers for most tests. ac_includes_default="\ #include -#if HAVE_SYS_TYPES_H +#ifdef HAVE_SYS_TYPES_H # include #endif -#if HAVE_SYS_STAT_H +#ifdef HAVE_SYS_STAT_H # include #endif -#if STDC_HEADERS +#ifdef STDC_HEADERS # include # include #else -# if HAVE_STDLIB_H +# ifdef HAVE_STDLIB_H # include # endif #endif -#if HAVE_STRING_H -# if !STDC_HEADERS && HAVE_MEMORY_H +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif -#if HAVE_STRINGS_H +#ifdef HAVE_STRINGS_H # include #endif -#if HAVE_INTTYPES_H +#ifdef HAVE_INTTYPES_H # include -#else -# if HAVE_STDINT_H -# include -# endif #endif -#if HAVE_UNISTD_H +#ifdef HAVE_STDINT_H +# include +#endif +#ifdef HAVE_UNISTD_H # include #endif" -ac_subdirs_all="$ac_subdirs_all tap" -ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA INSTALL build build_cpu build_vendor build_os host host_cpu host_vendor host_os CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT SET_MAKE STRIP CPP EGREP SNPRINTF_O SOCKETLIBS THREADLIBS nagios_user nagios_grp INSTALL_OPTS command_user command_grp COMMAND_OPTS MAIL_PROG HTTPD_CONF CHECKRESULTDIR TMPDIR init_dir lockfile XSDC XSDH XCDC XCDH XRDC XRDH XODC XODH XPDC XPDH XDDC XDDH htmurl cgiurl BROKER_LDFLAGS BROKERLIBS MOD_CFLAGS MOD_LDFLAGS BROKER_O BROKER_H nagios_name nagiostats_name PATH_TO_TRACEROUTE PACKDIR VERSION subdirs USE_LIBTAP CGIEXTRAS GDLIBS PERLLIBS PERLDIR PERLXSI_O BASEEXTRALIBS INITDIR INSTALLPERLSTUFF USE_EVENTBROKER PERL LIBOBJS LTLIBOBJS' +enable_option_checking=no +ac_subst_vars='LTLIBOBJS +LIBOBJS +UNZIP +PERL +USE_EVENTBROKER +INITDIR +BASEEXTRALIBS +GDLIBS +CGIEXTRAS +USE_LIBTAP +subdirs +VERSION +PACKDIR +PATH_TO_TRACEROUTE +nagiostats_name +nagios_name +BROKER_H +BROKER_O +WORKER_LDFLAGS +WORKER_CFLAGS +MOD_LDFLAGS +MOD_CFLAGS +BROKERLIBS +BROKER_LDFLAGS +cgiurl +htmurl +COREWINDOW +lockfile +init_dir +TMPDIR +CHECKRESULTDIR +LN_HTTPD_SITES_ENABLED +HTTPD_CONF +MAIL_PROG +COMMAND_OPTS +command_grp +command_user +INSTALL_OPTS +nagios_grp +nagios_user +INIT_OPTS +root_grp +SOCKETLIBS +SNPRINTF_O +EGREP +GREP +CPP +STRIP +LN_S +SET_MAKE +OBJEXT +EXEEXT +ac_ct_CC +CPPFLAGS +LDFLAGS +CFLAGS +CC +host_os +host_vendor +host_cpu +host +build_os +build_vendor +build_cpu +build +INSTALL +INSTALL_DATA +INSTALL_SCRIPT +INSTALL_PROGRAM +target_alias +host_alias +build_alias +LIBS +ECHO_T +ECHO_N +ECHO_C +DEFS +mandir +localedir +libdir +psdir +pdfdir +dvidir +htmldir +infodir +docdir +oldincludedir +includedir +localstatedir +sharedstatedir +sysconfdir +datadir +datarootdir +libexecdir +sbindir +bindir +program_transform_name +prefix +exec_prefix +PACKAGE_URL +PACKAGE_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL' ac_subst_files='' +ac_user_opts=' +enable_option_checking +with_root_group +with_nagios_user +with_nagios_group +with_command_user +with_command_group +with_mail +with_httpd_conf +with_checkresult_dir +with_temp_dir +with_init_dir +with_lockfile +with_iobroker +with_gd_lib +with_gd_inc +enable_corewindow +enable_statusmap +enable_statuswrl +with_cgiurl +with_htmurl +enable_nanosleep +enable_event_broker +enable_cygwin +enable_libtap +' + ac_precious_vars='build_alias +host_alias +target_alias +CC +CFLAGS +LDFLAGS +LIBS +CPPFLAGS +CPP' +ac_subdirs_all='tap' # Initialize some variables set by options. ac_init_help= ac_init_version=false +ac_unrecognized_opts= +ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null @@ -339,34 +793,49 @@ x_libraries=NONE # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' -datadir='${prefix}/share' +datarootdir='${prefix}/share' +datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' -libdir='${exec_prefix}/lib' includedir='${prefix}/include' oldincludedir='/usr/include' -infodir='${prefix}/info' -mandir='${prefix}/man' +docdir='${datarootdir}/doc/${PACKAGE}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' ac_prev= +ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then - eval "$ac_prev=\$ac_option" + eval $ac_prev=\$ac_option ac_prev= continue fi - ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'` + case $ac_option in + *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *=) ac_optarg= ;; + *) ac_optarg=yes ;; + esac # Accept the important Cygnus configure options, so we can diagnose typos. - case $ac_option in + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; @@ -388,33 +857,59 @@ do --config-cache | -C) cache_file=config.cache ;; - -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; - -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ - | --da=*) + -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + -disable-* | --disable-*) - ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. - expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && - { echo "$as_me: error: invalid feature name: $ac_feature" >&2 - { (exit 1); exit 1; }; } - ac_feature=`echo $ac_feature | sed 's/-/_/g'` - eval "enable_$ac_feature=no" ;; + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; -enable-* | --enable-*) - ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. - expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && - { echo "$as_me: error: invalid feature name: $ac_feature" >&2 - { (exit 1); exit 1; }; } - ac_feature=`echo $ac_feature | sed 's/-/_/g'` - case $ac_option in - *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; - *) ac_optarg=yes ;; + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; esac - eval "enable_$ac_feature='$ac_optarg'" ;; + eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ @@ -441,6 +936,12 @@ do -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; @@ -465,13 +966,16 @@ do | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + -localstatedir | --localstatedir | --localstatedi | --localstated \ - | --localstate | --localstat | --localsta | --localst \ - | --locals | --local | --loca | --loc | --lo) + | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ - | --localstate=* | --localstat=* | --localsta=* | --localst=* \ - | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) @@ -536,6 +1040,16 @@ do | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; @@ -586,26 +1100,36 @@ do ac_init_version=: ;; -with-* | --with-*) - ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. - expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && - { echo "$as_me: error: invalid package name: $ac_package" >&2 - { (exit 1); exit 1; }; } - ac_package=`echo $ac_package| sed 's/-/_/g'` - case $ac_option in - *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; - *) ac_optarg=yes ;; + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" + ac_unrecognized_sep=', ';; esac - eval "with_$ac_package='$ac_optarg'" ;; + eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) - ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` + ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. - expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && - { echo "$as_me: error: invalid package name: $ac_package" >&2 - { (exit 1); exit 1; }; } - ac_package=`echo $ac_package | sed 's/-/_/g'` - eval "with_$ac_package=no" ;; + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. @@ -625,27 +1149,26 @@ do | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; - -*) { echo "$as_me: error: unrecognized option: $ac_option -Try \`$0 --help' for more information." >&2 - { (exit 1); exit 1; }; } + -*) as_fn_error $? "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. - expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && - { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 - { (exit 1); exit 1; }; } - ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` - eval "$ac_envvar='$ac_optarg'" + case $ac_envvar in #( + '' | [0-9]* | *[!_$as_cr_alnum]* ) + as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; + esac + eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. - echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && - echo "$as_me: WARNING: invalid host type: $ac_option" >&2 - : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} + $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac @@ -653,31 +1176,36 @@ done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` - { echo "$as_me: error: missing argument to $ac_option" >&2 - { (exit 1); exit 1; }; } + as_fn_error $? "missing argument to $ac_option" fi -# Be sure to have absolute paths. -for ac_var in exec_prefix prefix -do - eval ac_val=$`echo $ac_var` - case $ac_val in - [\\/$]* | ?:[\\/]* | NONE | '' ) ;; - *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 - { (exit 1); exit 1; }; };; +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) ;; + fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; + *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac -done +fi -# Be sure to have absolute paths. -for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \ - localstatedir libdir includedir oldincludedir infodir mandir +# Check all directory arguments for consistency. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir do - eval ac_val=$`echo $ac_var` + eval ac_val=\$$ac_var + # Remove trailing slashes. case $ac_val in - [\\/$]* | ?:[\\/]* ) ;; - *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 - { (exit 1); exit 1; }; };; + */ ) + ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` + eval $ac_var=\$ac_val;; esac + # Be sure to have absolute directory names. + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' @@ -691,8 +1219,6 @@ target=$target_alias if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe - echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. - If a cross compiler is detected then cross compile mode will be used." >&2 elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi @@ -704,74 +1230,72 @@ test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + as_fn_error $? "working directory cannot be determined" +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + as_fn_error $? "pwd does not report name of working directory" + + # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes - # Try the directory containing this script, then its parent. - ac_confdir=`(dirname "$0") 2>/dev/null || -$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$0" : 'X\(//\)[^/]' \| \ - X"$0" : 'X\(//\)$' \| \ - X"$0" : 'X\(/\)' \| \ - . : '\(.\)' 2>/dev/null || -echo X"$0" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } - /^X\(\/\/\)[^/].*/{ s//\1/; q; } - /^X\(\/\/\)$/{ s//\1/; q; } - /^X\(\/\).*/{ s//\1/; q; } - s/.*/./; q'` + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$as_myself" || +$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_myself" : 'X\(//\)[^/]' \| \ + X"$as_myself" : 'X\(//\)$' \| \ + X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_myself" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` srcdir=$ac_confdir - if test ! -r $srcdir/$ac_unique_file; then + if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi -if test ! -r $srcdir/$ac_unique_file; then - if test "$ac_srcdir_defaulted" = yes; then - { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2 - { (exit 1); exit 1; }; } - else - { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 - { (exit 1); exit 1; }; } - fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi -(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null || - { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2 - { (exit 1); exit 1; }; } -srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'` -ac_env_build_alias_set=${build_alias+set} -ac_env_build_alias_value=$build_alias -ac_cv_env_build_alias_set=${build_alias+set} -ac_cv_env_build_alias_value=$build_alias -ac_env_host_alias_set=${host_alias+set} -ac_env_host_alias_value=$host_alias -ac_cv_env_host_alias_set=${host_alias+set} -ac_cv_env_host_alias_value=$host_alias -ac_env_target_alias_set=${target_alias+set} -ac_env_target_alias_value=$target_alias -ac_cv_env_target_alias_set=${target_alias+set} -ac_cv_env_target_alias_value=$target_alias -ac_env_CC_set=${CC+set} -ac_env_CC_value=$CC -ac_cv_env_CC_set=${CC+set} -ac_cv_env_CC_value=$CC -ac_env_CFLAGS_set=${CFLAGS+set} -ac_env_CFLAGS_value=$CFLAGS -ac_cv_env_CFLAGS_set=${CFLAGS+set} -ac_cv_env_CFLAGS_value=$CFLAGS -ac_env_LDFLAGS_set=${LDFLAGS+set} -ac_env_LDFLAGS_value=$LDFLAGS -ac_cv_env_LDFLAGS_set=${LDFLAGS+set} -ac_cv_env_LDFLAGS_value=$LDFLAGS -ac_env_CPPFLAGS_set=${CPPFLAGS+set} -ac_env_CPPFLAGS_value=$CPPFLAGS -ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set} -ac_cv_env_CPPFLAGS_value=$CPPFLAGS -ac_env_CPP_set=${CPP+set} -ac_env_CPP_value=$CPP -ac_cv_env_CPP_set=${CPP+set} -ac_cv_env_CPP_value=$CPP +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done # # Report the --help message. @@ -794,20 +1318,17 @@ Configuration: --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit - -q, --quiet, --silent do not print \`checking...' messages + -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] -_ACEOF - - cat <<_ACEOF Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX - [$ac_default_prefix] + [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX - [PREFIX] + [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify @@ -817,18 +1338,25 @@ for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: - --bindir=DIR user executables [EPREFIX/bin] - --sbindir=DIR system admin executables [EPREFIX/sbin] - --libexecdir=DIR program executables [EPREFIX/libexec] - --datadir=DIR read-only architecture-independent data [PREFIX/share] - --sysconfdir=DIR read-only single-machine data [PREFIX/etc] - --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] - --localstatedir=DIR modifiable single-machine data [PREFIX/var] - --libdir=DIR object code libraries [EPREFIX/lib] - --includedir=DIR C header files [PREFIX/include] - --oldincludedir=DIR C header files for non-gcc [/usr/include] - --infodir=DIR info documentation [PREFIX/info] - --mandir=DIR man documentation [PREFIX/man] + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF @@ -844,20 +1372,23 @@ if test -n "$ac_init_help"; then cat <<\_ACEOF Optional Features: + --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] ---disable-statusmap=disables compilation of statusmap CGI ---disable-statuswrl=disables compilation of statuswrl (VRML) CGI ---enable-nanosleep enables use of nanosleep (instead of sleep) in event timing ---enable-event-broker enables integration of event broker routines ---enable-embedded-perl will enable embedded Perl interpreter ---enable-cygwin enables building under the CYGWIN environment + --enable-corewindow enables the 'corewindow' URL argument + --disable-statusmap disables compilation of statusmap CGI + --disable-statuswrl disables compilation of statuswrl (VRML) CGI + --enable-nanosleep enables use of nanosleep (instead of sleep) in event + timing + --enable-event-broker enables integration of event broker routines + --enable-cygwin enables building under the CYGWIN environment --enable-libtap Enable built-in libtap for unit-testing (default: no). Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-root-group= sets group name for installing init --with-nagios-user= sets user name to run nagios --with-nagios-group= @@ -866,143 +1397,631 @@ Optional Packages: sets user name for command access --with-command-group= sets group name for command access ---with-mail= sets path to equivalent program to mail ---with-httpd-conf= sets path to Apache conf.d directory ---with-checkresult-dir= sets path to check results spool directory ---with-temp-dir= sets path to temp directory ---with-init-dir= sets directory to place init script into ---with-lockfile= sets path and file name for lock file ---with-gd-lib=DIR sets location of the gd library ---with-gd-inc=DIR sets location of the gd include files ---with-cgiurl= sets URL for cgi programs (do not use a trailing slash) ---with-htmurl= sets URL for public html ---with-perlcache turns on cacheing of internally compiled Perl scripts + --with-mail= + sets path to equivalent program to mail + --with-httpd-conf= + sets path to Apache conf.d directory + --with-checkresult-dir= + sets path to check results spool directory + --with-temp-dir= sets path to temp directory + --with-init-dir= sets directory to place init script into + --with-lockfile= sets path and file name for lock file + --with-iobroker= + specify the method to use with iobroker: epoll, + poll, or select + --with-gd-lib=DIR sets location of the gd library + --with-gd-inc=DIR sets location of the gd include files + --with-cgiurl= + sets URL for cgi programs (do not use a trailing + slash) + --with-htmurl= + sets URL for public html Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory - CPPFLAGS C/C++ preprocessor flags, e.g. -I if you have - headers in a nonstandard directory + LIBS libraries to pass to the linker, e.g. -l + CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if + you have headers in a nonstandard directory CPP C preprocessor Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. +Report bugs to the package provider. _ACEOF +ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. - ac_popdir=`pwd` for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue - test -d $ac_dir || continue + test -d "$ac_dir" || + { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || + continue ac_builddir=. -if test "$ac_dir" != .; then - ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` - # A "../" for each directory in $ac_dir_suffix. - ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` -else - ac_dir_suffix= ac_top_builddir= -fi +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix case $srcdir in - .) # No --srcdir option. We are building in place. + .) # We are building in place. ac_srcdir=. - if test -z "$ac_top_builddir"; then - ac_top_srcdir=. - else - ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` - fi ;; - [\\/]* | ?:[\\/]* ) # Absolute path. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; - ac_top_srcdir=$srcdir ;; - *) # Relative path. - ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix - ac_top_srcdir=$ac_top_builddir$srcdir ;; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix -# Do not use `cd foo && pwd` to compute absolute paths, because -# the directories may not exist. -case `pwd` in -.) ac_abs_builddir="$ac_dir";; -*) - case "$ac_dir" in - .) ac_abs_builddir=`pwd`;; - [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; - *) ac_abs_builddir=`pwd`/"$ac_dir";; - esac;; -esac -case $ac_abs_builddir in -.) ac_abs_top_builddir=${ac_top_builddir}.;; -*) - case ${ac_top_builddir}. in - .) ac_abs_top_builddir=$ac_abs_builddir;; - [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; - *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; - esac;; -esac -case $ac_abs_builddir in -.) ac_abs_srcdir=$ac_srcdir;; -*) - case $ac_srcdir in - .) ac_abs_srcdir=$ac_abs_builddir;; - [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; - *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; - esac;; -esac -case $ac_abs_builddir in -.) ac_abs_top_srcdir=$ac_top_srcdir;; -*) - case $ac_top_srcdir in - .) ac_abs_top_srcdir=$ac_abs_builddir;; - [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; - *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; - esac;; -esac - - cd $ac_dir - # Check for guested configure; otherwise get Cygnus style configure. - if test -f $ac_srcdir/configure.gnu; then - echo - $SHELL $ac_srcdir/configure.gnu --help=recursive - elif test -f $ac_srcdir/configure; then - echo - $SHELL $ac_srcdir/configure --help=recursive - elif test -f $ac_srcdir/configure.ac || - test -f $ac_srcdir/configure.in; then - echo - $ac_configure --help + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive else - echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 - fi - cd $ac_popdir + $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } done fi -test -n "$ac_init_help" && exit 0 +test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF +configure +generated by GNU Autoconf 2.69 -Copyright (C) 2003 Free Software Foundation, Inc. +Copyright (C) 2012 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF - exit 0 + exit fi -exec 5>config.log -cat >&5 <<_ACEOF + +## ------------------------ ## +## Autoconf initialization. ## +## ------------------------ ## + +# ac_fn_c_try_compile LINENO +# -------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_compile + +# ac_fn_c_try_cpp LINENO +# ---------------------- +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } > conftest.i && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_cpp + +# ac_fn_c_try_run LINENO +# ---------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes +# that executables *can* be run. +ac_fn_c_try_run () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + ac_retval=0 +else + $as_echo "$as_me: program exited with status $ac_status" >&5 + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=$ac_status +fi + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_run + +# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists, giving a warning if it cannot be compiled using +# the include files in INCLUDES and setting the cache variable VAR +# accordingly. +ac_fn_c_check_header_mongrel () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if eval \${$3+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 +$as_echo_n "checking $2 usability... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_header_compiler=yes +else + ac_header_compiler=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 +$as_echo_n "checking $2 presence... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <$2> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + ac_header_preproc=yes +else + ac_header_preproc=no +fi +rm -f conftest.err conftest.i conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( + yes:no: ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; + no:yes:* ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=\$ac_header_compiler" +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_mongrel + +# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists and can be compiled using the include files in +# INCLUDES, setting the cache variable VAR accordingly. +ac_fn_c_check_header_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_compile + +# ac_fn_c_check_member LINENO AGGR MEMBER VAR INCLUDES +# ---------------------------------------------------- +# Tries to find if the field MEMBER exists in type AGGR, after including +# INCLUDES, setting cache variable VAR accordingly. +ac_fn_c_check_member () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5 +$as_echo_n "checking for $2.$3... " >&6; } +if eval \${$4+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$5 +int +main () +{ +static $2 ac_aggr; +if (ac_aggr.$3) +return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$4=yes" +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$5 +int +main () +{ +static $2 ac_aggr; +if (sizeof ac_aggr.$3) +return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$4=yes" +else + eval "$4=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$4 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_member + +# ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES +# --------------------------------------------- +# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR +# accordingly. +ac_fn_c_check_decl () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + as_decl_name=`echo $2|sed 's/ *(.*//'` + as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'` + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5 +$as_echo_n "checking whether $as_decl_name is declared... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +#ifndef $as_decl_name +#ifdef __cplusplus + (void) $as_decl_use; +#else + (void) $as_decl_name; +#endif +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_decl + +# ac_fn_c_try_link LINENO +# ----------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + test -x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_link + +# ac_fn_c_check_type LINENO TYPE VAR INCLUDES +# ------------------------------------------- +# Tests whether TYPE exists after having included INCLUDES, setting cache +# variable VAR accordingly. +ac_fn_c_check_type () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=no" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +if (sizeof ($2)) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +if (sizeof (($2))) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + eval "$3=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_type + +# ac_fn_c_check_func LINENO FUNC VAR +# ---------------------------------- +# Tests whether FUNC exists, setting the cache variable VAR accordingly +ac_fn_c_check_func () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Define $2 to an innocuous variant, in case declares $2. + For example, HP-UX 11i declares gettimeofday. */ +#define $2 innocuous_$2 + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $2 (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $2 + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $2 (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$2 || defined __stub___$2 +choke me +#endif + +int +main () +{ +return $2 (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_func +cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by $as_me, which was -generated by GNU Autoconf 2.59. Invocation command line was +generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ _ACEOF +exec 5>>config.log { cat <<_ASUNAME ## --------- ## @@ -1021,7 +2040,7 @@ uname -v = `(uname -v) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` -hostinfo = `(hostinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` @@ -1033,8 +2052,9 @@ for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - echo "PATH: $as_dir" -done + $as_echo "PATH: $as_dir" + done +IFS=$as_save_IFS } >&5 @@ -1056,7 +2076,6 @@ _ACEOF ac_configure_args= ac_configure_args0= ac_configure_args1= -ac_sep= ac_must_keep_next=false for ac_pass in 1 2 do @@ -1067,13 +2086,13 @@ do -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; - *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) - ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + *\'*) + ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in - 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; + 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) - ac_configure_args1="$ac_configure_args1 '$ac_arg'" + as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else @@ -1089,104 +2108,115 @@ do -* ) ac_must_keep_next=true ;; esac fi - ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'" - # Get rid of the leading space. - ac_sep=" " + as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done -$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } -$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } +{ ac_configure_args0=; unset ac_configure_args0;} +{ ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. -# WARNING: Be sure not to use single quotes in there, as some shells, -# such as our DU 5.0 friend, will then `close' the trap. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo - cat <<\_ASBOX -## ---------------- ## + $as_echo "## ---------------- ## ## Cache variables. ## -## ---------------- ## -_ASBOX +## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, -{ +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done (set) 2>&1 | - case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in - *ac_space=\ *) + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) sed -n \ - "s/'"'"'/'"'"'\\\\'"'"''"'"'/g; - s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p" - ;; + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( *) - sed -n \ - "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; - esac; -} + esac | + sort +) echo - cat <<\_ASBOX -## ----------------- ## + $as_echo "## ----------------- ## ## Output variables. ## -## ----------------- ## -_ASBOX +## ----------------- ##" echo for ac_var in $ac_subst_vars do - eval ac_val=$`echo $ac_var` - echo "$ac_var='"'"'$ac_val'"'"'" + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then - cat <<\_ASBOX -## ------------- ## -## Output files. ## -## ------------- ## -_ASBOX + $as_echo "## ------------------- ## +## File substitutions. ## +## ------------------- ##" echo for ac_var in $ac_subst_files do - eval ac_val=$`echo $ac_var` - echo "$ac_var='"'"'$ac_val'"'"'" + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then - cat <<\_ASBOX -## ----------- ## + $as_echo "## ----------- ## ## confdefs.h. ## -## ----------- ## -_ASBOX +## ----------- ##" echo - sed "/^$/d" confdefs.h | sort + cat confdefs.h echo fi test "$ac_signal" != 0 && - echo "$as_me: caught signal $ac_signal" - echo "$as_me: exit $exit_status" + $as_echo "$as_me: caught signal $ac_signal" + $as_echo "$as_me: exit $exit_status" } >&5 - rm -f core *.core && - rm -rf conftest* confdefs* conf$$* $ac_clean_files && + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status - ' 0 +' 0 for ac_signal in 1 2 13 15; do - trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal + trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. -rm -rf conftest* confdefs.h -# AIX cpp loses on an empty file, so make sure it contains at least a newline. -echo >confdefs.h +rm -f -r conftest* confdefs.h + +$as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. @@ -1194,42 +2224,57 @@ cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF - cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF - cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF - cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF - cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF +cat >>confdefs.h <<_ACEOF +#define PACKAGE_URL "$PACKAGE_URL" +_ACEOF + # Let the site file select an alternate cache file if it wants to. -# Prefer explicitly selected file to automatically selected ones. -if test -z "$CONFIG_SITE"; then - if test "x$prefix" != xNONE; then - CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" - else - CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" - fi +# Prefer an explicitly selected file to automatically selected ones. +ac_site_file1=NONE +ac_site_file2=NONE +if test -n "$CONFIG_SITE"; then + # We do not want a PATH search for config.site. + case $CONFIG_SITE in #(( + -*) ac_site_file1=./$CONFIG_SITE;; + */*) ac_site_file1=$CONFIG_SITE;; + *) ac_site_file1=./$CONFIG_SITE;; + esac +elif test "x$prefix" != xNONE; then + ac_site_file1=$prefix/share/config.site + ac_site_file2=$prefix/etc/config.site +else + ac_site_file1=$ac_default_prefix/share/config.site + ac_site_file2=$ac_default_prefix/etc/config.site fi -for ac_site_file in $CONFIG_SITE; do - if test -r "$ac_site_file"; then - { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 -echo "$as_me: loading site script $ac_site_file" >&6;} +for ac_site_file in "$ac_site_file1" "$ac_site_file2" +do + test "x$ac_site_file" = xNONE && continue + if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +$as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 - . "$ac_site_file" + . "$ac_site_file" \ + || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "failed to load site script $ac_site_file +See \`config.log' for more details" "$LINENO" 5; } fi done @@ -1237,53 +2282,63 @@ done # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false -for ac_var in `(set) 2>&1 | - sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do +for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set - eval ac_old_val="\$ac_cv_env_${ac_var}_value" - eval ac_new_val="\$ac_env_${ac_var}_value" + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) - { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 -echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) - { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 -echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then - { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 -echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} - { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 -echo "$as_me: former value: $ac_old_val" >&2;} - { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 -echo "$as_me: current value: $ac_new_val" >&2;} - ac_cache_corrupted=: + # differences in whitespace do not lead to failure. + ac_old_val_w=`echo x $ac_old_val` + ac_new_val_w=`echo x $ac_new_val` + if test "$ac_old_val_w" != "$ac_new_val_w"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 +$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + ac_cache_corrupted=: + else + { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + eval $ac_var=\$ac_old_val + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 +$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 +$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in - *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) - ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. - *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; + *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then - { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 -echo "$as_me: error: changes in the environment can compromise the build" >&2;} - { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 -echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} - { (exit 1); exit 1; }; } + { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 +$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} + as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi +## -------------------- ## +## Main body of script. ## +## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' @@ -1292,56 +2347,44 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $ ac_compiler_gnu=$ac_cv_c_compiler_gnu - - - - - - - - - - - - - - - - - - ac_config_headers="$ac_config_headers include/config.h include/snprintf.h" +ac_config_headers="$ac_config_headers include/config.h lib/snprintf.h lib/iobroker.h" PKG_NAME=nagios -PKG_VERSION="3.5.1" -PKG_HOME_URL="http://www.nagios.org/" -PKG_REL_DATE="08-30-2013" + +PKG_VERSION="4.3.2" +PKG_HOME_URL="https://www.nagios.org/" +PKG_REL_DATE="2017-05-09" ac_aux_dir= -for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do - if test -f $ac_dir/install-sh; then +for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do + if test -f "$ac_dir/install-sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break - elif test -f $ac_dir/install.sh; then + elif test -f "$ac_dir/install.sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break - elif test -f $ac_dir/shtool; then + elif test -f "$ac_dir/shtool"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/shtool install -c" break fi done if test -z "$ac_aux_dir"; then - { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&5 -echo "$as_me: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&2;} - { (exit 1); exit 1; }; } + as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 fi -ac_config_guess="$SHELL $ac_aux_dir/config.guess" -ac_config_sub="$SHELL $ac_aux_dir/config.sub" -ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure. + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or @@ -1356,22 +2399,23 @@ ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure. # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. -echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 -echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6 +# Reject install programs that cannot install multiple files. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 +$as_echo_n "checking for a BSD-compatible install... " >&6; } if test -z "$INSTALL"; then -if test "${ac_cv_path_install+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +if ${ac_cv_path_install+:} false; then : + $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - # Account for people who put trailing slashes in PATH elements. -case $as_dir/ in - ./ | .// | /cC/* | \ + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in #(( + ./ | .// | /[cC]/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ - ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \ + ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. @@ -1379,7 +2423,7 @@ case $as_dir/ in # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then + if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then if test $ac_prog = install && grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. @@ -1389,30 +2433,43 @@ case $as_dir/ in # program-specific install script used by HP pwplus--don't use. : else - ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" - break 3 + rm -rf conftest.one conftest.two conftest.dir + echo one > conftest.one + echo two > conftest.two + mkdir conftest.dir + if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && + test -s conftest.one && test -s conftest.two && + test -s conftest.dir/conftest.one && + test -s conftest.dir/conftest.two + then + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi fi fi done done ;; esac -done + done +IFS=$as_save_IFS + +rm -rf conftest.one conftest.two conftest.dir fi if test "${ac_cv_path_install+set}" = set; then INSTALL=$ac_cv_path_install else - # As a last resort, use the slow shell script. We don't cache a - # path for INSTALL within a source directory, because that will + # As a last resort, use the slow shell script. Don't cache a + # value for INSTALL within a source directory, because that will # break other packages using the cache if that directory is - # removed, or if the path is relative. + # removed, or if the value is a relative name. INSTALL=$ac_install_sh fi fi -echo "$as_me:$LINENO: result: $INSTALL" >&5 -echo "${ECHO_T}$INSTALL" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 +$as_echo "$INSTALL" >&6; } # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. @@ -1425,60 +2482,80 @@ test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' # Make sure we can run config.sub. -$ac_config_sub sun4 >/dev/null 2>&1 || - { { echo "$as_me:$LINENO: error: cannot run $ac_config_sub" >&5 -echo "$as_me: error: cannot run $ac_config_sub" >&2;} - { (exit 1); exit 1; }; } +$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || + as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 -echo "$as_me:$LINENO: checking build system type" >&5 -echo $ECHO_N "checking build system type... $ECHO_C" >&6 -if test "${ac_cv_build+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 +$as_echo_n "checking build system type... " >&6; } +if ${ac_cv_build+:} false; then : + $as_echo_n "(cached) " >&6 else - ac_cv_build_alias=$build_alias -test -z "$ac_cv_build_alias" && - ac_cv_build_alias=`$ac_config_guess` -test -z "$ac_cv_build_alias" && - { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5 -echo "$as_me: error: cannot guess build type; you must specify one" >&2;} - { (exit 1); exit 1; }; } -ac_cv_build=`$ac_config_sub $ac_cv_build_alias` || - { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_build_alias failed" >&5 -echo "$as_me: error: $ac_config_sub $ac_cv_build_alias failed" >&2;} - { (exit 1); exit 1; }; } + ac_build_alias=$build_alias +test "x$ac_build_alias" = x && + ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` +test "x$ac_build_alias" = x && + as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 +ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 fi -echo "$as_me:$LINENO: result: $ac_cv_build" >&5 -echo "${ECHO_T}$ac_cv_build" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 +$as_echo "$ac_cv_build" >&6; } +case $ac_cv_build in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; +esac build=$ac_cv_build -build_cpu=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` -build_vendor=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` -build_os=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_build +shift +build_cpu=$1 +build_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +build_os=$* +IFS=$ac_save_IFS +case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac -echo "$as_me:$LINENO: checking host system type" >&5 -echo $ECHO_N "checking host system type... $ECHO_C" >&6 -if test "${ac_cv_host+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 +$as_echo_n "checking host system type... " >&6; } +if ${ac_cv_host+:} false; then : + $as_echo_n "(cached) " >&6 else - ac_cv_host_alias=$host_alias -test -z "$ac_cv_host_alias" && - ac_cv_host_alias=$ac_cv_build_alias -ac_cv_host=`$ac_config_sub $ac_cv_host_alias` || - { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_host_alias failed" >&5 -echo "$as_me: error: $ac_config_sub $ac_cv_host_alias failed" >&2;} - { (exit 1); exit 1; }; } + if test "x$host_alias" = x; then + ac_cv_host=$ac_cv_build +else + ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 +fi fi -echo "$as_me:$LINENO: result: $ac_cv_host" >&5 -echo "${ECHO_T}$ac_cv_host" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 +$as_echo "$ac_cv_host" >&6; } +case $ac_cv_host in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; +esac host=$ac_cv_host -host_cpu=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` -host_vendor=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` -host_os=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_host +shift +host_cpu=$1 +host_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +host_os=$* +IFS=$ac_save_IFS +case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac +ac_config_files="$ac_config_files html/index.php" + + ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' @@ -1487,10 +2564,10 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. @@ -1500,35 +2577,37 @@ for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done -done + done +IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then - echo "$as_me:$LINENO: result: $CC" >&5 -echo "${ECHO_T}$CC" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi + fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_ac_ct_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. @@ -1538,39 +2617,50 @@ for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done -done + done +IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then - echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 -echo "${ECHO_T}$ac_ct_CC" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi - CC=$ac_ct_CC + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. @@ -1580,77 +2670,37 @@ for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done -done + done +IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then - echo "$as_me:$LINENO: result: $CC" >&5 -echo "${ECHO_T}$CC" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi -fi -if test -z "$ac_cv_prog_CC"; then - ac_ct_CC=$CC - # Extract the first word of "cc", so it can be a program name with args. -set dummy cc; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_ac_ct_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - if test -n "$ac_ct_CC"; then - ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_CC="cc" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 + fi -done -done - -fi -fi -ac_ct_CC=$ac_cv_prog_ac_ct_CC -if test -n "$ac_ct_CC"; then - echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 -echo "${ECHO_T}$ac_ct_CC" >&6 -else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 -fi - - CC=$ac_ct_CC -else - CC="$ac_cv_prog_CC" -fi - fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. @@ -1661,18 +2711,19 @@ for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done -done + done +IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. @@ -1690,24 +2741,25 @@ fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then - echo "$as_me:$LINENO: result: $CC" >&5 -echo "${ECHO_T}$CC" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi + fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then - for ac_prog in cl + for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. @@ -1717,39 +2769,41 @@ for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done -done + done +IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then - echo "$as_me:$LINENO: result: $CC" >&5 -echo "${ECHO_T}$CC" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi + test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC - for ac_prog in cl + for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_prog_ac_ct_CC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. @@ -1759,66 +2813,78 @@ for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done -done + done +IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then - echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 -echo "${ECHO_T}$ac_ct_CC" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi + test -n "$ac_ct_CC" && break done - CC=$ac_ct_CC + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi fi fi -test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH -See \`config.log' for more details." >&5 -echo "$as_me: error: no acceptable C compiler found in \$PATH -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. -echo "$as_me:$LINENO:" \ - "checking for C compiler version" >&5 -ac_compiler=`set X $ac_compile; echo $2` -{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version &5\"") >&5 - (eval $ac_compiler --version &5) 2>&5 +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } -{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v &5\"") >&5 - (eval $ac_compiler -v &5) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } -{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V &5\"") >&5 - (eval $ac_compiler -V &5) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF +cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int @@ -1830,112 +2896,108 @@ main () } _ACEOF ac_clean_files_save=$ac_clean_files -ac_clean_files="$ac_clean_files a.out a.exe b.out" +ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. -echo "$as_me:$LINENO: checking for C compiler default output file name" >&5 -echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6 -ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` -if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5 - (eval $ac_link_default) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then - # Find the output, starting from the most likely. This scheme is -# not robust to junk in `.', hence go to wildcards (a.*) only as a last -# resort. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 +$as_echo_n "checking whether the C compiler works... " >&6; } +ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` -# Be careful to initialize this variable, since it used to be cached. -# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile. -ac_cv_exeext= -# b.out is created by i960 compilers. -for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out +# The possible output files: +ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" + +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { { ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) - ;; - conftest.$ac_ext ) - # This is the source file. + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) - ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` - # FIXME: I believe we export ac_cv_exeext for Libtool, - # but it would be cool to find out if it's true. Does anybody - # maintain Libtool? --akim. - export ac_cv_exeext + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. break;; * ) break;; esac done +test "$ac_cv_exeext" = no && ac_cv_exeext= + else - echo "$as_me: failed program was:" >&5 + ac_file='' +fi +if test -z "$ac_file"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +$as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 -{ { echo "$as_me:$LINENO: error: C compiler cannot create executables -See \`config.log' for more details." >&5 -echo "$as_me: error: C compiler cannot create executables -See \`config.log' for more details." >&2;} - { (exit 77); exit 77; }; } +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "C compiler cannot create executables +See \`config.log' for more details" "$LINENO" 5; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } fi - +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 +$as_echo_n "checking for C compiler default output file name... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 +$as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext -echo "$as_me:$LINENO: result: $ac_file" >&5 -echo "${ECHO_T}$ac_file" >&6 -# Check the compiler produces executables we can run. If not, either -# the compiler is broken, or we cross compile. -echo "$as_me:$LINENO: checking whether the C compiler works" >&5 -echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6 -# FIXME: These cross compiler hacks should be removed for Autoconf 3.0 -# If not cross compiling, check that we can run a simple program. -if test "$cross_compiling" != yes; then - if { ac_try='./$ac_file' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - cross_compiling=no - else - if test "$cross_compiling" = maybe; then - cross_compiling=yes - else - { { echo "$as_me:$LINENO: error: cannot run C compiled programs. -If you meant to cross compile, use \`--host'. -See \`config.log' for more details." >&5 -echo "$as_me: error: cannot run C compiled programs. -If you meant to cross compile, use \`--host'. -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } - fi - fi -fi -echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6 - -rm -f a.out a.exe conftest$ac_cv_exeext b.out +rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save -# Check the compiler produces executables we can run. If not, either -# the compiler is broken, or we cross compile. -echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 -echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6 -echo "$as_me:$LINENO: result: $cross_compiling" >&5 -echo "${ECHO_T}$cross_compiling" >&6 - -echo "$as_me:$LINENO: checking for suffix of executables" >&5 -echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6 -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 +$as_echo_n "checking for suffix of executables... " >&6; } +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with @@ -1943,38 +3005,90 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;; + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` - export ac_cv_exeext break;; * ) break;; esac done else - { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link -See \`config.log' for more details." >&5 -echo "$as_me: error: cannot compute suffix of executables: cannot compile and link -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details" "$LINENO" 5; } fi - -rm -f conftest$ac_cv_exeext -echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 -echo "${ECHO_T}$ac_cv_exeext" >&6 +rm -f conftest conftest$ac_cv_exeext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 +$as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT -echo "$as_me:$LINENO: checking for suffix of object files" >&5 -echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6 -if test "${ac_cv_objext+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +FILE *f = fopen ("conftest.out", "w"); + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} _ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF +ac_clean_files="$ac_clean_files conftest.out" +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 +$as_echo_n "checking whether we are cross compiling... " >&6; } +if test "$cross_compiling" != yes; then + { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if { ac_try='./conftest$ac_cv_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details" "$LINENO" 5; } + fi + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 +$as_echo "$cross_compiling" >&6; } + +rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 +$as_echo_n "checking for suffix of object files... " >&6; } +if ${ac_cv_objext+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int @@ -1986,45 +3100,46 @@ main () } _ACEOF rm -f conftest.o conftest.obj -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&5 +if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>&5 ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; then - for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;; + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else - echo "$as_me: failed program was:" >&5 + $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 -{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile -See \`config.log' for more details." >&5 -echo "$as_me: error: cannot compute suffix of object files: cannot compile -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of object files: cannot compile +See \`config.log' for more details" "$LINENO" 5; } fi - rm -f conftest.$ac_cv_objext conftest.$ac_ext fi -echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 -echo "${ECHO_T}$ac_cv_objext" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 +$as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT -echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 -echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6 -if test "${ac_cv_c_compiler_gnu+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if ${ac_cv_c_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int @@ -2038,55 +3153,34 @@ main () return 0; } _ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then +if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_compiler_gnu=no + ac_compiler_gnu=no fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi -echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 -echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6 -GCC=`test $ac_compiler_gnu = yes && echo yes` +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS -CFLAGS="-g" -echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 -echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6 -if test "${ac_cv_prog_cc_g+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if ${ac_cv_prog_cc_g+:} false; then : + $as_echo_n "(cached) " >&6 else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int @@ -2097,39 +3191,49 @@ main () return 0; } _ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then +if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ -ac_cv_prog_cc_g=no +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi -echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 -echo "${ECHO_T}$ac_cv_prog_cc_g" >&6 +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then @@ -2145,23 +3249,18 @@ else CFLAGS= fi fi -echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5 -echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6 -if test "${ac_cv_prog_cc_stdc+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 else - ac_cv_prog_cc_stdc=no + ac_cv_prog_cc_c89=no ac_save_CC=$CC -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF +cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include -#include -#include +struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); @@ -2184,12 +3283,17 @@ static char *f (char * (*g) (char **, int), char **p, ...) /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated - as 'x'. The following induces an error, until -std1 is added to get + as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something - that's true only with -std1. */ + that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; @@ -2204,246 +3308,91 @@ return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; return 0; } _ACEOF -# Don't try gcc -ansi; that turns off useful extensions and -# breaks some systems' header files. -# AIX -qlanglvl=ansi -# Ultrix and OSF/1 -std1 -# HP-UX 10.20 and later -Ae -# HP-UX older versions -Aa -D_HPUX_SOURCE -# SVR4 -Xc -D__EXTENSIONS__ -for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" - rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_prog_cc_stdc=$ac_arg -break -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg fi -rm -f conftest.err conftest.$ac_objext +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break done -rm -f conftest.$ac_ext conftest.$ac_objext +rm -f conftest.$ac_ext CC=$ac_save_CC fi - -case "x$ac_cv_prog_cc_stdc" in - x|xno) - echo "$as_me:$LINENO: result: none needed" >&5 -echo "${ECHO_T}none needed" >&6 ;; +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; *) - echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5 -echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6 - CC="$CC $ac_cv_prog_cc_stdc" ;; + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac - -# Some people use a C++ compiler to compile C. Since we use `exit', -# in C++ we need to declare it. In case someone uses the same compiler -# for both compiling C and C++ we need to have the C++ compiler decide -# the declaration of exit, since it's the most demanding environment. -cat >conftest.$ac_ext <<_ACEOF -#ifndef __cplusplus - choke me -#endif -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - for ac_declaration in \ - '' \ - 'extern "C" void std::exit (int) throw (); using std::exit;' \ - 'extern "C" void std::exit (int); using std::exit;' \ - 'extern "C" void exit (int) throw ();' \ - 'extern "C" void exit (int);' \ - 'void exit (int);' -do - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_declaration -#include -int -main () -{ -exit (42); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - : -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -continue -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_declaration -int -main () -{ -exit (42); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - break -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 +if test "x$ac_cv_prog_cc_c89" != xno; then : fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -done -rm -f conftest* -if test -n "$ac_declaration"; then - echo '#ifdef __cplusplus' >>confdefs.h - echo $ac_declaration >>confdefs.h - echo '#endif' >>confdefs.h -fi -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu -echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5 -echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6 -set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,:./+-,___p_,'` -if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } +set x ${MAKE-make} +ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : + $as_echo_n "(cached) " >&6 else cat >conftest.make <<\_ACEOF +SHELL = /bin/sh all: - @echo 'ac_maketemp="$(MAKE)"' + @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF -# GNU make sometimes prints "make[1]: Entering...", which would confuse us. -eval `${MAKE-make} -f conftest.make 2>/dev/null | grep temp=` -if test -n "$ac_maketemp"; then - eval ac_cv_prog_make_${ac_make}_set=yes -else - eval ac_cv_prog_make_${ac_make}_set=no -fi +# GNU make sometimes prints "make[1]: Entering ...", which would confuse us. +case `${MAKE-make} -f conftest.make 2>/dev/null` in + *@@@%%%=?*=@@@%%%*) + eval ac_cv_prog_make_${ac_make}_set=yes;; + *) + eval ac_cv_prog_make_${ac_make}_set=no;; +esac rm -f conftest.make fi -if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then - echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6 +if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } SET_MAKE= else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 +$as_echo_n "checking whether ln -s works... " >&6; } +LN_S=$as_ln_s +if test "$LN_S" = "ln -s"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 +$as_echo "no, using $LN_S" >&6; } +fi + # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_path_STRIP+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 else case $STRIP in [\\/]* | ?:[\\/]*) @@ -2455,45 +3404,46 @@ for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_STRIP="$as_dir/$ac_word$ac_exec_ext" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done -done + done +IFS=$as_save_IFS test -z "$ac_cv_path_STRIP" && ac_cv_path_STRIP="true" ;; esac fi STRIP=$ac_cv_path_STRIP - if test -n "$STRIP"; then - echo "$as_me:$LINENO: result: $STRIP" >&5 -echo "${ECHO_T}$STRIP" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi + ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu -echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5 -echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 +$as_echo_n "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then - if test "${ac_cv_prog_CPP+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 + if ${ac_cv_prog_CPP+:} false; then : + $as_echo_n "(cached) " >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" @@ -2507,11 +3457,7 @@ do # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include @@ -2520,78 +3466,34 @@ cat >>conftest.$ac_ext <<_ACEOF #endif Syntax error _ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_c_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_c_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then - : -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 +if ac_fn_c_try_cpp "$LINENO"; then : +else # Broken: fails on valid input. continue fi -rm -f conftest.err conftest.$ac_ext +rm -f conftest.err conftest.i conftest.$ac_ext - # OK, works on sane cases. Now check whether non-existent headers + # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_c_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_c_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then +if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - # Passes both tests. ac_preproc_ok=: break fi -rm -f conftest.err conftest.$ac_ext +rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.err conftest.$ac_ext -if $ac_preproc_ok; then +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : break fi @@ -2603,8 +3505,8 @@ fi else ac_cv_prog_CPP=$CPP fi -echo "$as_me:$LINENO: result: $CPP" >&5 -echo "${ECHO_T}$CPP" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 +$as_echo "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do @@ -2614,11 +3516,7 @@ do # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include @@ -2627,85 +3525,40 @@ cat >>conftest.$ac_ext <<_ACEOF #endif Syntax error _ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_c_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_c_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then - : -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 +if ac_fn_c_try_cpp "$LINENO"; then : +else # Broken: fails on valid input. continue fi -rm -f conftest.err conftest.$ac_ext +rm -f conftest.err conftest.i conftest.$ac_ext - # OK, works on sane cases. Now check whether non-existent headers + # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_c_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_c_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then +if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - # Passes both tests. ac_preproc_ok=: break fi -rm -f conftest.err conftest.$ac_ext +rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.err conftest.$ac_ext -if $ac_preproc_ok; then - : +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + else - { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check -See \`config.log' for more details." >&5 -echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c @@ -2715,31 +3568,142 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $ ac_compiler_gnu=$ac_cv_c_compiler_gnu -echo "$as_me:$LINENO: checking for egrep" >&5 -echo $ECHO_N "checking for egrep... $ECHO_C" >&6 -if test "${ac_cv_prog_egrep+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 +$as_echo_n "checking for grep that handles long lines and -e... " >&6; } +if ${ac_cv_path_GREP+:} false; then : + $as_echo_n "(cached) " >&6 else - if echo a | (grep -E '(a|b)') >/dev/null 2>&1 - then ac_cv_prog_egrep='grep -E' - else ac_cv_prog_egrep='egrep' + if test -z "$GREP"; then + ac_path_GREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_GREP" || continue +# Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count fi -fi -echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5 -echo "${ECHO_T}$ac_cv_prog_egrep" >&6 - EGREP=$ac_cv_prog_egrep + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac - -echo "$as_me:$LINENO: checking for ANSI C header files" >&5 -echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6 -if test "${ac_cv_header_stdc+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 + $ac_path_GREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_GREP"; then + as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF + ac_cv_path_GREP=$GREP +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 +$as_echo "$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 +$as_echo_n "checking for egrep... " >&6; } +if ${ac_cv_path_EGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + if test -z "$EGREP"; then + ac_path_EGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_EGREP" || continue +# Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_EGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_EGREP"; then + as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_EGREP=$EGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 +$as_echo "$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include @@ -2754,51 +3718,23 @@ main () return 0; } _ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then +if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_header_stdc=no + ac_cv_header_stdc=no fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "memchr" >/dev/null 2>&1; then - : + $EGREP "memchr" >/dev/null 2>&1; then : + else ac_cv_header_stdc=no fi @@ -2808,18 +3744,14 @@ fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "free" >/dev/null 2>&1; then - : + $EGREP "free" >/dev/null 2>&1; then : + else ac_cv_header_stdc=no fi @@ -2829,16 +3761,13 @@ fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. - if test "$cross_compiling" = yes; then + if test "$cross_compiling" = yes; then : : else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include +#include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) @@ -2858,54 +3787,35 @@ main () for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) - exit(2); - exit (0); + return 2; + return 0; } _ACEOF -rm -f conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { ac_try='./conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - : -else - echo "$as_me: program exited with status $ac_status" >&5 -echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 +if ac_fn_c_try_run "$LINENO"; then : -( exit $ac_status ) -ac_cv_header_stdc=no +else + ac_cv_header_stdc=no fi -rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + fi fi -fi -echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 -echo "${ECHO_T}$ac_cv_header_stdc" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then -cat >>confdefs.h <<\_ACEOF -#define STDC_HEADERS 1 -_ACEOF +$as_echo "#define STDC_HEADERS 1" >>confdefs.h fi -echo "$as_me:$LINENO: checking whether time.h and sys/time.h may both be included" >&5 -echo $ECHO_N "checking whether time.h and sys/time.h may both be included... $ECHO_C" >&6 -if test "${ac_cv_header_time+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether time.h and sys/time.h may both be included" >&5 +$as_echo_n "checking whether time.h and sys/time.h may both be included... " >&6; } +if ${ac_cv_header_time+:} false; then : + $as_echo_n "(cached) " >&6 else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include @@ -2920,62 +3830,32 @@ return 0; return 0; } _ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then +if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_time=yes else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_header_time=no + ac_cv_header_time=no fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi -echo "$as_me:$LINENO: result: $ac_cv_header_time" >&5 -echo "${ECHO_T}$ac_cv_header_time" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_time" >&5 +$as_echo "$ac_cv_header_time" >&6; } if test $ac_cv_header_time = yes; then -cat >>confdefs.h <<\_ACEOF -#define TIME_WITH_SYS_TIME 1 -_ACEOF +$as_echo "#define TIME_WITH_SYS_TIME 1" >>confdefs.h fi -echo "$as_me:$LINENO: checking for sys/wait.h that is POSIX.1 compatible" >&5 -echo $ECHO_N "checking for sys/wait.h that is POSIX.1 compatible... $ECHO_C" >&6 -if test "${ac_cv_header_sys_wait_h+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sys/wait.h that is POSIX.1 compatible" >&5 +$as_echo_n "checking for sys/wait.h that is POSIX.1 compatible... " >&6; } +if ${ac_cv_header_sys_wait_h+:} false; then : + $as_echo_n "(cached) " >&6 else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #ifndef WEXITSTATUS -# define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8) +# define WEXITSTATUS(stat_val) ((unsigned int) (stat_val) >> 8) #endif #ifndef WIFEXITED # define WIFEXITED(stat_val) (((stat_val) & 255) == 0) @@ -2991,112 +3871,31 @@ main () return 0; } _ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then +if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_sys_wait_h=yes else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_header_sys_wait_h=no + ac_cv_header_sys_wait_h=no fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi -echo "$as_me:$LINENO: result: $ac_cv_header_sys_wait_h" >&5 -echo "${ECHO_T}$ac_cv_header_sys_wait_h" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_sys_wait_h" >&5 +$as_echo "$ac_cv_header_sys_wait_h" >&6; } if test $ac_cv_header_sys_wait_h = yes; then -cat >>confdefs.h <<\_ACEOF -#define HAVE_SYS_WAIT_H 1 -_ACEOF +$as_echo "#define HAVE_SYS_WAIT_H 1" >>confdefs.h fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. - - - - - - - - - for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h -do -as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` -echo "$as_me:$LINENO: checking for $ac_header" >&5 -echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 -if eval "test \"\${$as_ac_Header+set}\" = set"; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default - -#include <$ac_header> -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - eval "$as_ac_Header=yes" -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -eval "$as_ac_Header=no" -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 -echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 -if test `eval echo '${'$as_ac_Header'}'` = yes; then +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF -#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi @@ -3104,187 +3903,90 @@ fi done - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -for ac_header in arpa/inet.h ctype.h dirent.h errno.h fcntl.h getopt.h grp.h libgen.h limits.h math.h netdb.h netinet/in.h pthread.h pthreads.h pwd.h regex.h signal.h socket.h stdarg.h string.h strings.h sys/mman.h sys/types.h sys/time.h sys/resource.h sys/wait.h sys/socket.h sys/stat.h sys/timeb.h sys/un.h sys/ipc.h sys/msg.h sys/poll.h syslog.h uio.h unistd.h locale.h wchar.h -do -as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` -if eval "test \"\${$as_ac_Header+set}\" = set"; then - echo "$as_me:$LINENO: checking for $ac_header" >&5 -echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 -if eval "test \"\${$as_ac_Header+set}\" = set"; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -fi -echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 -echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 -else - # Is the header compilable? -echo "$as_me:$LINENO: checking $ac_header usability" >&5 -echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -#include <$ac_header> -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_header_compiler=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_header_compiler=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 -echo "${ECHO_T}$ac_header_compiler" >&6 - -# Is the header present? -echo "$as_me:$LINENO: checking $ac_header presence" >&5 -echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include <$ac_header> -_ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_c_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_c_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then - ac_header_preproc=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_header_preproc=no -fi -rm -f conftest.err conftest.$ac_ext -echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 -echo "${ECHO_T}$ac_header_preproc" >&6 - -# So? What about this header? -case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in - yes:no: ) - { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 -echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 -echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} - ac_header_preproc=yes - ;; - no:yes:* ) - { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 -echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 -echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 -echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 -echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 -echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 -echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} - ( - cat <<\_ASBOX -## ------------------------------------------ ## -## Report this to the AC_PACKAGE_NAME lists. ## -## ------------------------------------------ ## -_ASBOX - ) | - sed "s/^/$as_me: WARNING: /" >&2 - ;; -esac -echo "$as_me:$LINENO: checking for $ac_header" >&5 -echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 -if eval "test \"\${$as_ac_Header+set}\" = set"; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - eval "$as_ac_Header=\$ac_header_preproc" -fi -echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 -echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 - -fi -if test `eval echo '${'$as_ac_Header'}'` = yes; then +for ac_header in arpa/inet.h ctype.h dirent.h errno.h fcntl.h getopt.h grp.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF -#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +for ac_header in libgen.h limits.h math.h netdb.h netinet/in.h pwd.h regex.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +for ac_header in signal.h socket.h stdarg.h string.h strings.h sys/loadavg.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +for ac_header in sys/mman.h sys/types.h sys/time.h sys/resource.h sys/wait.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +for ac_header in sys/socket.h sys/stat.h sys/timeb.h sys/un.h sys/ipc.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +for ac_header in sys/msg.h sys/poll.h syslog.h uio.h unistd.h locale.h wchar.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +for ac_header in sys/prctl.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "sys/prctl.h" "ac_cv_header_sys_prctl_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_prctl_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SYS_PRCTL_H 1 _ACEOF fi @@ -3292,29 +3994,25 @@ fi done -echo "$as_me:$LINENO: checking for an ANSI C-conforming const" >&5 -echo $ECHO_N "checking for an ANSI C-conforming const... $ECHO_C" >&6 -if test "${ac_cv_c_const+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5 +$as_echo_n "checking for an ANSI C-conforming const... " >&6; } +if ${ac_cv_c_const+:} false; then : + $as_echo_n "(cached) " >&6 else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { -/* FIXME: Include the comments suggested by Paul. */ + #ifndef __cplusplus - /* Ultrix mips cc rejects this. */ + /* Ultrix mips cc rejects this sort of thing. */ typedef int charset[2]; - const charset x; + const charset cs = { 0, 0 }; /* SunOS 4.1.1 cc rejects this. */ - char const *const *ccp; - char **p; + char const *const *pcpcc; + char **ppc; /* NEC SVR4.0.2 mips cc rejects this. */ struct point {int x, y;}; static struct point const zero = {0,0}; @@ -3323,16 +4021,18 @@ main () an arm of an if-expression whose if-part is not a constant expression */ const char *g = "string"; - ccp = &g + (g ? g-g : 0); + pcpcc = &g + (g ? g-g : 0); /* HPUX 7.0 cc rejects these. */ - ++ccp; - p = (char**) ccp; - ccp = (char const *const *) p; - { /* SCO 3.2v4 cc rejects this. */ - char *t; + ++pcpcc; + ppc = (char**) pcpcc; + pcpcc = (char const *const *) ppc; + { /* SCO 3.2v4 cc rejects this sort of thing. */ + char tx; + char *t = &tx; char const *s = 0 ? (char *) 0 : (char const *) 0; *t++ = 0; + if (s) return 0; } { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ int x[] = {25, 17}; @@ -3344,71 +4044,43 @@ main () iptr p = 0; ++p; } - { /* AIX XL C 1.02.0.0 rejects this saying + { /* AIX XL C 1.02.0.0 rejects this sort of thing, saying "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ - struct s { int j; const int *ap[3]; }; - struct s *b; b->j = 5; + struct s { int j; const int *ap[3]; } bx; + struct s *b = &bx; b->j = 5; } { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ const int foo = 10; + if (!foo) return 0; } + return !cs[0] && !zero.x; #endif ; return 0; } _ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then +if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_const=yes else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_c_const=no + ac_cv_c_const=no fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi -echo "$as_me:$LINENO: result: $ac_cv_c_const" >&5 -echo "${ECHO_T}$ac_cv_c_const" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_const" >&5 +$as_echo "$ac_cv_c_const" >&6; } if test $ac_cv_c_const = no; then -cat >>confdefs.h <<\_ACEOF -#define const -_ACEOF +$as_echo "#define const /**/" >>confdefs.h fi -echo "$as_me:$LINENO: checking whether struct tm is in sys/time.h or time.h" >&5 -echo $ECHO_N "checking whether struct tm is in sys/time.h or time.h... $ECHO_C" >&6 -if test "${ac_cv_struct_tm+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether struct tm is in sys/time.h or time.h" >&5 +$as_echo_n "checking whether struct tm is in sys/time.h or time.h... " >&6; } +if ${ac_cv_struct_tm+:} false; then : + $as_echo_n "(cached) " >&6 else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include @@ -3416,160 +4088,33 @@ cat >>conftest.$ac_ext <<_ACEOF int main () { -struct tm *tp; tp->tm_sec; +struct tm tm; + int *p = &tm.tm_sec; + return !p; ; return 0; } _ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then +if ac_fn_c_try_compile "$LINENO"; then : ac_cv_struct_tm=time.h else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_struct_tm=sys/time.h + ac_cv_struct_tm=sys/time.h fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi -echo "$as_me:$LINENO: result: $ac_cv_struct_tm" >&5 -echo "${ECHO_T}$ac_cv_struct_tm" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_struct_tm" >&5 +$as_echo "$ac_cv_struct_tm" >&6; } if test $ac_cv_struct_tm = sys/time.h; then -cat >>confdefs.h <<\_ACEOF -#define TM_IN_SYS_TIME 1 -_ACEOF +$as_echo "#define TM_IN_SYS_TIME 1" >>confdefs.h fi -echo "$as_me:$LINENO: checking for struct tm.tm_zone" >&5 -echo $ECHO_N "checking for struct tm.tm_zone... $ECHO_C" >&6 -if test "${ac_cv_member_struct_tm_tm_zone+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include +ac_fn_c_check_member "$LINENO" "struct tm" "tm_zone" "ac_cv_member_struct_tm_tm_zone" "#include #include <$ac_cv_struct_tm> - -int -main () -{ -static struct tm ac_aggr; -if (ac_aggr.tm_zone) -return 0; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_member_struct_tm_tm_zone=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -#include <$ac_cv_struct_tm> - - -int -main () -{ -static struct tm ac_aggr; -if (sizeof ac_aggr.tm_zone) -return 0; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_member_struct_tm_tm_zone=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_member_struct_tm_tm_zone=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: $ac_cv_member_struct_tm_tm_zone" >&5 -echo "${ECHO_T}$ac_cv_member_struct_tm_tm_zone" >&6 -if test $ac_cv_member_struct_tm_tm_zone = yes; then +" +if test "x$ac_cv_member_struct_tm_tm_zone" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STRUCT_TM_TM_ZONE 1 @@ -3580,136 +4125,61 @@ fi if test "$ac_cv_member_struct_tm_tm_zone" = yes; then -cat >>confdefs.h <<\_ACEOF -#define HAVE_TM_ZONE 1 -_ACEOF +$as_echo "#define HAVE_TM_ZONE 1" >>confdefs.h else - echo "$as_me:$LINENO: checking for tzname" >&5 -echo $ECHO_N "checking for tzname... $ECHO_C" >&6 -if test "${ac_cv_var_tzname+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 + ac_fn_c_check_decl "$LINENO" "tzname" "ac_cv_have_decl_tzname" "#include +" +if test "x$ac_cv_have_decl_tzname" = xyes; then : + ac_have_decl=1 else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_TZNAME $ac_have_decl _ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for tzname" >&5 +$as_echo_n "checking for tzname... " >&6; } +if ${ac_cv_var_tzname+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include -#ifndef tzname /* For SGI. */ -extern char *tzname[]; /* RS6000 and others reject char **tzname. */ +#if !HAVE_DECL_TZNAME +extern char *tzname[]; #endif int main () { -atoi(*tzname); +return tzname[0][0]; ; return 0; } _ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then +if ac_fn_c_try_link "$LINENO"; then : ac_cv_var_tzname=yes else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_var_tzname=no + ac_cv_var_tzname=no fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext fi -echo "$as_me:$LINENO: result: $ac_cv_var_tzname" >&5 -echo "${ECHO_T}$ac_cv_var_tzname" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_var_tzname" >&5 +$as_echo "$ac_cv_var_tzname" >&6; } if test $ac_cv_var_tzname = yes; then -cat >>confdefs.h <<\_ACEOF -#define HAVE_TZNAME 1 -_ACEOF +$as_echo "#define HAVE_TZNAME 1" >>confdefs.h fi fi -echo "$as_me:$LINENO: checking for mode_t" >&5 -echo $ECHO_N "checking for mode_t... $ECHO_C" >&6 -if test "${ac_cv_type_mode_t+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -int -main () -{ -if ((mode_t *) 0) - return 0; -if (sizeof (mode_t)) - return 0; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_type_mode_t=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 +ac_fn_c_check_type "$LINENO" "mode_t" "ac_cv_type_mode_t" "$ac_includes_default" +if test "x$ac_cv_type_mode_t" = xyes; then : -ac_cv_type_mode_t=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: $ac_cv_type_mode_t" >&5 -echo "${ECHO_T}$ac_cv_type_mode_t" >&6 -if test $ac_cv_type_mode_t = yes; then - : else cat >>confdefs.h <<_ACEOF @@ -3718,64 +4188,9 @@ _ACEOF fi -echo "$as_me:$LINENO: checking for pid_t" >&5 -echo $ECHO_N "checking for pid_t... $ECHO_C" >&6 -if test "${ac_cv_type_pid_t+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -int -main () -{ -if ((pid_t *) 0) - return 0; -if (sizeof (pid_t)) - return 0; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_type_pid_t=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 +ac_fn_c_check_type "$LINENO" "pid_t" "ac_cv_type_pid_t" "$ac_includes_default" +if test "x$ac_cv_type_pid_t" = xyes; then : -ac_cv_type_pid_t=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: $ac_cv_type_pid_t" >&5 -echo "${ECHO_T}$ac_cv_type_pid_t" >&6 -if test $ac_cv_type_pid_t = yes; then - : else cat >>confdefs.h <<_ACEOF @@ -3784,157 +4199,62 @@ _ACEOF fi -echo "$as_me:$LINENO: checking for size_t" >&5 -echo $ECHO_N "checking for size_t... $ECHO_C" >&6 -if test "${ac_cv_type_size_t+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -int -main () -{ -if ((size_t *) 0) - return 0; -if (sizeof (size_t)) - return 0; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_type_size_t=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 +ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default" +if test "x$ac_cv_type_size_t" = xyes; then : -ac_cv_type_size_t=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: $ac_cv_type_size_t" >&5 -echo "${ECHO_T}$ac_cv_type_size_t" >&6 -if test $ac_cv_type_size_t = yes; then - : else cat >>confdefs.h <<_ACEOF -#define size_t unsigned +#define size_t unsigned int _ACEOF fi -echo "$as_me:$LINENO: checking return type of signal handlers" >&5 -echo $ECHO_N "checking return type of signal handlers... $ECHO_C" >&6 -if test "${ac_cv_type_signal+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking return type of signal handlers" >&5 +$as_echo_n "checking return type of signal handlers... " >&6; } +if ${ac_cv_type_signal+:} false; then : + $as_echo_n "(cached) " >&6 else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include -#ifdef signal -# undef signal -#endif -#ifdef __cplusplus -extern "C" void (*signal (int, void (*)(int)))(int); -#else -void (*signal ()) (); -#endif int main () { -int i; +return *(signal (0, 0)) (0) == 1; ; return 0; } _ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_type_signal=void +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_type_signal=int else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_type_signal=int + ac_cv_type_signal=void fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi -echo "$as_me:$LINENO: result: $ac_cv_type_signal" >&5 -echo "${ECHO_T}$ac_cv_type_signal" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_signal" >&5 +$as_echo "$ac_cv_type_signal" >&6; } cat >>confdefs.h <<_ACEOF #define RETSIGTYPE $ac_cv_type_signal _ACEOF -echo "$as_me:$LINENO: checking for uid_t in sys/types.h" >&5 -echo $ECHO_N "checking for uid_t in sys/types.h... $ECHO_C" >&6 -if test "${ac_cv_type_uid_t+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for uid_t in sys/types.h" >&5 +$as_echo_n "checking for uid_t in sys/types.h... " >&6; } +if ${ac_cv_type_uid_t+:} false; then : + $as_echo_n "(cached) " >&6 else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "uid_t" >/dev/null 2>&1; then + $EGREP "uid_t" >/dev/null 2>&1; then : ac_cv_type_uid_t=yes else ac_cv_type_uid_t=no @@ -3942,37 +4262,29 @@ fi rm -f conftest* fi -echo "$as_me:$LINENO: result: $ac_cv_type_uid_t" >&5 -echo "${ECHO_T}$ac_cv_type_uid_t" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_uid_t" >&5 +$as_echo "$ac_cv_type_uid_t" >&6; } if test $ac_cv_type_uid_t = no; then -cat >>confdefs.h <<\_ACEOF -#define uid_t int -_ACEOF +$as_echo "#define uid_t int" >>confdefs.h -cat >>confdefs.h <<\_ACEOF -#define gid_t int -_ACEOF +$as_echo "#define gid_t int" >>confdefs.h fi -echo "$as_me:$LINENO: checking type of array argument to getgroups" >&5 -echo $ECHO_N "checking type of array argument to getgroups... $ECHO_C" >&6 -if test "${ac_cv_type_getgroups+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking type of array argument to getgroups" >&5 +$as_echo_n "checking type of array argument to getgroups... " >&6; } +if ${ac_cv_type_getgroups+:} false; then : + $as_echo_n "(cached) " >&6 else - if test "$cross_compiling" = yes; then + if test "$cross_compiling" = yes; then : ac_cv_type_getgroups=cross else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Thanks to Mike Rendell for this test. */ -#include +$ac_includes_default #define NGID 256 #undef MAX #define MAX(x, y) ((x) > (y) ? (x) : (y)) @@ -3982,7 +4294,7 @@ main () { gid_t gidset[NGID]; int i, n; - union { gid_t gval; long lval; } val; + union { gid_t gval; long int lval; } val; val.lval = -1; for (i = 0; i < NGID; i++) @@ -3990,44 +4302,28 @@ main () n = getgroups (sizeof (gidset) / MAX (sizeof (int), sizeof (gid_t)) - 1, gidset); /* Exit non-zero if getgroups seems to require an array of ints. This - happens when gid_t is short but getgroups modifies an array of ints. */ - exit ((n > 0 && gidset[n] != val.gval) ? 1 : 0); + happens when gid_t is short int but getgroups modifies an array + of ints. */ + return n > 0 && gidset[n] != val.gval; } _ACEOF -rm -f conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { ac_try='./conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then +if ac_fn_c_try_run "$LINENO"; then : ac_cv_type_getgroups=gid_t else - echo "$as_me: program exited with status $ac_status" >&5 -echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 + ac_cv_type_getgroups=int +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi -( exit $ac_status ) -ac_cv_type_getgroups=int -fi -rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext -fi if test $ac_cv_type_getgroups = cross; then - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "getgroups.*int.*gid_t" >/dev/null 2>&1; then + $EGREP "getgroups.*int.*gid_t" >/dev/null 2>&1; then : ac_cv_type_getgroups=gid_t else ac_cv_type_getgroups=int @@ -4036,8 +4332,8 @@ rm -f conftest* fi fi -echo "$as_me:$LINENO: result: $ac_cv_type_getgroups" >&5 -echo "${ECHO_T}$ac_cv_type_getgroups" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_getgroups" >&5 +$as_echo "$ac_cv_type_getgroups" >&6; } cat >>confdefs.h <<_ACEOF #define GETGROUPS_T $ac_cv_type_getgroups @@ -4046,17 +4342,13 @@ _ACEOF -echo "$as_me:$LINENO: checking for va_copy" >&5 -echo $ECHO_N "checking for va_copy... $ECHO_C" >&6 -if test "${ac_cv_HAVE_VA_COPY+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for va_copy" >&5 +$as_echo_n "checking for va_copy... " >&6; } +if ${ac_cv_HAVE_VA_COPY+:} false; then : + $as_echo_n "(cached) " >&6 else -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF +cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include va_list ap1,ap2; @@ -4068,58 +4360,28 @@ va_copy(ap1,ap2); return 0; } _ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then +if ac_fn_c_try_link "$LINENO"; then : ac_cv_HAVE_VA_COPY=yes else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_HAVE_VA_COPY=no + ac_cv_HAVE_VA_COPY=no fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext fi -echo "$as_me:$LINENO: result: $ac_cv_HAVE_VA_COPY" >&5 -echo "${ECHO_T}$ac_cv_HAVE_VA_COPY" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_HAVE_VA_COPY" >&5 +$as_echo "$ac_cv_HAVE_VA_COPY" >&6; } if test x"$ac_cv_HAVE_VA_COPY" = x"yes"; then -cat >>confdefs.h <<\_ACEOF -#define HAVE_VA_COPY 1 -_ACEOF +$as_echo "#define HAVE_VA_COPY 1" >>confdefs.h else - echo "$as_me:$LINENO: checking for __va_copy" >&5 -echo $ECHO_N "checking for __va_copy... $ECHO_C" >&6 -if test "${ac_cv_HAVE___VA_COPY+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __va_copy" >&5 +$as_echo_n "checking for __va_copy... " >&6; } +if ${ac_cv_HAVE___VA_COPY+:} false; then : + $as_echo_n "(cached) " >&6 else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include va_list ap1,ap2; @@ -4131,448 +4393,73 @@ __va_copy(ap1,ap2); return 0; } _ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then +if ac_fn_c_try_link "$LINENO"; then : ac_cv_HAVE___VA_COPY=yes else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_HAVE___VA_COPY=no + ac_cv_HAVE___VA_COPY=no fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext fi -echo "$as_me:$LINENO: result: $ac_cv_HAVE___VA_COPY" >&5 -echo "${ECHO_T}$ac_cv_HAVE___VA_COPY" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_HAVE___VA_COPY" >&5 +$as_echo "$ac_cv_HAVE___VA_COPY" >&6; } if test x"$ac_cv_HAVE___VA_COPY" = x"yes"; then -cat >>confdefs.h <<\_ACEOF -#define HAVE___VA_COPY 1 -_ACEOF +$as_echo "#define HAVE___VA_COPY 1" >>confdefs.h fi fi -echo "$as_me:$LINENO: checking for vsnprintf" >&5 -echo $ECHO_N "checking for vsnprintf... $ECHO_C" >&6 -if test "${ac_cv_func_vsnprintf+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +ac_fn_c_check_func "$LINENO" "vsnprintf" "ac_cv_func_vsnprintf" +if test "x$ac_cv_func_vsnprintf" = xyes; then : + else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ + SNPRINTF_O=../lib/snprintf.o +fi + +ac_fn_c_check_func "$LINENO" "snprintf" "ac_cv_func_snprintf" +if test "x$ac_cv_func_snprintf" = xyes; then : + +else + SNPRINTF_O=../lib/snprintf.o +fi + +ac_fn_c_check_func "$LINENO" "asprintf" "ac_cv_func_asprintf" +if test "x$ac_cv_func_asprintf" = xyes; then : + +else + SNPRINTF_O=../lib/snprintf.o +fi + +ac_fn_c_check_func "$LINENO" "vasprintf" "ac_cv_func_vasprintf" +if test "x$ac_cv_func_vasprintf" = xyes; then : + +else + SNPRINTF_O=../lib/snprintf.o +fi + +for ac_func in sigaction +do : + ac_fn_c_check_func "$LINENO" "sigaction" "ac_cv_func_sigaction" +if test "x$ac_cv_func_sigaction" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SIGACTION 1 _ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -/* Define vsnprintf to an innocuous variant, in case declares vsnprintf. - For example, HP-UX 11i declares gettimeofday. */ -#define vsnprintf innocuous_vsnprintf -/* System header to define __stub macros and hopefully few prototypes, - which can conflict with char vsnprintf (); below. - Prefer to if __STDC__ is defined, since - exists even on freestanding compilers. */ - -#ifdef __STDC__ -# include -#else -# include -#endif - -#undef vsnprintf - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -{ -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char vsnprintf (); -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined (__stub_vsnprintf) || defined (__stub___vsnprintf) -choke me -#else -char (*f) () = vsnprintf; -#endif -#ifdef __cplusplus -} -#endif - -int -main () -{ -return f != vsnprintf; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_func_vsnprintf=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_func_vsnprintf=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: $ac_cv_func_vsnprintf" >&5 -echo "${ECHO_T}$ac_cv_func_vsnprintf" >&6 -if test $ac_cv_func_vsnprintf = yes; then - : -else - SNPRINTF_O=../common/snprintf.o -fi - -echo "$as_me:$LINENO: checking for snprintf" >&5 -echo $ECHO_N "checking for snprintf... $ECHO_C" >&6 -if test "${ac_cv_func_snprintf+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -/* Define snprintf to an innocuous variant, in case declares snprintf. - For example, HP-UX 11i declares gettimeofday. */ -#define snprintf innocuous_snprintf - -/* System header to define __stub macros and hopefully few prototypes, - which can conflict with char snprintf (); below. - Prefer to if __STDC__ is defined, since - exists even on freestanding compilers. */ - -#ifdef __STDC__ -# include -#else -# include -#endif - -#undef snprintf - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -{ -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char snprintf (); -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined (__stub_snprintf) || defined (__stub___snprintf) -choke me -#else -char (*f) () = snprintf; -#endif -#ifdef __cplusplus -} -#endif - -int -main () -{ -return f != snprintf; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_func_snprintf=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_func_snprintf=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: $ac_cv_func_snprintf" >&5 -echo "${ECHO_T}$ac_cv_func_snprintf" >&6 -if test $ac_cv_func_snprintf = yes; then - : -else - SNPRINTF_O=../common/snprintf.o -fi - -echo "$as_me:$LINENO: checking for asprintf" >&5 -echo $ECHO_N "checking for asprintf... $ECHO_C" >&6 -if test "${ac_cv_func_asprintf+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -/* Define asprintf to an innocuous variant, in case declares asprintf. - For example, HP-UX 11i declares gettimeofday. */ -#define asprintf innocuous_asprintf - -/* System header to define __stub macros and hopefully few prototypes, - which can conflict with char asprintf (); below. - Prefer to if __STDC__ is defined, since - exists even on freestanding compilers. */ - -#ifdef __STDC__ -# include -#else -# include -#endif - -#undef asprintf - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -{ -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char asprintf (); -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined (__stub_asprintf) || defined (__stub___asprintf) -choke me -#else -char (*f) () = asprintf; -#endif -#ifdef __cplusplus -} -#endif - -int -main () -{ -return f != asprintf; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_func_asprintf=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_func_asprintf=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: $ac_cv_func_asprintf" >&5 -echo "${ECHO_T}$ac_cv_func_asprintf" >&6 -if test $ac_cv_func_asprintf = yes; then - : -else - SNPRINTF_O=../common/snprintf.o -fi - -echo "$as_me:$LINENO: checking for vasprintf" >&5 -echo $ECHO_N "checking for vasprintf... $ECHO_C" >&6 -if test "${ac_cv_func_vasprintf+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -/* Define vasprintf to an innocuous variant, in case declares vasprintf. - For example, HP-UX 11i declares gettimeofday. */ -#define vasprintf innocuous_vasprintf - -/* System header to define __stub macros and hopefully few prototypes, - which can conflict with char vasprintf (); below. - Prefer to if __STDC__ is defined, since - exists even on freestanding compilers. */ - -#ifdef __STDC__ -# include -#else -# include -#endif - -#undef vasprintf - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -{ -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char vasprintf (); -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined (__stub_vasprintf) || defined (__stub___vasprintf) -choke me -#else -char (*f) () = vasprintf; -#endif -#ifdef __cplusplus -} -#endif - -int -main () -{ -return f != vasprintf; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_func_vasprintf=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_func_vasprintf=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: $ac_cv_func_vasprintf" >&5 -echo "${ECHO_T}$ac_cv_func_vasprintf" >&6 -if test $ac_cv_func_vasprintf = yes; then - : -else - SNPRINTF_O=../common/snprintf.o fi +done -echo "$as_me:$LINENO: checking for C99 vsnprintf" >&5 -echo $ECHO_N "checking for C99 vsnprintf... $ECHO_C" >&6 -if test "${ac_cv_HAVE_C99_VSNPRINTF+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C99 vsnprintf" >&5 +$as_echo_n "checking for C99 vsnprintf... " >&6; } +if ${ac_cv_HAVE_C99_VSNPRINTF+:} false; then : + $as_echo_n "(cached) " >&6 else -if test "$cross_compiling" = yes; then +if test "$cross_compiling" = yes; then : ac_cv_HAVE_C99_VSNPRINTF=cross else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include @@ -4599,414 +4486,160 @@ void foo(const char *format, ...) { main() { foo("hello"); } _ACEOF -rm -f conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && { ac_try='./conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then +if ac_fn_c_try_run "$LINENO"; then : ac_cv_HAVE_C99_VSNPRINTF=yes else - echo "$as_me: program exited with status $ac_status" >&5 -echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 + ac_cv_HAVE_C99_VSNPRINTF=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi -( exit $ac_status ) -ac_cv_HAVE_C99_VSNPRINTF=no fi -rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext -fi -fi -echo "$as_me:$LINENO: result: $ac_cv_HAVE_C99_VSNPRINTF" >&5 -echo "${ECHO_T}$ac_cv_HAVE_C99_VSNPRINTF" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_HAVE_C99_VSNPRINTF" >&5 +$as_echo "$ac_cv_HAVE_C99_VSNPRINTF" >&6; } if test x"$ac_cv_HAVE_C99_VSNPRINTF" = x"yes"; then -cat >>confdefs.h <<\_ACEOF -#define HAVE_C99_VSNPRINTF 1 -_ACEOF +$as_echo "#define HAVE_C99_VSNPRINTF 1" >>confdefs.h fi -echo "$as_me:$LINENO: checking for library containing getservbyname" >&5 -echo $ECHO_N "checking for library containing getservbyname... $ECHO_C" >&6 -if test "${ac_cv_search_getservbyname+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing getservbyname" >&5 +$as_echo_n "checking for library containing getservbyname... " >&6; } +if ${ac_cv_search_getservbyname+:} false; then : + $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS -ac_cv_search_getservbyname=no -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF +cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -/* Override any gcc2 internal prototype to avoid an error. */ +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ char getservbyname (); int main () { -getservbyname (); +return getservbyname (); ; return 0; } _ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_search_getservbyname="none required" -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -if test "$ac_cv_search_getservbyname" = no; then - for ac_lib in nsl; do +for ac_lib in '' nsl; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_getservbyname=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_getservbyname+:} false; then : + break +fi +done +if ${ac_cv_search_getservbyname+:} false; then : -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char getservbyname (); -int -main () -{ -getservbyname (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_search_getservbyname="-l$ac_lib" -break else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - done + ac_cv_search_getservbyname=no fi +rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi -echo "$as_me:$LINENO: result: $ac_cv_search_getservbyname" >&5 -echo "${ECHO_T}$ac_cv_search_getservbyname" >&6 -if test "$ac_cv_search_getservbyname" != no; then - test "$ac_cv_search_getservbyname" = "none required" || LIBS="$ac_cv_search_getservbyname $LIBS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_getservbyname" >&5 +$as_echo "$ac_cv_search_getservbyname" >&6; } +ac_res=$ac_cv_search_getservbyname +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" if test "$ac_cv_search_getservbyname" != "none required"; then SOCKETLIBS="$SOCKETLIBS -lnsl" fi fi -echo "$as_me:$LINENO: checking for library containing connect" >&5 -echo $ECHO_N "checking for library containing connect... $ECHO_C" >&6 -if test "${ac_cv_search_connect+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing connect" >&5 +$as_echo_n "checking for library containing connect... " >&6; } +if ${ac_cv_search_connect+:} false; then : + $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS -ac_cv_search_connect=no -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF +cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -/* Override any gcc2 internal prototype to avoid an error. */ +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ char connect (); int main () { -connect (); +return connect (); ; return 0; } _ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_search_connect="none required" -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -if test "$ac_cv_search_connect" = no; then - for ac_lib in socket; do +for ac_lib in '' socket; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_connect=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_connect+:} false; then : + break +fi +done +if ${ac_cv_search_connect+:} false; then : -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char connect (); -int -main () -{ -connect (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_search_connect="-l$ac_lib" -break else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - done + ac_cv_search_connect=no fi +rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi -echo "$as_me:$LINENO: result: $ac_cv_search_connect" >&5 -echo "${ECHO_T}$ac_cv_search_connect" >&6 -if test "$ac_cv_search_connect" != no; then - test "$ac_cv_search_connect" = "none required" || LIBS="$ac_cv_search_connect $LIBS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_connect" >&5 +$as_echo "$ac_cv_search_connect" >&6; } +ac_res=$ac_cv_search_connect +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" if test "$ac_cv_search_connect" != "none required"; then SOCKETLIBS="$SOCKETLIBS -lsocket" fi fi - - - - - - for ac_func in initgroups setenv strdup strstr strtoul unsetenv -do -as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` -echo "$as_me:$LINENO: checking for $ac_func" >&5 -echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6 -if eval "test \"\${$as_ac_var+set}\" = set"; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -/* Define $ac_func to an innocuous variant, in case declares $ac_func. - For example, HP-UX 11i declares gettimeofday. */ -#define $ac_func innocuous_$ac_func - -/* System header to define __stub macros and hopefully few prototypes, - which can conflict with char $ac_func (); below. - Prefer to if __STDC__ is defined, since - exists even on freestanding compilers. */ - -#ifdef __STDC__ -# include -#else -# include -#endif - -#undef $ac_func - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -{ -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char $ac_func (); -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined (__stub_$ac_func) || defined (__stub___$ac_func) -choke me -#else -char (*f) () = $ac_func; -#endif -#ifdef __cplusplus -} -#endif - -int -main () -{ -return f != $ac_func; - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - eval "$as_ac_var=yes" -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -eval "$as_ac_var=no" -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5 -echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6 -if test `eval echo '${'$as_ac_var'}'` = yes; then +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF -#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1 +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done -echo "$as_me:$LINENO: checking for type of socket size" >&5 -echo $ECHO_N "checking for type of socket size... $ECHO_C" >&6 -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for type of socket size" >&5 +$as_echo_n "checking for type of socket size... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include @@ -5020,615 +4653,73 @@ int a = send(1, (const void *) 0, (size_t) 0, (int) 0); return 0; } _ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - -cat >>confdefs.h <<\_ACEOF -#define SOCKET_SIZE_TYPE size_t -_ACEOF - echo "$as_me:$LINENO: result: size_t" >&5 -echo "${ECHO_T}size_t" >&6 -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - -cat >>confdefs.h <<\_ACEOF -#define SOCKET_SIZE_TYPE int -_ACEOF - echo "$as_me:$LINENO: result: int" >&5 -echo "${ECHO_T}int" >&6 -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext - - -THREADLIBS="" -have_pthreads="no" - - - -echo "$as_me:$LINENO: checking for pthread_create in -lcma" >&5 -echo $ECHO_N "checking for pthread_create in -lcma... $ECHO_C" >&6 -if test "${ac_cv_lib_cma_pthread_create+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lcma $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char pthread_create (); -int -main () -{ -pthread_create (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_lib_cma_pthread_create=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_cma_pthread_create=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -echo "$as_me:$LINENO: result: $ac_cv_lib_cma_pthread_create" >&5 -echo "${ECHO_T}$ac_cv_lib_cma_pthread_create" >&6 -if test $ac_cv_lib_cma_pthread_create = yes; then - THREADLIBS="$THREADLIBS -lpthread" -fi - -if test $ac_cv_lib_cma_pthread_create = yes; then - have_pthreads="yes" -fi - -echo "$as_me:$LINENO: checking for pthread_create in -lpthread" >&5 -echo $ECHO_N "checking for pthread_create in -lpthread... $ECHO_C" >&6 -if test "${ac_cv_lib_pthread_pthread_create+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lpthread $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char pthread_create (); -int -main () -{ -pthread_create (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_lib_pthread_pthread_create=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_pthread_pthread_create=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -echo "$as_me:$LINENO: result: $ac_cv_lib_pthread_pthread_create" >&5 -echo "${ECHO_T}$ac_cv_lib_pthread_pthread_create" >&6 -if test $ac_cv_lib_pthread_pthread_create = yes; then - THREADLIBS="$THREADLIBS -lpthread" -fi - -if test $ac_cv_lib_pthread_pthread_create = yes; then - have_pthreads="yes" -else - echo "$as_me:$LINENO: checking for pthread_mutex_init in -lpthread" >&5 -echo $ECHO_N "checking for pthread_mutex_init in -lpthread... $ECHO_C" >&6 -if test "${ac_cv_lib_pthread_pthread_mutex_init+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lpthread $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char pthread_mutex_init (); -int -main () -{ -pthread_mutex_init (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_lib_pthread_pthread_mutex_init=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_pthread_pthread_mutex_init=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -echo "$as_me:$LINENO: result: $ac_cv_lib_pthread_pthread_mutex_init" >&5 -echo "${ECHO_T}$ac_cv_lib_pthread_pthread_mutex_init" >&6 -if test $ac_cv_lib_pthread_pthread_mutex_init = yes; then - THREADLIBS="$THREADLIBS -lpthread" -fi - - if test $ac_cv_lib_pthread_pthread_mutex_init = yes; then - have_pthreads="yes" - fi -fi - -if test $have_pthreads = "no"; then - echo "$as_me:$LINENO: checking for pthread_create in -lpthreads" >&5 -echo $ECHO_N "checking for pthread_create in -lpthreads... $ECHO_C" >&6 -if test "${ac_cv_lib_pthreads_pthread_create+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lpthreads $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char pthread_create (); -int -main () -{ -pthread_create (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_lib_pthreads_pthread_create=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_pthreads_pthread_create=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -echo "$as_me:$LINENO: result: $ac_cv_lib_pthreads_pthread_create" >&5 -echo "${ECHO_T}$ac_cv_lib_pthreads_pthread_create" >&6 -if test $ac_cv_lib_pthreads_pthread_create = yes; then - THREADLIBS="$THREADLIBS -lpthreads" -fi - - if test $ac_cv_lib_pthreads_pthread_create = yes; then - have_pthreads="yes" - fi -fi - -if test $have_pthreads = "no"; then - - echo "$as_me:$LINENO: checking for pthread_create in -llthread" >&5 -echo $ECHO_N "checking for pthread_create in -llthread... $ECHO_C" >&6 -if test "${ac_cv_lib_lthread_pthread_create+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-llthread -L/usr/local/lib $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char pthread_create (); -int -main () -{ -pthread_create (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_lib_lthread_pthread_create=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_lthread_pthread_create=no -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -echo "$as_me:$LINENO: result: $ac_cv_lib_lthread_pthread_create" >&5 -echo "${ECHO_T}$ac_cv_lib_lthread_pthread_create" >&6 -if test $ac_cv_lib_lthread_pthread_create = yes; then - - CFLAGS="-D_THREAD_SAFE -I/usr/local/include/pthread/linuxthreads -I/usr/include $CFLAGS" - THREADLIBS="-L/usr/local/lib -llthread -llgcc_r" +if ac_fn_c_try_compile "$LINENO"; then : +$as_echo "#define SOCKET_SIZE_TYPE size_t" >>confdefs.h + { $as_echo "$as_me:${as_lineno-$LINENO}: result: size_t" >&5 +$as_echo "size_t" >&6; } else - echo "$as_me:$LINENO: checking if we need -pthread for threads" >&5 -echo $ECHO_N "checking if we need -pthread for threads... $ECHO_C" >&6 - if test "${ac_ldflag_pthread+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - - ac_save_LDFLAGS="$LDFLAGS" - LDFLAGS="-pthread $LDFLAGS" - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ - - char pthread_create(); - -int -main () -{ -pthread_create(); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - eval "ac_ldflag_pthread=yes" -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -eval "ac_ldflag_pthread=no" - -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext, - THREADLIBS="$ac_save_LDFLAGS" - -fi - - if eval "test \"`echo $ac_ldflag_pthread`\" = yes"; then - echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6 - else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 - fi - +$as_echo "#define SOCKET_SIZE_TYPE int" >>confdefs.h + { $as_echo "$as_me:${as_lineno-$LINENO}: result: int" >&5 +$as_echo "int" >&6; } fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi - - - -echo "$as_me:$LINENO: checking for library containing nanosleep" >&5 -echo $ECHO_N "checking for library containing nanosleep... $ECHO_C" >&6 -if test "${ac_cv_search_nanosleep+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing nanosleep" >&5 +$as_echo_n "checking for library containing nanosleep... " >&6; } +if ${ac_cv_search_nanosleep+:} false; then : + $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS -ac_cv_search_nanosleep=no -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF +cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -/* Override any gcc2 internal prototype to avoid an error. */ +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ char nanosleep (); int main () { -nanosleep (); +return nanosleep (); ; return 0; } _ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_search_nanosleep="none required" -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -if test "$ac_cv_search_nanosleep" = no; then - for ac_lib in rt posix4; do +for ac_lib in '' rt posix4; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_nanosleep=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_nanosleep+:} false; then : + break +fi +done +if ${ac_cv_search_nanosleep+:} false; then : -/* Override any gcc2 internal prototype to avoid an error. */ -#ifdef __cplusplus -extern "C" -#endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ -char nanosleep (); -int -main () -{ -nanosleep (); - ; - return 0; -} -_ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_cv_search_nanosleep="-l$ac_lib" -break else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - done + ac_cv_search_nanosleep=no fi +rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi -echo "$as_me:$LINENO: result: $ac_cv_search_nanosleep" >&5 -echo "${ECHO_T}$ac_cv_search_nanosleep" >&6 -if test "$ac_cv_search_nanosleep" != no; then - test "$ac_cv_search_nanosleep" = "none required" || LIBS="$ac_cv_search_nanosleep $LIBS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_nanosleep" >&5 +$as_echo "$ac_cv_search_nanosleep" >&6; } +ac_res=$ac_cv_search_nanosleep +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" else @@ -5638,22 +4729,41 @@ else fi +case $host_os in +*bsd*|darwin*) + root_grp=wheel + ;; +*) + root_grp=root + ;; +esac -# Check whether --with-nagios_user or --without-nagios_user was given. -if test "${with_nagios_user+set}" = set; then - withval="$with_nagios_user" - nagios_user=$withval + +# Check whether --with-root_group was given. +if test "${with_root_group+set}" = set; then : + withval=$with_root_group; root_grp=$withval +fi + + +INIT_OPTS="-o root -g $root_grp" + + + +# Check whether --with-nagios_user was given. +if test "${with_nagios_user+set}" = set; then : + withval=$with_nagios_user; nagios_user=$withval else nagios_user=nagios -fi; +fi -# Check whether --with-nagios_group or --without-nagios_group was given. -if test "${with_nagios_group+set}" = set; then - withval="$with_nagios_group" - nagios_grp=$withval + +# Check whether --with-nagios_group was given. +if test "${with_nagios_group+set}" = set; then : + withval=$with_nagios_group; nagios_grp=$withval else nagios_grp=nagios -fi; +fi + @@ -5670,21 +4780,21 @@ INSTALL_OPTS="-o $nagios_user -g $nagios_grp" -# Check whether --with-command_user or --without-command_user was given. -if test "${with_command_user+set}" = set; then - withval="$with_command_user" - command_user=$withval +# Check whether --with-command_user was given. +if test "${with_command_user+set}" = set; then : + withval=$with_command_user; command_user=$withval else command_user=$nagios_user -fi; +fi -# Check whether --with-command_group or --without-command_group was given. -if test "${with_command_group+set}" = set; then - withval="$with_command_group" - command_grp=$withval + +# Check whether --with-command_group was given. +if test "${with_command_group+set}" = set; then : + withval=$with_command_group; command_grp=$withval else command_grp=$nagios_grp -fi; +fi + COMMAND_OPTS="-o $command_user -g $command_grp" @@ -5692,20 +4802,21 @@ COMMAND_OPTS="-o $command_user -g $command_grp" MAIL_PROG=no -# Check whether --with-mail or --without-mail was given. -if test "${with_mail+set}" = set; then - withval="$with_mail" - MAIL_PROG=$withval +# Check whether --with-mail was given. +if test "${with_mail+set}" = set; then : + withval=$with_mail; MAIL_PROG=$withval else MAIL_PROG=no -fi; + +fi + if test x$MAIL_PROG = xno; then # Extract the first word of "mail", so it can be a program name with args. set dummy mail; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_path_MAIL_PROG+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_MAIL_PROG+:} false; then : + $as_echo_n "(cached) " >&6 else case $MAIL_PROG in [\\/]* | ?:[\\/]*) @@ -5717,28 +4828,29 @@ for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_MAIL_PROG="$as_dir/$ac_word$ac_exec_ext" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done -done + done +IFS=$as_save_IFS ;; esac fi MAIL_PROG=$ac_cv_path_MAIL_PROG - if test -n "$MAIL_PROG"; then - echo "$as_me:$LINENO: result: $MAIL_PROG" >&5 -echo "${ECHO_T}$MAIL_PROG" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAIL_PROG" >&5 +$as_echo "$MAIL_PROG" >&6; } else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi + fi if test x$MAIL_PROG = x; then MAIL_PROG="/bin/mail" @@ -5747,18 +4859,27 @@ fi HTTP_CONF=no -# Check whether --with-httpd_conf or --without-httpd_conf was given. -if test "${with_httpd_conf+set}" = set; then - withval="$with_httpd_conf" - HTTPD_CONF=$withval +# Check whether --with-httpd_conf was given. +if test "${with_httpd_conf+set}" = set; then : + withval=$with_httpd_conf; HTTPD_CONF=$withval else HTTPD_CONF=no -fi; + +fi + +LN_HTTPD_SITES_ENABLED=0 if test x$HTTPD_CONF = xno; then if test -d /etc/httpd/conf.d; then HTTPD_CONF="/etc/httpd/conf.d" elif test -d /etc/apache2/conf.d; then HTTPD_CONF="/etc/apache2/conf.d" + elif test -d /etc/apache2/sites-available; then + HTTPD_CONF="/etc/apache2/sites-available" + if test -d /etc/apache2/sites-enabled; then + LN_HTTPD_SITES_ENABLED=1 + fi + elif test -d /etc/apache2/sites-enabled; then + HTTPD_CONF="/etc/apache2/sites-enabled" elif test -d /etc/apache/conf.d; then HTTPD_CONF="/etc/apache/conf.d" else @@ -5767,15 +4888,17 @@ if test x$HTTPD_CONF = xno; then fi + CHECKRESULTDIR=no -# Check whether --with-checkresult-dir or --without-checkresult-dir was given. -if test "${with_checkresult_dir+set}" = set; then - withval="$with_checkresult_dir" - CHECKRESULTDIR=$withval +# Check whether --with-checkresult-dir was given. +if test "${with_checkresult_dir+set}" = set; then : + withval=$with_checkresult_dir; CHECKRESULTDIR=$withval else CHECKRESULTDIR=no -fi; + +fi + if test x$CHECKRESULTDIR = xno; then CHECKRESULTDIR="$localstatedir/spool/checkresults" fi @@ -5783,13 +4906,14 @@ fi TMPDIR=no -# Check whether --with-temp-dir or --without-temp-dir was given. -if test "${with_temp_dir+set}" = set; then - withval="$with_temp_dir" - TMPDIR=$withval +# Check whether --with-temp-dir was given. +if test "${with_temp_dir+set}" = set; then : + withval=$with_temp_dir; TMPDIR=$withval else TMPDIR=no -fi; + +fi + if test x$TMPDIR = xno; then TMPDIR="/tmp" fi @@ -5809,161 +4933,188 @@ elif test -d /sbin/init.d; then fi -# Check whether --with-init_dir or --without-init_dir was given. -if test "${with_init_dir+set}" = set; then - withval="$with_init_dir" - init_dir=$withval -fi; +# Check whether --with-init_dir was given. +if test "${with_init_dir+set}" = set; then : + withval=$with_init_dir; init_dir=$withval + +fi -# Check whether --with-lockfile or --without-lockfile was given. -if test "${with_lockfile+set}" = set; then - withval="$with_lockfile" - lockfile=$withval + +# Check whether --with-lockfile was given. +if test "${with_lockfile+set}" = set; then : + withval=$with_lockfile; lockfile=$withval else lockfile=$localstatedir/nagios.lock -fi; + +fi -XSDTYPE=default -XCDTYPE=default -XRDTYPE=default -XODTYPE=template -XPDTYPE=default -XDDTYPE=default - -XSDCOMMENT= -XCDCOMMENT= -XRDCOMMENT= -XODCOMMENT= -XPDCOMMENT= -XDDCOMMENT= - -USE_MYSQL=no -USE_PGSQL=no -cat >>confdefs.h <<_ACEOF -#define USE_XSDDEFAULT +case $host_os in +linux*) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for glibc at least version 2.4" >&5 +$as_echo_n "checking for glibc at least version 2.4... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#if defined(__GLIBC__) && defined(__linux) +#include +# if !__GLIBC_PREREQ(2, 4) +# error GLIBC too old +# endif +#else +# error Not using GLIBC +#endif + _ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + GLIBC_NEWER_2_4=1; { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + GLIBC_NEWER_2_4=0; { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } -XSDC="xsddefault.c" -XSDH="xsddefault.h" -XSDCOMMENT="Default (text file)" -echo "We'll use default routines (in xdata/xsddefault.*) for status data I/O..." +fi +rm -f conftest.err conftest.i conftest.$ac_ext + if test $GLIBC_NEWER_2_4 -eq 1; then + ac_fn_c_check_header_mongrel "$LINENO" "sys/epoll.h" "ac_cv_header_sys_epoll_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_epoll_h" = xyes; then : + +fi + + + fi + ;; +esac +ac_fn_c_check_header_mongrel "$LINENO" "sys/select.h" "ac_cv_header_sys_select_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_select_h" = xyes; then : + +fi +# Check whether --with-iobroker was given. +if test "${with_iobroker+set}" = set; then : + withval=$with_iobroker; IOBROKER_METHOD=$withval +else + IOBROKER_METHOD="none" -cat >>confdefs.h <<_ACEOF -#define USE_XCDDEFAULT -_ACEOF - -XCDC="xcddefault.c" -XCDH="xcddefault.h" -XCDCOMMENT="Default (text file)" -echo "We'll use default routines (in xdata/xcddefault.*) for comment data I/O..." +fi +case $IOBROKER_METHOD in +epoll*) + if test $GLIBC_NEWER_2_4 -eq 1 -a x$ac_cv_header_sys_epoll_h = xyes ; then + $as_echo "#define IOBROKER_USES_EPOLL 1" >>confdefs.h + + else + echo "\"epoll\" is not available as an iobroker method." + echo "Please use one of the other options." + exit 1 + fi + ;; +poll*) + if test x$ac_cv_header_sys_poll_h = xyes -o x$ac_cv_header_poll_h = xyes ; then + $as_echo "#define IOBROKER_USES_POLL 1" >>confdefs.h + + else + echo "\"poll\" is not available as an iobroker method." + echo "Please use one of the other options." + exit 1 + fi + ;; +select*) + if test x$ac_cv_header_sys_select_h = xyes ; then + $as_echo "#define IOBROKER_USES_SELECT 1" >>confdefs.h + + else + echo "\"select\" is not available as an iobroker method." + echo "Please use one of the other options." + exit 1 + fi + ;; +none*) + if test $GLIBC_NEWER_2_4 -eq 1 -a x$ac_cv_header_sys_epoll_h = xyes ; then + $as_echo "#define IOBROKER_USES_EPOLL 1" >>confdefs.h + + IOBROKER_METHOD="epoll" + elif test x$ac_cv_header_sys_poll_h = xyes -o x$ac_cv_header_poll_h = xyes ; then + $as_echo "#define IOBROKER_USES_POLL 1" >>confdefs.h + + IOBROKER_METHOD="poll" + elif test x$ac_cv_header_sys_select_h = xyes ; then + $as_echo "#define IOBROKER_USES_SELECT 1" >>confdefs.h + + IOBROKER_METHOD="select" + else + echo "There are no available options for iobroker polling" + exit 1 + fi + ;; +*) + echo "\"$IOBROKER_METHOD\" is not a valid method for --with-iobroker" + exit 1 + ;; +esac - -cat >>confdefs.h <<_ACEOF -#define USE_XRDDEFAULT -_ACEOF - -XRDC="xrddefault.c" -XRDH="xrddefault.h" -XRDCOMMENT="Default (text file)" -echo "We'll use default routines (in xdata/xrddefault.*) for retention data I/O..." +# Check whether --with-gd-lib was given. +if test "${with_gd_lib+set}" = set; then : + withval=$with_gd_lib; + LDFLAGS="${LDFLAGS} -L${withval}" + LD_RUN_PATH="${withval}${LD_RUN_PATH:+:}${LD_RUN_PATH}" +fi +# Check whether --with-gd-inc was given. +if test "${with_gd_inc+set}" = set; then : + withval=$with_gd_inc; CFLAGS="${CFLAGS} -I${withval}" -cat >>confdefs.h <<_ACEOF -#define USE_XODTEMPLATE -_ACEOF +fi -XODC="xodtemplate.c" -XODH="xodtemplate.h" -XODCOMMENT="Template-based (text file)" -echo "We'll use template-based routines (in xdata/xodtemplate.*) for object data I/O..." - - - - - - -cat >>confdefs.h <<_ACEOF -#define USE_XPDDEFAULT -_ACEOF - -XPDC="xpddefault.c" -XPDH="xpddefault.h" -XPDCOMMENT="Default (external commands)" -echo "We'll use default routines (in xdata/xpddefault.*) for performance data I/O..." - - - - - -cat >>confdefs.h <<_ACEOF -#define USE_XDDDEFAULT -_ACEOF - -XDDC="xdddefault.c" -XDDH="xdddefault.h" -XDDCOMMENT="Default (text file)" -echo "We'll use default routines (in xdata/xdddefault.*) for scheduled downtime data I/O..." - - - - - -# Check whether --with-gd-lib or --without-gd-lib was given. -if test "${with_gd_lib+set}" = set; then - withval="$with_gd_lib" - - LDFLAGS="${LDFLAGS} -L${withval}" - LD_RUN_PATH="${withval}${LD_RUN_PATH:+:}${LD_RUN_PATH}" - -fi; - -# Check whether --with-gd-inc or --without-gd-inc was given. -if test "${with_gd_inc+set}" = set; then - withval="$with_gd_inc" - - CFLAGS="${CFLAGS} -I${withval}" - -fi; TRYGD=yep +COREWINDOW=no +# Check whether --enable-corewindow was given. +if test "${enable_corewindow+set}" = set; then : + enableval=$enable_corewindow; COREWINDOW=yes + +fi + + + TRYSTATUSMAP=yep -# Check whether --enable-statusmap or --disable-statusmap was given. -if test "${enable_statusmap+set}" = set; then - enableval="$enable_statusmap" - TRYSTATUSMAP=nope -fi; +# Check whether --enable-statusmap was given. +if test "${enable_statusmap+set}" = set; then : + enableval=$enable_statusmap; TRYSTATUSMAP=nope + +fi + TRYSTATUSWRL=yep -# Check whether --enable-statuswrl or --disable-statuswrl was given. -if test "${enable_statuswrl+set}" = set; then - enableval="$enable_statuswrl" - TRYSTATUSWRL=nope -fi; +# Check whether --enable-statuswrl was given. +if test "${enable_statuswrl+set}" = set; then : + enableval=$enable_statuswrl; TRYSTATUSWRL=nope + +fi + if test x$TRYSTATUSWRL = xyep; then cat >>confdefs.h <<_ACEOF -#define USE_STATUSWRL +#define USE_STATUSWRL /**/ _ACEOF CGIEXTRAS="$CGIEXTRAS statuswrl.cgi" @@ -5976,83 +5127,51 @@ fi if test x$TRYGD = xyep; then - echo "$as_me:$LINENO: checking for main in -liconv" >&5 -echo $ECHO_N "checking for main in -liconv... $ECHO_C" >&6 -if test "${ac_cv_lib_iconv_main+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -liconv" >&5 +$as_echo_n "checking for main in -liconv... " >&6; } +if ${ac_cv_lib_iconv_main+:} false; then : + $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-liconv $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF +cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { -main (); +return main (); ; return 0; } _ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then +if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_iconv_main=yes else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_iconv_main=no + ac_cv_lib_iconv_main=no fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -echo "$as_me:$LINENO: result: $ac_cv_lib_iconv_main" >&5 -echo "${ECHO_T}$ac_cv_lib_iconv_main" >&6 -if test $ac_cv_lib_iconv_main = yes; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_iconv_main" >&5 +$as_echo "$ac_cv_lib_iconv_main" >&6; } +if test "x$ac_cv_lib_iconv_main" = xyes; then : ICONV=-liconv fi - echo "$as_me:$LINENO: checking for gdImagePng in -lgd (order 1)" >&5 -echo $ECHO_N "checking for gdImagePng in -lgd (order 1)... $ECHO_C" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gdImagePng in -lgd (order 1)" >&5 +$as_echo_n "checking for gdImagePng in -lgd (order 1)... " >&6; } ac_lib_var=`echo gd'_'gdImagePng'_'1 | sed 'y%./+-%__p_%'` - if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then - echo $ECHO_N "(cached) $ECHO_C" >&6 + if eval \${ac_cv_lib_$ac_lib_var+:} false; then : + $as_echo_n "(cached) " >&6 else ac_save_LIBS="$LIBS" LIBS="-lgd -lttf -lpng -ljpeg -lz -lm $LIBS" - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 @@ -6067,68 +5186,40 @@ gdImagePng() return 0; } _ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then +if ac_fn_c_try_link "$LINENO"; then : eval "ac_cv_lib_$ac_lib_var=yes" else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -eval "ac_cv_lib_$ac_lib_var=no" + eval "ac_cv_lib_$ac_lib_var=no" fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext LIBS="$ac_save_LIBS" fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then - echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } GDLIBFOUND=yep GDLIBS="-lgd -lttf -lpng -ljpeg -lz -lm" else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } : fi if test x$GDLIBFOUND = x; then - echo "$as_me:$LINENO: checking for gdImagePng in -lgd (order 2)" >&5 -echo $ECHO_N "checking for gdImagePng in -lgd (order 2)... $ECHO_C" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gdImagePng in -lgd (order 2)" >&5 +$as_echo_n "checking for gdImagePng in -lgd (order 2)... " >&6; } ac_lib_var=`echo gd'_'gdImagePng'_'2 | sed 'y%./+-%__p_%'` - if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then - echo $ECHO_N "(cached) $ECHO_C" >&6 + if eval \${ac_cv_lib_$ac_lib_var+:} false; then : + $as_echo_n "(cached) " >&6 else ac_save_LIBS="$LIBS" LIBS="-lgd $ICONV -lpng -ljpeg -lz -lm $LIBS" - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 @@ -6143,69 +5234,41 @@ gdImagePng() return 0; } _ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then +if ac_fn_c_try_link "$LINENO"; then : eval "ac_cv_lib_$ac_lib_var=yes" else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -eval "ac_cv_lib_$ac_lib_var=no" + eval "ac_cv_lib_$ac_lib_var=no" fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext LIBS="$ac_save_LIBS" fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then - echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } GDLIBFOUND=yep GDLIBS="-lgd $ICONV -lpng -ljpeg -lz -lm" else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } : fi fi if test x$GDLIBFOUND = x; then - echo "$as_me:$LINENO: checking for gdImagePng in -lgd (order 3)" >&5 -echo $ECHO_N "checking for gdImagePng in -lgd (order 3)... $ECHO_C" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gdImagePng in -lgd (order 3)" >&5 +$as_echo_n "checking for gdImagePng in -lgd (order 3)... " >&6; } ac_lib_var=`echo gd'_'gdImagePng'_'3 | sed 'y%./+-%__p_%'` - if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then - echo $ECHO_N "(cached) $ECHO_C" >&6 + if eval \${ac_cv_lib_$ac_lib_var+:} false; then : + $as_echo_n "(cached) " >&6 else ac_save_LIBS="$LIBS" LIBS="-lgd $ICONV -lz -lm -lpng $LIBS" - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 @@ -6220,69 +5283,41 @@ gdImagePng() return 0; } _ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then +if ac_fn_c_try_link "$LINENO"; then : eval "ac_cv_lib_$ac_lib_var=yes" else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -eval "ac_cv_lib_$ac_lib_var=no" + eval "ac_cv_lib_$ac_lib_var=no" fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext LIBS="$ac_save_LIBS" fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then - echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } GDLIBFOUND=yep GDLIBS="-lgd $ICONV -lz -lm -lpng" else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } : fi fi if test x$GDLIBFOUND = x; then - echo "$as_me:$LINENO: checking for gdImagePng in -lgd (order 4)" >&5 -echo $ECHO_N "checking for gdImagePng in -lgd (order 4)... $ECHO_C" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gdImagePng in -lgd (order 4)" >&5 +$as_echo_n "checking for gdImagePng in -lgd (order 4)... " >&6; } ac_lib_var=`echo gd'_'gdImagePng'_'4 | sed 'y%./+-%__p_%'` - if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then - echo $ECHO_N "(cached) $ECHO_C" >&6 + if eval \${ac_cv_lib_$ac_lib_var+:} false; then : + $as_echo_n "(cached) " >&6 else ac_save_LIBS="$LIBS" LIBS="-lgd $ICONV -lpng -lz -lm $LIBS" - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 @@ -6297,50 +5332,26 @@ gdImagePng() return 0; } _ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then +if ac_fn_c_try_link "$LINENO"; then : eval "ac_cv_lib_$ac_lib_var=yes" else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -eval "ac_cv_lib_$ac_lib_var=no" + eval "ac_cv_lib_$ac_lib_var=no" fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext LIBS="$ac_save_LIBS" fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then - echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } GDLIBFOUND=yep GDLIBS="-lgd $ICONV -lpng -lz -lm" else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } : fi @@ -6385,79 +5396,49 @@ echo "${ECHO_T}no" >&6 if test x$TRYSTATUSMAP = xyep; then cat >>confdefs.h <<_ACEOF -#define USE_STATUSMAP +#define USE_STATUSMAP /**/ _ACEOF CGIEXTRAS="$CGIEXTRAS statusmap.cgi" - echo "$as_me:$LINENO: checking for gdImageCreateTrueColor in -lgd" >&5 -echo $ECHO_N "checking for gdImageCreateTrueColor in -lgd... $ECHO_C" >&6 -if test "${ac_cv_lib_gd_gdImageCreateTrueColor+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gdImageCreateTrueColor in -lgd" >&5 +$as_echo_n "checking for gdImageCreateTrueColor in -lgd... " >&6; } +if ${ac_cv_lib_gd_gdImageCreateTrueColor+:} false; then : + $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lgd $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF +cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -/* Override any gcc2 internal prototype to avoid an error. */ +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ char gdImageCreateTrueColor (); int main () { -gdImageCreateTrueColor (); +return gdImageCreateTrueColor (); ; return 0; } _ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then +if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_gd_gdImageCreateTrueColor=yes else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_gd_gdImageCreateTrueColor=no + ac_cv_lib_gd_gdImageCreateTrueColor=no fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -echo "$as_me:$LINENO: result: $ac_cv_lib_gd_gdImageCreateTrueColor" >&5 -echo "${ECHO_T}$ac_cv_lib_gd_gdImageCreateTrueColor" >&6 -if test $ac_cv_lib_gd_gdImageCreateTrueColor = yes; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gd_gdImageCreateTrueColor" >&5 +$as_echo "$ac_cv_lib_gd_gdImageCreateTrueColor" >&6; } +if test "x$ac_cv_lib_gd_gdImageCreateTrueColor" = xyes; then : -cat >>confdefs.h <<\_ACEOF -#define HAVE_GDIMAGECREATETRUECOLOR 1 -_ACEOF +$as_echo "#define HAVE_GDIMAGECREATETRUECOLOR 1" >>confdefs.h fi @@ -6465,14 +5446,14 @@ fi cat >>confdefs.h <<_ACEOF -#define USE_TRENDS +#define USE_TRENDS /**/ _ACEOF CGIEXTRAS="$CGIEXTRAS trends.cgi" cat >>confdefs.h <<_ACEOF -#define USE_HISTOGRAM +#define USE_HISTOGRAM /**/ _ACEOF CGIEXTRAS="$CGIEXTRAS histogram.cgi" @@ -6480,263 +5461,101 @@ _ACEOF fi -# Check whether --with-cgiurl or --without-cgiurl was given. -if test "${with_cgiurl+set}" = set; then - withval="$with_cgiurl" - cgiurl=$withval +# Check whether --with-cgiurl was given. +if test "${with_cgiurl+set}" = set; then : + withval=$with_cgiurl; cgiurl=$withval else cgiurl=/nagios/cgi-bin -fi; -# Check whether --with-htmurl or --without-htmurl was given. -if test "${with_htmurl+set}" = set; then - withval="$with_htmurl" - htmurl=$withval +fi + + +# Check whether --with-htmurl was given. +if test "${with_htmurl+set}" = set; then : + withval=$with_htmurl; htmurl=$withval else htmurl=/nagios -fi; + +fi + USE_NANOSLEEP=yes -# Check whether --enable-nanosleep or --disable-nanosleep was given. -if test "${enable_nanosleep+set}" = set; then - enableval="$enable_nanosleep" - USE_NANOSLEEP=$enableval +# Check whether --enable-nanosleep was given. +if test "${enable_nanosleep+set}" = set; then : + enableval=$enable_nanosleep; USE_NANOSLEEP=$enableval else USE_NANOSLEEP=yes -fi; + +fi + if test x$USE_NANOSLEEP = xyes; then cat >>confdefs.h <<_ACEOF -#define USE_NANOSLEEP +#define USE_NANOSLEEP /**/ _ACEOF fi USE_EVENTBROKER=yes -# Check whether --enable-event-broker or --disable-event-broker was given. -if test "${enable_event_broker+set}" = set; then - enableval="$enable_event_broker" - USE_EVENTBROKER=$enableval +# Check whether --enable-event-broker was given. +if test "${enable_event_broker+set}" = set; then : + enableval=$enable_event_broker; USE_EVENTBROKER=$enableval else USE_EVENTBROKER=yes -fi; + +fi + BROKER_LDFLAGS="" BROKERLIBS=""; some_dl_found="no"; if test x$USE_EVENTBROKER = xyes; then - if test "${ac_cv_header_ltdl_h+set}" = set; then - echo "$as_me:$LINENO: checking for ltdl.h" >&5 -echo $ECHO_N "checking for ltdl.h... $ECHO_C" >&6 -if test "${ac_cv_header_ltdl_h+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -fi -echo "$as_me:$LINENO: result: $ac_cv_header_ltdl_h" >&5 -echo "${ECHO_T}$ac_cv_header_ltdl_h" >&6 -else - # Is the header compilable? -echo "$as_me:$LINENO: checking ltdl.h usability" >&5 -echo $ECHO_N "checking ltdl.h usability... $ECHO_C" >&6 -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -#include -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_header_compiler=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 + ac_fn_c_check_header_mongrel "$LINENO" "ltdl.h" "ac_cv_header_ltdl_h" "$ac_includes_default" +if test "x$ac_cv_header_ltdl_h" = xyes; then : -ac_header_compiler=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 -echo "${ECHO_T}$ac_header_compiler" >&6 - -# Is the header present? -echo "$as_me:$LINENO: checking ltdl.h presence" >&5 -echo $ECHO_N "checking ltdl.h presence... $ECHO_C" >&6 -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -_ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_c_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_c_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then - ac_header_preproc=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_header_preproc=no -fi -rm -f conftest.err conftest.$ac_ext -echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 -echo "${ECHO_T}$ac_header_preproc" >&6 - -# So? What about this header? -case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in - yes:no: ) - { echo "$as_me:$LINENO: WARNING: ltdl.h: accepted by the compiler, rejected by the preprocessor!" >&5 -echo "$as_me: WARNING: ltdl.h: accepted by the compiler, rejected by the preprocessor!" >&2;} - { echo "$as_me:$LINENO: WARNING: ltdl.h: proceeding with the compiler's result" >&5 -echo "$as_me: WARNING: ltdl.h: proceeding with the compiler's result" >&2;} - ac_header_preproc=yes - ;; - no:yes:* ) - { echo "$as_me:$LINENO: WARNING: ltdl.h: present but cannot be compiled" >&5 -echo "$as_me: WARNING: ltdl.h: present but cannot be compiled" >&2;} - { echo "$as_me:$LINENO: WARNING: ltdl.h: check for missing prerequisite headers?" >&5 -echo "$as_me: WARNING: ltdl.h: check for missing prerequisite headers?" >&2;} - { echo "$as_me:$LINENO: WARNING: ltdl.h: see the Autoconf documentation" >&5 -echo "$as_me: WARNING: ltdl.h: see the Autoconf documentation" >&2;} - { echo "$as_me:$LINENO: WARNING: ltdl.h: section \"Present But Cannot Be Compiled\"" >&5 -echo "$as_me: WARNING: ltdl.h: section \"Present But Cannot Be Compiled\"" >&2;} - { echo "$as_me:$LINENO: WARNING: ltdl.h: proceeding with the preprocessor's result" >&5 -echo "$as_me: WARNING: ltdl.h: proceeding with the preprocessor's result" >&2;} - { echo "$as_me:$LINENO: WARNING: ltdl.h: in the future, the compiler will take precedence" >&5 -echo "$as_me: WARNING: ltdl.h: in the future, the compiler will take precedence" >&2;} - ( - cat <<\_ASBOX -## ------------------------------------------ ## -## Report this to the AC_PACKAGE_NAME lists. ## -## ------------------------------------------ ## -_ASBOX - ) | - sed "s/^/$as_me: WARNING: /" >&2 - ;; -esac -echo "$as_me:$LINENO: checking for ltdl.h" >&5 -echo $ECHO_N "checking for ltdl.h... $ECHO_C" >&6 -if test "${ac_cv_header_ltdl_h+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_cv_header_ltdl_h=$ac_header_preproc -fi -echo "$as_me:$LINENO: result: $ac_cv_header_ltdl_h" >&5 -echo "${ECHO_T}$ac_cv_header_ltdl_h" >&6 - -fi -if test $ac_cv_header_ltdl_h = yes; then - - echo "$as_me:$LINENO: checking for lt_dlinit in -lltdl" >&5 -echo $ECHO_N "checking for lt_dlinit in -lltdl... $ECHO_C" >&6 -if test "${ac_cv_lib_ltdl_lt_dlinit+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for lt_dlinit in -lltdl" >&5 +$as_echo_n "checking for lt_dlinit in -lltdl... " >&6; } +if ${ac_cv_lib_ltdl_lt_dlinit+:} false; then : + $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lltdl $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF +cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -/* Override any gcc2 internal prototype to avoid an error. */ +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ char lt_dlinit (); int main () { -lt_dlinit (); +return lt_dlinit (); ; return 0; } _ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then +if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_ltdl_lt_dlinit=yes else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_ltdl_lt_dlinit=no + ac_cv_lib_ltdl_lt_dlinit=no fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -echo "$as_me:$LINENO: result: $ac_cv_lib_ltdl_lt_dlinit" >&5 -echo "${ECHO_T}$ac_cv_lib_ltdl_lt_dlinit" >&6 -if test $ac_cv_lib_ltdl_lt_dlinit = yes; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ltdl_lt_dlinit" >&5 +$as_echo "$ac_cv_lib_ltdl_lt_dlinit" >&6; } +if test "x$ac_cv_lib_ltdl_lt_dlinit" = xyes; then : -cat >>confdefs.h <<\_ACEOF -#define HAVE_LTDL_H -_ACEOF +$as_echo "#define HAVE_LTDL_H /**/" >>confdefs.h some_dl_found="yes" BROKERLIBS="$BROKERLIBS -lltdl" @@ -6748,215 +5567,49 @@ fi if test "x$some_dl_found" != xyes; then - if test "${ac_cv_header_dlfcn_h+set}" = set; then - echo "$as_me:$LINENO: checking for dlfcn.h" >&5 -echo $ECHO_N "checking for dlfcn.h... $ECHO_C" >&6 -if test "${ac_cv_header_dlfcn_h+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -fi -echo "$as_me:$LINENO: result: $ac_cv_header_dlfcn_h" >&5 -echo "${ECHO_T}$ac_cv_header_dlfcn_h" >&6 -else - # Is the header compilable? -echo "$as_me:$LINENO: checking dlfcn.h usability" >&5 -echo $ECHO_N "checking dlfcn.h usability... $ECHO_C" >&6 -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -$ac_includes_default -#include -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - ac_header_compiler=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 + ac_fn_c_check_header_mongrel "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default" +if test "x$ac_cv_header_dlfcn_h" = xyes; then : -ac_header_compiler=no -fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext -echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 -echo "${ECHO_T}$ac_header_compiler" >&6 - -# Is the header present? -echo "$as_me:$LINENO: checking dlfcn.h presence" >&5 -echo $ECHO_N "checking dlfcn.h presence... $ECHO_C" >&6 -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -_ACEOF -if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 - (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_c_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_c_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then - ac_header_preproc=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_header_preproc=no -fi -rm -f conftest.err conftest.$ac_ext -echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 -echo "${ECHO_T}$ac_header_preproc" >&6 - -# So? What about this header? -case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in - yes:no: ) - { echo "$as_me:$LINENO: WARNING: dlfcn.h: accepted by the compiler, rejected by the preprocessor!" >&5 -echo "$as_me: WARNING: dlfcn.h: accepted by the compiler, rejected by the preprocessor!" >&2;} - { echo "$as_me:$LINENO: WARNING: dlfcn.h: proceeding with the compiler's result" >&5 -echo "$as_me: WARNING: dlfcn.h: proceeding with the compiler's result" >&2;} - ac_header_preproc=yes - ;; - no:yes:* ) - { echo "$as_me:$LINENO: WARNING: dlfcn.h: present but cannot be compiled" >&5 -echo "$as_me: WARNING: dlfcn.h: present but cannot be compiled" >&2;} - { echo "$as_me:$LINENO: WARNING: dlfcn.h: check for missing prerequisite headers?" >&5 -echo "$as_me: WARNING: dlfcn.h: check for missing prerequisite headers?" >&2;} - { echo "$as_me:$LINENO: WARNING: dlfcn.h: see the Autoconf documentation" >&5 -echo "$as_me: WARNING: dlfcn.h: see the Autoconf documentation" >&2;} - { echo "$as_me:$LINENO: WARNING: dlfcn.h: section \"Present But Cannot Be Compiled\"" >&5 -echo "$as_me: WARNING: dlfcn.h: section \"Present But Cannot Be Compiled\"" >&2;} - { echo "$as_me:$LINENO: WARNING: dlfcn.h: proceeding with the preprocessor's result" >&5 -echo "$as_me: WARNING: dlfcn.h: proceeding with the preprocessor's result" >&2;} - { echo "$as_me:$LINENO: WARNING: dlfcn.h: in the future, the compiler will take precedence" >&5 -echo "$as_me: WARNING: dlfcn.h: in the future, the compiler will take precedence" >&2;} - ( - cat <<\_ASBOX -## ------------------------------------------ ## -## Report this to the AC_PACKAGE_NAME lists. ## -## ------------------------------------------ ## -_ASBOX - ) | - sed "s/^/$as_me: WARNING: /" >&2 - ;; -esac -echo "$as_me:$LINENO: checking for dlfcn.h" >&5 -echo $ECHO_N "checking for dlfcn.h... $ECHO_C" >&6 -if test "${ac_cv_header_dlfcn_h+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - ac_cv_header_dlfcn_h=$ac_header_preproc -fi -echo "$as_me:$LINENO: result: $ac_cv_header_dlfcn_h" >&5 -echo "${ECHO_T}$ac_cv_header_dlfcn_h" >&6 - -fi -if test $ac_cv_header_dlfcn_h = yes; then - - echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5 -echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6 -if test "${ac_cv_lib_dl_dlopen+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if ${ac_cv_lib_dl_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF +cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -/* Override any gcc2 internal prototype to avoid an error. */ +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif -/* We use char because int might match the return type of a gcc2 - builtin and then its argument prototype would still apply. */ char dlopen (); int main () { -dlopen (); +return dlopen (); ; return 0; } _ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then +if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -ac_cv_lib_dl_dlopen=no + ac_cv_lib_dl_dlopen=no fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5 -echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6 -if test $ac_cv_lib_dl_dlopen = yes; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = xyes; then : -cat >>confdefs.h <<\_ACEOF -#define HAVE_DLFCN_H -_ACEOF +$as_echo "#define HAVE_DLFCN_H /**/" >>confdefs.h some_dl_found="yes" BROKERLIBS="$BROKERLIBS -ldl" @@ -6979,8 +5632,8 @@ fi # AIX 4.x (perhaps only for x>=2) wants -Wl,-bexpall,-brtl and doesn't # reliably return an error for others, thus we separate it out. # Otherwise we assume that if the linker accepts the flag, it is needed. - echo "$as_me:$LINENO: checking for extra flags needed to export symbols" >&5 -echo $ECHO_N "checking for extra flags needed to export symbols... $ECHO_C" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for extra flags needed to export symbols" >&5 +$as_echo_n "checking for extra flags needed to export symbols... " >&6; } case $host_os in aix4*|aix5*) BROKER_LDFLAGS="$BROKER_LDFLAGS -Wl,-bexpall,-brtl" @@ -6991,11 +5644,7 @@ echo $ECHO_N "checking for extra flags needed to export symbols... $ECHO_C" >&6 *) save_ldflags="$LDFLAGS" LDFLAGS=-Wl,-export-dynamic - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int @@ -7006,40 +5655,12 @@ main () return 0; } _ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then +if ac_fn_c_try_link "$LINENO"; then : BROKER_LDFLAGS="$BROKER_LDFLAGS -Wl,-export-dynamic" else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - LDFLAGS=-Wl,-Bexport - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int @@ -7050,55 +5671,32 @@ main () return 0; } _ACEOF -rm -f conftest.$ac_objext conftest$ac_exeext -if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 - (eval $ac_link) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest$ac_exeext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then +if ac_fn_c_try_link "$LINENO"; then : BROKER_LDFLAGS="$BROKER_LDFLAGS -Wl,-Bexport" else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -echo "$as_me:$LINENO: result: none" >&5 -echo "${ECHO_T}none" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 +$as_echo "none" >&6; } fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext fi -rm -f conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext LDFLAGS="$save_ldflags" ;; esac - test "x$BROKER_LDFLAGS" != x && echo "$as_me:$LINENO: result: $BROKER_LDFLAGS" >&5 -echo "${ECHO_T}$BROKER_LDFLAGS" >&6 + test "x$BROKER_LDFLAGS" != x && { $as_echo "$as_me:${as_lineno-$LINENO}: result: $BROKER_LDFLAGS" >&5 +$as_echo "$BROKER_LDFLAGS" >&6; } - echo "$as_me:$LINENO: checking for linker flags for loadable modules" >&5 -echo $ECHO_N "checking for linker flags for loadable modules... $ECHO_C" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for linker flags for loadable modules" >&5 +$as_echo_n "checking for linker flags for loadable modules... " >&6; } case $host_os in solaris2*|sysv4*) MOD_LDFLAGS="-G" + MOD_CFLAGS="-fPIC" ;; aix4*|aix5*) #MOD_LDFLAGS="-G -bnoentry -bexpall" @@ -7119,7 +5717,7 @@ echo $ECHO_N "checking for linker flags for loadable modules... $ECHO_C" >&6 MOD_LDFLAGS="-shared" MOD_CFLAGS="-fPIC" ;; - freebsd*) + *bsd*) MOD_LDFLAGS="-shared" MOD_CFLAGS="-fPIC" ;; @@ -7128,15 +5726,19 @@ echo $ECHO_N "checking for linker flags for loadable modules... $ECHO_C" >&6 MOD_LDFLAGS="-shared" ;; esac - echo "$as_me:$LINENO: result: $MOD_LDFLAGS" >&5 -echo "${ECHO_T}$MOD_LDFLAGS" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MOD_LDFLAGS" >&5 +$as_echo "$MOD_LDFLAGS" >&6; } + WORKER_CFLAGS="-I ../../include -I ../.." + WORKER_LDFLAGS="-L ../../lib -l nagios" + + cat >>confdefs.h <<_ACEOF -#define USE_EVENT_BROKER +#define USE_EVENT_BROKER /**/ _ACEOF BROKER_O="broker.o nebmods.o" @@ -7146,98 +5748,15 @@ _ACEOF fi -USEPERL=no; -INSTALLPERLSTUFF=no; -# Check whether --enable-embedded-perl or --disable-embedded-perl was given. -if test "${enable_embedded_perl+set}" = set; then - enableval="$enable_embedded_perl" - - USEPERL=$enableval - - -else - USEPERL=no -fi; - -PERLCACHE=yes; - -# Check whether --with-perlcache or --without-perlcache was given. -if test "${with_perlcache+set}" = set; then - withval="$with_perlcache" - - PERLCACHE=$withval - - -else - - -cat >>confdefs.h <<\_ACEOF -#define DO_CLEAN "1" -_ACEOF - - PERLCACHE=yes; - -fi; - -if test x$USEPERL = xyes; then - - -cat >>confdefs.h <<_ACEOF -#define EMBEDDEDPERL -_ACEOF - - PERLLIBS="`perl -MExtUtils::Embed -e ldopts`" - PERLDIR="`perl -MConfig -e 'print $Config{installsitearch}'`" - CFLAGS="${CFLAGS} `perl -MExtUtils::Embed -e ccopts`" - USEPERL=yes - INSTALLPERLSTUFF=yes; - PERLXSI_O=perlxsi.o - OBJS="${OBJS} ${PERLXSI_O}" - echo "creating base/perlxsi.c" - perl -MExtUtils::Embed -e xsinit -- -o base/perlxsi.c - - echo "Embedded Perl interpreter will be compiled in..." - - if test x$PERLCACHE = xyes; then - -cat >>confdefs.h <<\_ACEOF -#define DO_CLEAN "0" -_ACEOF - - PERLCACHE=yes; - echo "Internally compiled Perl scripts will be cached..." - else - -cat >>confdefs.h <<\_ACEOF -#define DO_CLEAN "1" -_ACEOF - - echo "Internally compiled Perl scripts will NOT be cached..." - fi -fi - -if test x$USEPERL = xyes; then - if (perl -e 'use Config;exit -1 unless ($Config{'usethreads'});'); then - echo "Using threaded perl" - -cat >>confdefs.h <<_ACEOF -#define THREADEDPERL -_ACEOF - - fi -fi - - nagios_name=nagios nagiostats_name=nagiostats cygwin=no -# Check whether --enable-cygwin or --disable-cygwin was given. -if test "${enable_cygwin+set}" = set; then - enableval="$enable_cygwin" +# Check whether --enable-cygwin was given. +if test "${enable_cygwin+set}" = set; then : + enableval=$enable_cygwin; cygwin=$enableval - cygwin=$enableval +fi -fi; if test x$cygwin = xyes; then CFLAGS="${CFLAGS} -DCYGWIN" nagios_name=nagios.exe; @@ -7250,10 +5769,10 @@ fi # Extract the first word of "traceroute", so it can be a program name with args. set dummy traceroute; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_path_PATH_TO_TRACEROUTE+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_PATH_TO_TRACEROUTE+:} false; then : + $as_echo_n "(cached) " >&6 else case $PATH_TO_TRACEROUTE in [\\/]* | ?:[\\/]*) @@ -7265,29 +5784,30 @@ for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_PATH_TO_TRACEROUTE="$as_dir/$ac_word$ac_exec_ext" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done -done + done +IFS=$as_save_IFS ;; esac fi PATH_TO_TRACEROUTE=$ac_cv_path_PATH_TO_TRACEROUTE - if test -n "$PATH_TO_TRACEROUTE"; then - echo "$as_me:$LINENO: result: $PATH_TO_TRACEROUTE" >&5 -echo "${ECHO_T}$PATH_TO_TRACEROUTE" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PATH_TO_TRACEROUTE" >&5 +$as_echo "$PATH_TO_TRACEROUTE" >&6; } else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi + cat >>confdefs.h <<_ACEOF #define TRACEROUTE_COMMAND "$PATH_TO_TRACEROUTE" _ACEOF @@ -7300,13 +5820,9 @@ PACKDIR=`pwd`/pkg -echo "$as_me:$LINENO: checking for type va_list" >&5 -echo $ECHO_N "checking for type va_list... $ECHO_C" >&6 -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for type va_list" >&5 +$as_echo_n "checking for type va_list... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ #include @@ -7325,50 +5841,24 @@ va_list args; return 0; } _ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -z "$ac_c_werror_flag" - || test ! -s conftest.err' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6 +if ac_fn_c_try_compile "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -cat >>confdefs.h <<\_ACEOF -#define NEED_VA_LIST -_ACEOF - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 +$as_echo "#define NEED_VA_LIST /**/" >>confdefs.h + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi -rm -f conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -# Check whether --enable-libtap or --disable-libtap was given. -if test "${enable_libtap+set}" = set; then - enableval="$enable_libtap" - enable_libtap=$enableval +# Check whether --enable-libtap was given. +if test "${enable_libtap+set}" = set; then : + enableval=$enable_libtap; enable_libtap=$enableval else enable_libtap=no -fi; +fi + #Disabled for moment #AM_CONDITIONAL([USE_LIBTAP_LOCAL],[test "$enable_libtap" = "yes"]) @@ -7400,16 +5890,12 @@ fi - - - - # Extract the first word of "perl", so it can be a program name with args. set dummy perl; ac_word=$2 -echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 -if test "${ac_cv_path_PERL+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_PERL+:} false; then : + $as_echo_n "(cached) " >&6 else case $PERL in [\\/]* | ?:[\\/]*) @@ -7421,62 +5907,98 @@ for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_PERL="$as_dir/$ac_word$ac_exec_ext" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done -done + done +IFS=$as_save_IFS ;; esac fi PERL=$ac_cv_path_PERL - if test -n "$PERL"; then - echo "$as_me:$LINENO: result: $PERL" >&5 -echo "${ECHO_T}$PERL" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PERL" >&5 +$as_echo "$PERL" >&6; } else - echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi - ac_config_files="$ac_config_files Makefile subst pkginfo base/Makefile common/Makefile contrib/Makefile cgi/Makefile html/Makefile module/Makefile xdata/Makefile daemon-init t/Makefile t-tap/Makefile" +if test -z "$PERL"; then + as_fn_error $? "Cannot continue without perl!" "$LINENO" 5 +fi + +# Extract the first word of "unzip", so it can be a program name with args. +set dummy unzip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_UNZIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $UNZIP in + [\\/]* | ?:[\\/]*) + ac_cv_path_UNZIP="$UNZIP" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_UNZIP="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +UNZIP=$ac_cv_path_UNZIP +if test -n "$UNZIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $UNZIP" >&5 +$as_echo "$UNZIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +if test -z "$UNZIP"; then + as_fn_error $? "Cannot continue without unzip!" "$LINENO" 5 +fi + +ac_config_files="$ac_config_files Makefile lib/Makefile subst pkginfo base/Makefile common/Makefile contrib/Makefile cgi/Makefile html/Makefile module/Makefile worker/Makefile worker/ping/Makefile xdata/Makefile daemon-init t/Makefile t-tap/Makefile" + test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' -# VPATH may cause trouble with some makes, so we remove $(srcdir), -# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and -# trailing colons and then remove the whole line if VPATH becomes empty -# (actually we leave an empty line to preserve line numbers). -if test "x$srcdir" = x.; then - ac_vpsub='/^[ ]*VPATH[ ]*=/{ -s/:*\$(srcdir):*/:/; -s/:*\${srcdir}:*/:/; -s/:*@srcdir@:*/:/; -s/^\([^=]*=[ ]*\):*/\1/; -s/:*$//; -s/^[^=]*=[ ]*$//; -}' -fi - DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= +U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. - ac_i=`echo "$ac_i" | - sed 's/\$U\././;s/\.o$//;s/\.obj$//'` - # 2. Add them. - ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext" - ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo' + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" + as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs @@ -7484,12 +6006,14 @@ LTLIBOBJS=$ac_ltlibobjs -: ${CONFIG_STATUS=./config.status} +: "${CONFIG_STATUS=./config.status}" +ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" -{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 -echo "$as_me: creating $CONFIG_STATUS" >&6;} -cat >$CONFIG_STATUS <<_ACEOF +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +as_write_fail=0 +cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. @@ -7499,81 +6023,253 @@ cat >$CONFIG_STATUS <<_ACEOF debug=false ac_cs_recheck=false ac_cs_silent=false + SHELL=\${CONFIG_SHELL-$SHELL} -_ACEOF +export SHELL +_ASEOF +cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## -cat >>$CONFIG_STATUS <<\_ACEOF -## --------------------- ## -## M4sh Initialization. ## -## --------------------- ## - -# Be Bourne compatible -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: - # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' -elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then - set -o posix -fi -DUALCASE=1; export DUALCASE # for MKS sh - -# Support unset when possible. -if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then - as_unset=unset + setopt NO_GLOB_SUBST else - as_unset=false + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac fi -# Work around bugs in pre-3.0 UWIN ksh. -$as_unset ENV MAIL MAILPATH +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. -for as_var in \ - LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ - LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ - LC_TELEPHONE LC_TIME -do - if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then - eval $as_var=C; export $as_var - else - $as_unset $as_var - fi -done +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE -# Required to use basename. -if expr a : '\(a\)' >/dev/null 2>&1; then +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi -if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi -# Name of the executable. -as_me=`$as_basename "$0" || +as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ - X"$0" : 'X\(/\)$' \| \ - . : '\(.\)' 2>/dev/null || -echo X/"$0" | - sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } - /^X\/\(\/\/\)$/{ s//\1/; q; } - /^X\/\(\/\).*/{ s//\1/; q; } - s/.*/./; q'` + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` - -# PATH needs CR, and LINENO needs CR and PATH. # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' @@ -7581,148 +6277,111 @@ as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits -# The user is always right. -if test "${PATH_SEPARATOR+set}" != set; then - echo "#! /bin/sh" >conf$$.sh - echo "exit 0" >>conf$$.sh - chmod +x conf$$.sh - if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then - PATH_SEPARATOR=';' - else - PATH_SEPARATOR=: - fi - rm -f conf$$.sh -fi - - - as_lineno_1=$LINENO - as_lineno_2=$LINENO - as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` - test "x$as_lineno_1" != "x$as_lineno_2" && - test "x$as_lineno_3" = "x$as_lineno_2" || { - # Find who we are. Look in the path if we contain no path at all - # relative or not. - case $0 in - *[\\/]* ) as_myself=$0 ;; - *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break -done - - ;; - esac - # We did not find ourselves, most probably we were run as `sh COMMAND' - # in which case we are not to be found in the path. - if test "x$as_myself" = x; then - as_myself=$0 - fi - if test ! -f "$as_myself"; then - { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5 -echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;} - { (exit 1); exit 1; }; } - fi - case $CONFIG_SHELL in - '') - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for as_base in sh bash ksh sh5; do - case $as_dir in - /*) - if ("$as_dir/$as_base" -c ' - as_lineno_1=$LINENO - as_lineno_2=$LINENO - as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` - test "x$as_lineno_1" != "x$as_lineno_2" && - test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then - $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } - $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } - CONFIG_SHELL=$as_dir/$as_base - export CONFIG_SHELL - exec "$CONFIG_SHELL" "$0" ${1+"$@"} - fi;; - esac - done -done -;; - esac - - # Create $as_me.lineno as a copy of $as_myself, but with $LINENO - # uniformly replaced by the line number. The first 'sed' inserts a - # line-number line before each line; the second 'sed' does the real - # work. The second script uses 'N' to pair each line-number line - # with the numbered line, and appends trailing '-' during - # substitution so that $LINENO is not a special case at line end. - # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the - # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) - sed '=' <$as_myself | - sed ' - N - s,$,-, - : loop - s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, - t loop - s,-$,, - s,^['$as_cr_digits']*\n,, - ' >$as_me.lineno && - chmod +x $as_me.lineno || - { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5 -echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;} - { (exit 1); exit 1; }; } - - # Don't try to exec as it changes $[0], causing all sort of problems - # (the dirname of $[0] is not the place where we might find the - # original and so on. Autoconf is especially sensible to this). - . ./$as_me.lineno - # Exit status is that of the last command. - exit -} - - -case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in - *c*,-n*) ECHO_N= ECHO_C=' -' ECHO_T=' ' ;; - *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; - *) ECHO_N= ECHO_C='\c' ECHO_T= ;; +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; esac -if expr a : '\(a\)' >/dev/null 2>&1; then - as_expr=expr -else - as_expr=false -fi - rm -f conf$$ conf$$.exe conf$$.file -echo >conf$$.file -if ln -s conf$$.file conf$$ 2>/dev/null; then - # We could just check for DJGPP; but this test a) works b) is more generic - # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). - if test -f conf$$.exe; then - # Don't use ln at all; we don't have any links - as_ln_s='cp -p' - else +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' fi -elif ln conf$$.file conf$$ 2>/dev/null; then - as_ln_s=ln else - as_ln_s='cp -p' + as_ln_s='cp -pR' fi -rm -f conf$$ conf$$.exe conf$$.file +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then - as_mkdir_p=: + as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi -as_executable_p="test -f" + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +as_test_x='test -x' +as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" @@ -7731,31 +6390,20 @@ as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" -# IFS -# We need space, tab and new line, in precisely that order. -as_nl=' -' -IFS=" $as_nl" - -# CDPATH. -$as_unset CDPATH - exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 -# Open the log real soon, to keep \$[0] and so on meaningful, and to +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their -# values after options handling. Logging --version etc. is OK. -exec 5>>config.log -{ - echo - sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX -## Running $as_me. ## -_ASBOX -} >&5 -cat >&5 <<_CSEOF - +# values after options handling. +ac_log=" This file was extended by $as_me, which was -generated by GNU Autoconf 2.59. Invocation command line was +generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS @@ -7763,45 +6411,46 @@ generated by GNU Autoconf 2.59. Invocation command line was CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ -_CSEOF -echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5 -echo >&5 +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + _ACEOF +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + +case $ac_config_headers in *" +"*) set x $ac_config_headers; shift; ac_config_headers=$*;; +esac + + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. -if test -n "$ac_config_files"; then - echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS -fi +config_files="$ac_config_files" +config_headers="$ac_config_headers" -if test -n "$ac_config_headers"; then - echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS -fi - -if test -n "$ac_config_links"; then - echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS -fi - -if test -n "$ac_config_commands"; then - echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS -fi - -cat >>$CONFIG_STATUS <<\_ACEOF +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ -\`$as_me' instantiates files from templates according to the -current configuration. +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. -Usage: $0 [OPTIONS] [FILE]... +Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit - -V, --version print version number, then exit - -q, --quiet do not print progress messages + -V, --version print version number and configuration settings, then exit + --config print configuration, then exit + -q, --quiet, --silent + do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions - --file=FILE[:TEMPLATE] - instantiate the configuration file FILE - --header=FILE[:TEMPLATE] - instantiate the configuration header FILE + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE Configuration files: $config_files @@ -7809,84 +6458,90 @@ $config_files Configuration headers: $config_headers -Report bugs to ." -_ACEOF +Report bugs to the package provider." -cat >>$CONFIG_STATUS <<_ACEOF +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ config.status -configured by $0, generated by GNU Autoconf 2.59, - with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\" +configured by $0, generated by GNU Autoconf 2.69, + with options \\"\$ac_cs_config\\" -Copyright (C) 2003 Free Software Foundation, Inc. +Copyright (C) 2012 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." -srcdir=$srcdir -INSTALL="$INSTALL" + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +INSTALL='$INSTALL' +test -n "\$AWK" || AWK=awk _ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF -# If no file are specified by the user, then we need to provide default -# value. By we need to know if files were specified by the user. +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in - --*=*) - ac_option=`expr "x$1" : 'x\([^=]*\)='` - ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'` + --*=?*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; - -*) + --*=) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg= + ac_shift=: + ;; + *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; - *) # This is not an option, so the user has probably given explicit - # arguments. - ac_option=$1 - ac_need_defaults=false;; esac case $ac_option in # Handling of the options. -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; - --version | --vers* | -V ) - echo "$ac_cs_version"; exit 0 ;; - --he | --h) - # Conflict between --help and --header - { { echo "$as_me:$LINENO: error: ambiguous option: $1 -Try \`$0 --help' for more information." >&5 -echo "$as_me: error: ambiguous option: $1 -Try \`$0 --help' for more information." >&2;} - { (exit 1); exit 1; }; };; - --help | --hel | -h ) - echo "$ac_cs_usage"; exit 0 ;; - --debug | --d* | -d ) + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + $as_echo "$ac_cs_config"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift - CONFIG_FILES="$CONFIG_FILES $ac_optarg" + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift - CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg" + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append CONFIG_HEADERS " '$ac_optarg'" ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + as_fn_error $? "ambiguous option: \`$1' +Try \`$0 --help' for more information.";; + --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. - -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1 -Try \`$0 --help' for more information." >&5 -echo "$as_me: error: unrecognized option: $1 -Try \`$0 --help' for more information." >&2;} - { (exit 1); exit 1; }; } ;; + -*) as_fn_error $? "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; - *) ac_config_targets="$ac_config_targets $1" ;; + *) as_fn_append ac_config_targets " $1" + ac_need_defaults=false ;; esac shift @@ -7900,44 +6555,63 @@ if $ac_cs_silent; then fi _ACEOF -cat >>$CONFIG_STATUS <<_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then - echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 - exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + shift + \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 + CONFIG_SHELL='$SHELL' + export CONFIG_SHELL + exec "\$@" fi _ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + $as_echo "$ac_log" +} >&5 +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 - - -cat >>$CONFIG_STATUS <<\_ACEOF +# Handling of arguments. for ac_config_target in $ac_config_targets do - case "$ac_config_target" in - # Handling of arguments. - "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;; - "subst" ) CONFIG_FILES="$CONFIG_FILES subst" ;; - "pkginfo" ) CONFIG_FILES="$CONFIG_FILES pkginfo" ;; - "base/Makefile" ) CONFIG_FILES="$CONFIG_FILES base/Makefile" ;; - "common/Makefile" ) CONFIG_FILES="$CONFIG_FILES common/Makefile" ;; - "contrib/Makefile" ) CONFIG_FILES="$CONFIG_FILES contrib/Makefile" ;; - "cgi/Makefile" ) CONFIG_FILES="$CONFIG_FILES cgi/Makefile" ;; - "html/Makefile" ) CONFIG_FILES="$CONFIG_FILES html/Makefile" ;; - "module/Makefile" ) CONFIG_FILES="$CONFIG_FILES module/Makefile" ;; - "xdata/Makefile" ) CONFIG_FILES="$CONFIG_FILES xdata/Makefile" ;; - "daemon-init" ) CONFIG_FILES="$CONFIG_FILES daemon-init" ;; - "t/Makefile" ) CONFIG_FILES="$CONFIG_FILES t/Makefile" ;; - "t-tap/Makefile" ) CONFIG_FILES="$CONFIG_FILES t-tap/Makefile" ;; - "include/config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS include/config.h" ;; - "include/snprintf.h" ) CONFIG_HEADERS="$CONFIG_HEADERS include/snprintf.h" ;; - *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 -echo "$as_me: error: invalid argument: $ac_config_target" >&2;} - { (exit 1); exit 1; }; };; + case $ac_config_target in + "include/config.h") CONFIG_HEADERS="$CONFIG_HEADERS include/config.h" ;; + "lib/snprintf.h") CONFIG_HEADERS="$CONFIG_HEADERS lib/snprintf.h" ;; + "lib/iobroker.h") CONFIG_HEADERS="$CONFIG_HEADERS lib/iobroker.h" ;; + "html/index.php") CONFIG_FILES="$CONFIG_FILES html/index.php" ;; + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "lib/Makefile") CONFIG_FILES="$CONFIG_FILES lib/Makefile" ;; + "subst") CONFIG_FILES="$CONFIG_FILES subst" ;; + "pkginfo") CONFIG_FILES="$CONFIG_FILES pkginfo" ;; + "base/Makefile") CONFIG_FILES="$CONFIG_FILES base/Makefile" ;; + "common/Makefile") CONFIG_FILES="$CONFIG_FILES common/Makefile" ;; + "contrib/Makefile") CONFIG_FILES="$CONFIG_FILES contrib/Makefile" ;; + "cgi/Makefile") CONFIG_FILES="$CONFIG_FILES cgi/Makefile" ;; + "html/Makefile") CONFIG_FILES="$CONFIG_FILES html/Makefile" ;; + "module/Makefile") CONFIG_FILES="$CONFIG_FILES module/Makefile" ;; + "worker/Makefile") CONFIG_FILES="$CONFIG_FILES worker/Makefile" ;; + "worker/ping/Makefile") CONFIG_FILES="$CONFIG_FILES worker/ping/Makefile" ;; + "xdata/Makefile") CONFIG_FILES="$CONFIG_FILES xdata/Makefile" ;; + "daemon-init") CONFIG_FILES="$CONFIG_FILES daemon-init" ;; + "t/Makefile") CONFIG_FILES="$CONFIG_FILES t/Makefile" ;; + "t-tap/Makefile") CONFIG_FILES="$CONFIG_FILES t-tap/Makefile" ;; + + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done + # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely @@ -7948,620 +6622,550 @@ if $ac_need_defaults; then fi # Have a temporary directory for convenience. Make it in the build tree -# simply because there is no reason to put it here, and in addition, +# simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. -# Create a temporary directory, and hook for its removal unless debugging. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. $debug || { - trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0 - trap '{ (exit 1); exit 1; }' 1 2 13 15 + tmp= ac_tmp= + trap 'exit_status=$? + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 } - # Create a (secure) tmp directory for tmp files. { - tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` && - test -n "$tmp" && test -d "$tmp" + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -d "$tmp" } || { - tmp=./confstat$$-$RANDOM - (umask 077 && mkdir $tmp) -} || + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && +_ACEOF + + { - echo "$me: cannot create a temporary directory in ." >&2 - { (exit 1); exit 1; } + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\)..*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\)..*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' >$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line } +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF -cat >>$CONFIG_STATUS <<_ACEOF +# VPATH may cause trouble with some makes, so we remove sole $(srcdir), +# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ +h +s/// +s/^/:/ +s/[ ]*$/:/ +s/:\$(srcdir):/:/g +s/:\${srcdir}:/:/g +s/:@srcdir@:/:/g +s/^:*// +s/:*$// +x +s/\(=[ ]*\).*/\1/ +G +s/\n// +s/^[^=]*=[ ]*$// +}' +fi -# -# CONFIG_FILES section. -# - -# No need to generate the scripts if there are no CONFIG_FILES. -# This happens for instance when ./config.status config.h -if test -n "\$CONFIG_FILES"; then - # Protect against being on the right side of a sed subst in config.status. - sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g; - s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF -s,@SHELL@,$SHELL,;t t -s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t -s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t -s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t -s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t -s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t -s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t -s,@exec_prefix@,$exec_prefix,;t t -s,@prefix@,$prefix,;t t -s,@program_transform_name@,$program_transform_name,;t t -s,@bindir@,$bindir,;t t -s,@sbindir@,$sbindir,;t t -s,@libexecdir@,$libexecdir,;t t -s,@datadir@,$datadir,;t t -s,@sysconfdir@,$sysconfdir,;t t -s,@sharedstatedir@,$sharedstatedir,;t t -s,@localstatedir@,$localstatedir,;t t -s,@libdir@,$libdir,;t t -s,@includedir@,$includedir,;t t -s,@oldincludedir@,$oldincludedir,;t t -s,@infodir@,$infodir,;t t -s,@mandir@,$mandir,;t t -s,@build_alias@,$build_alias,;t t -s,@host_alias@,$host_alias,;t t -s,@target_alias@,$target_alias,;t t -s,@DEFS@,$DEFS,;t t -s,@ECHO_C@,$ECHO_C,;t t -s,@ECHO_N@,$ECHO_N,;t t -s,@ECHO_T@,$ECHO_T,;t t -s,@LIBS@,$LIBS,;t t -s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t -s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t -s,@INSTALL_DATA@,$INSTALL_DATA,;t t -s,@INSTALL@,$INSTALL,;t t -s,@build@,$build,;t t -s,@build_cpu@,$build_cpu,;t t -s,@build_vendor@,$build_vendor,;t t -s,@build_os@,$build_os,;t t -s,@host@,$host,;t t -s,@host_cpu@,$host_cpu,;t t -s,@host_vendor@,$host_vendor,;t t -s,@host_os@,$host_os,;t t -s,@CC@,$CC,;t t -s,@CFLAGS@,$CFLAGS,;t t -s,@LDFLAGS@,$LDFLAGS,;t t -s,@CPPFLAGS@,$CPPFLAGS,;t t -s,@ac_ct_CC@,$ac_ct_CC,;t t -s,@EXEEXT@,$EXEEXT,;t t -s,@OBJEXT@,$OBJEXT,;t t -s,@SET_MAKE@,$SET_MAKE,;t t -s,@STRIP@,$STRIP,;t t -s,@CPP@,$CPP,;t t -s,@EGREP@,$EGREP,;t t -s,@SNPRINTF_O@,$SNPRINTF_O,;t t -s,@SOCKETLIBS@,$SOCKETLIBS,;t t -s,@THREADLIBS@,$THREADLIBS,;t t -s,@nagios_user@,$nagios_user,;t t -s,@nagios_grp@,$nagios_grp,;t t -s,@INSTALL_OPTS@,$INSTALL_OPTS,;t t -s,@command_user@,$command_user,;t t -s,@command_grp@,$command_grp,;t t -s,@COMMAND_OPTS@,$COMMAND_OPTS,;t t -s,@MAIL_PROG@,$MAIL_PROG,;t t -s,@HTTPD_CONF@,$HTTPD_CONF,;t t -s,@CHECKRESULTDIR@,$CHECKRESULTDIR,;t t -s,@TMPDIR@,$TMPDIR,;t t -s,@init_dir@,$init_dir,;t t -s,@lockfile@,$lockfile,;t t -s,@XSDC@,$XSDC,;t t -s,@XSDH@,$XSDH,;t t -s,@XCDC@,$XCDC,;t t -s,@XCDH@,$XCDH,;t t -s,@XRDC@,$XRDC,;t t -s,@XRDH@,$XRDH,;t t -s,@XODC@,$XODC,;t t -s,@XODH@,$XODH,;t t -s,@XPDC@,$XPDC,;t t -s,@XPDH@,$XPDH,;t t -s,@XDDC@,$XDDC,;t t -s,@XDDH@,$XDDH,;t t -s,@htmurl@,$htmurl,;t t -s,@cgiurl@,$cgiurl,;t t -s,@BROKER_LDFLAGS@,$BROKER_LDFLAGS,;t t -s,@BROKERLIBS@,$BROKERLIBS,;t t -s,@MOD_CFLAGS@,$MOD_CFLAGS,;t t -s,@MOD_LDFLAGS@,$MOD_LDFLAGS,;t t -s,@BROKER_O@,$BROKER_O,;t t -s,@BROKER_H@,$BROKER_H,;t t -s,@nagios_name@,$nagios_name,;t t -s,@nagiostats_name@,$nagiostats_name,;t t -s,@PATH_TO_TRACEROUTE@,$PATH_TO_TRACEROUTE,;t t -s,@PACKDIR@,$PACKDIR,;t t -s,@VERSION@,$VERSION,;t t -s,@subdirs@,$subdirs,;t t -s,@USE_LIBTAP@,$USE_LIBTAP,;t t -s,@CGIEXTRAS@,$CGIEXTRAS,;t t -s,@GDLIBS@,$GDLIBS,;t t -s,@PERLLIBS@,$PERLLIBS,;t t -s,@PERLDIR@,$PERLDIR,;t t -s,@PERLXSI_O@,$PERLXSI_O,;t t -s,@BASEEXTRALIBS@,$BASEEXTRALIBS,;t t -s,@INITDIR@,$INITDIR,;t t -s,@INSTALLPERLSTUFF@,$INSTALLPERLSTUFF,;t t -s,@USE_EVENTBROKER@,$USE_EVENTBROKER,;t t -s,@PERL@,$PERL,;t t -s,@LIBOBJS@,$LIBOBJS,;t t -s,@LTLIBOBJS@,$LTLIBOBJS,;t t -CEOF - -_ACEOF - - cat >>$CONFIG_STATUS <<\_ACEOF - # Split the substitutions into bite-sized pieces for seds with - # small command number limits, like on Digital OSF/1 and HP-UX. - ac_max_sed_lines=48 - ac_sed_frag=1 # Number of current file. - ac_beg=1 # First line for current file. - ac_end=$ac_max_sed_lines # Line after last line for current file. - ac_more_lines=: - ac_sed_cmds= - while $ac_more_lines; do - if test $ac_beg -gt 1; then - sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag - else - sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag - fi - if test ! -s $tmp/subs.frag; then - ac_more_lines=false - else - # The purpose of the label and of the branching condition is to - # speed up the sed processing (if there are no `@' at all, there - # is no need to browse any of the substitutions). - # These are the two extra sed commands mentioned above. - (echo ':t - /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed - if test -z "$ac_sed_cmds"; then - ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed" - else - ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed" - fi - ac_sed_frag=`expr $ac_sed_frag + 1` - ac_beg=$ac_end - ac_end=`expr $ac_end + $ac_max_sed_lines` - fi - done - if test -z "$ac_sed_cmds"; then - ac_sed_cmds=cat - fi +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" +# Set up the scripts for CONFIG_HEADERS section. +# No need to generate them if there are no CONFIG_HEADERS. +# This happens for instance with `./config.status Makefile'. +if test -n "$CONFIG_HEADERS"; then +cat >"$ac_tmp/defines.awk" <<\_ACAWK || +BEGIN { _ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF -for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue - # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". - case $ac_file in - - | *:- | *:-:* ) # input from stdin - cat >$tmp/stdin - ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` - ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; - *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` - ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; - * ) ac_file_in=$ac_file.in ;; + +# Transform confdefs.h into an awk script `defines.awk', embedded as +# here-document in config.status, that substitutes the proper values into +# config.h.in to produce config.h. + +# Create a delimiter string that does not exist in confdefs.h, to ease +# handling of long lines. +ac_delim='%!_!# ' +for ac_last_try in false false :; do + ac_tt=`sed -n "/$ac_delim/p" confdefs.h` + if test -z "$ac_tt"; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +# For the awk script, D is an array of macro values keyed by name, +# likewise P contains macro parameters if any. Preserve backslash +# newline sequences. + +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +sed -n ' +s/.\{148\}/&'"$ac_delim"'/g +t rset +:rset +s/^[ ]*#[ ]*define[ ][ ]*/ / +t def +d +:def +s/\\$// +t bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3"/p +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p +d +:bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3\\\\\\n"\\/p +t cont +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p +t cont +d +:cont +n +s/.\{148\}/&'"$ac_delim"'/g +t clear +:clear +s/\\$// +t bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/"/p +d +:bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p +b cont +' >$CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + for (key in D) D_is_set[key] = 1 + FS = "" +} +/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { + line = \$ 0 + split(line, arg, " ") + if (arg[1] == "#") { + defundef = arg[2] + mac1 = arg[3] + } else { + defundef = substr(arg[1], 2) + mac1 = arg[2] + } + split(mac1, mac2, "(") #) + macro = mac2[1] + prefix = substr(line, 1, index(line, defundef) - 1) + if (D_is_set[macro]) { + # Preserve the white space surrounding the "#". + print prefix "define", macro P[macro] D[macro] + next + } else { + # Replace #undef with comments. This is necessary, for example, + # in the case of _POSIX_SOURCE, which is predefined and required + # on some systems where configure will not decide to define it. + if (defundef == "undef") { + print "/*", prefix defundef, macro, "*/" + next + } + } +} +{ print } +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 +fi # test -n "$CONFIG_HEADERS" + + +eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS " +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$ac_tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + as_fn_append ac_file_inputs " '$ac_f'" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input='Generated from '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$ac_tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; esac - # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories. - ac_dir=`(dirname "$ac_file") 2>/dev/null || + ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ - X"$ac_file" : 'X\(/\)' \| \ - . : '\(.\)' 2>/dev/null || -echo X"$ac_file" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } - /^X\(\/\/\)[^/].*/{ s//\1/; q; } - /^X\(\/\/\)$/{ s//\1/; q; } - /^X\(\/\).*/{ s//\1/; q; } - s/.*/./; q'` - { if $as_mkdir_p; then - mkdir -p "$ac_dir" - else - as_dir="$ac_dir" - as_dirs= - while test ! -d "$as_dir"; do - as_dirs="$as_dir $as_dirs" - as_dir=`(dirname "$as_dir") 2>/dev/null || -$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$as_dir" : 'X\(//\)[^/]' \| \ - X"$as_dir" : 'X\(//\)$' \| \ - X"$as_dir" : 'X\(/\)' \| \ - . : '\(.\)' 2>/dev/null || -echo X"$as_dir" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } - /^X\(\/\/\)[^/].*/{ s//\1/; q; } - /^X\(\/\/\)$/{ s//\1/; q; } - /^X\(\/\).*/{ s//\1/; q; } - s/.*/./; q'` - done - test ! -n "$as_dirs" || mkdir $as_dirs - fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 -echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} - { (exit 1); exit 1; }; }; } - + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. -if test "$ac_dir" != .; then - ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` - # A "../" for each directory in $ac_dir_suffix. - ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` -else - ac_dir_suffix= ac_top_builddir= -fi +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix case $srcdir in - .) # No --srcdir option. We are building in place. + .) # We are building in place. ac_srcdir=. - if test -z "$ac_top_builddir"; then - ac_top_srcdir=. - else - ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` - fi ;; - [\\/]* | ?:[\\/]* ) # Absolute path. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; - ac_top_srcdir=$srcdir ;; - *) # Relative path. - ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix - ac_top_srcdir=$ac_top_builddir$srcdir ;; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix -# Do not use `cd foo && pwd` to compute absolute paths, because -# the directories may not exist. -case `pwd` in -.) ac_abs_builddir="$ac_dir";; -*) - case "$ac_dir" in - .) ac_abs_builddir=`pwd`;; - [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; - *) ac_abs_builddir=`pwd`/"$ac_dir";; - esac;; -esac -case $ac_abs_builddir in -.) ac_abs_top_builddir=${ac_top_builddir}.;; -*) - case ${ac_top_builddir}. in - .) ac_abs_top_builddir=$ac_abs_builddir;; - [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; - *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; - esac;; -esac -case $ac_abs_builddir in -.) ac_abs_srcdir=$ac_srcdir;; -*) - case $ac_srcdir in - .) ac_abs_srcdir=$ac_abs_builddir;; - [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; - *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; - esac;; -esac -case $ac_abs_builddir in -.) ac_abs_top_srcdir=$ac_top_srcdir;; -*) - case $ac_top_srcdir in - .) ac_abs_top_srcdir=$ac_abs_builddir;; - [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; - *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; - esac;; -esac + case $ac_mode in + :F) + # + # CONFIG_FILE + # case $INSTALL in [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; - *) ac_INSTALL=$ac_top_builddir$INSTALL ;; + *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; esac - - if test x"$ac_file" != x-; then - { echo "$as_me:$LINENO: creating $ac_file" >&5 -echo "$as_me: creating $ac_file" >&6;} - rm -f "$ac_file" - fi - # Let's still pretend it is `configure' which instantiates (i.e., don't - # use $as_me), people would be surprised to read: - # /* config.h. Generated by config.status. */ - if test x"$ac_file" = x-; then - configure_input= - else - configure_input="$ac_file. " - fi - configure_input=$configure_input"Generated from `echo $ac_file_in | - sed 's,.*/,,'` by configure." - - # First look for the input files in the build tree, otherwise in the - # src tree. - ac_file_inputs=`IFS=: - for f in $ac_file_in; do - case $f in - -) echo $tmp/stdin ;; - [\\/$]*) - # Absolute (can't be DOS-style, as IFS=:) - test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 -echo "$as_me: error: cannot find input file: $f" >&2;} - { (exit 1); exit 1; }; } - echo "$f";; - *) # Relative - if test -f "$f"; then - # Build tree - echo "$f" - elif test -f "$srcdir/$f"; then - # Source tree - echo "$srcdir/$f" - else - # /dev/null tree - { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 -echo "$as_me: error: cannot find input file: $f" >&2;} - { (exit 1); exit 1; }; } - fi;; - esac - done` || { (exit 1); exit 1; } _ACEOF -cat >>$CONFIG_STATUS <<_ACEOF - sed "$ac_vpsub + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub $extrasub _ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b -s,@configure_input@,$configure_input,;t t -s,@srcdir@,$ac_srcdir,;t t -s,@abs_srcdir@,$ac_abs_srcdir,;t t -s,@top_srcdir@,$ac_top_srcdir,;t t -s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t -s,@builddir@,$ac_builddir,;t t -s,@abs_builddir@,$ac_abs_builddir,;t t -s,@top_builddir@,$ac_top_builddir,;t t -s,@abs_top_builddir@,$ac_abs_top_builddir,;t t -s,@INSTALL@,$ac_INSTALL,;t t -" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out - rm -f $tmp/stdin - if test x"$ac_file" != x-; then - mv $tmp/out $ac_file - else - cat $tmp/out - rm -f $tmp/out - fi +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +s&@INSTALL@&$ac_INSTALL&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 -done -_ACEOF -cat >>$CONFIG_STATUS <<\_ACEOF +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&2;} -# -# CONFIG_HEADER section. -# - -# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where -# NAME is the cpp macro being defined and VALUE is the value it is being given. -# -# ac_d sets the value in "#define NAME VALUE" lines. -ac_dA='s,^\([ ]*\)#\([ ]*define[ ][ ]*\)' -ac_dB='[ ].*$,\1#\2' -ac_dC=' ' -ac_dD=',;t' -# ac_u turns "#undef NAME" without trailing blanks into "#define NAME VALUE". -ac_uA='s,^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' -ac_uB='$,\1#\2define\3' -ac_uC=' ' -ac_uD=',;t' - -for ac_file in : $CONFIG_HEADERS; do test "x$ac_file" = x: && continue - # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + rm -f "$ac_tmp/stdin" case $ac_file in - - | *:- | *:-:* ) # input from stdin - cat >$tmp/stdin - ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` - ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; - *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` - ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; - * ) ac_file_in=$ac_file.in ;; - esac - - test x"$ac_file" != x- && { echo "$as_me:$LINENO: creating $ac_file" >&5 -echo "$as_me: creating $ac_file" >&6;} - - # First look for the input files in the build tree, otherwise in the - # src tree. - ac_file_inputs=`IFS=: - for f in $ac_file_in; do - case $f in - -) echo $tmp/stdin ;; - [\\/$]*) - # Absolute (can't be DOS-style, as IFS=:) - test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 -echo "$as_me: error: cannot find input file: $f" >&2;} - { (exit 1); exit 1; }; } - # Do quote $f, to prevent DOS paths from being IFS'd. - echo "$f";; - *) # Relative - if test -f "$f"; then - # Build tree - echo "$f" - elif test -f "$srcdir/$f"; then - # Source tree - echo "$srcdir/$f" - else - # /dev/null tree - { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 -echo "$as_me: error: cannot find input file: $f" >&2;} - { (exit 1); exit 1; }; } - fi;; - esac - done` || { (exit 1); exit 1; } - # Remove the trailing spaces. - sed 's/[ ]*$//' $ac_file_inputs >$tmp/in - -_ACEOF - -# Transform confdefs.h into two sed scripts, `conftest.defines' and -# `conftest.undefs', that substitutes the proper values into -# config.h.in to produce config.h. The first handles `#define' -# templates, and the second `#undef' templates. -# And first: Protect against being on the right side of a sed subst in -# config.status. Protect against being in an unquoted here document -# in config.status. -rm -f conftest.defines conftest.undefs -# Using a here document instead of a string reduces the quoting nightmare. -# Putting comments in sed scripts is not portable. -# -# `end' is used to avoid that the second main sed command (meant for -# 0-ary CPP macros) applies to n-ary macro definitions. -# See the Autoconf documentation for `clear'. -cat >confdef2sed.sed <<\_ACEOF -s/[\\&,]/\\&/g -s,[\\$`],\\&,g -t clear -: clear -s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*\)\(([^)]*)\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1\2${ac_dC}\3${ac_dD},gp -t end -s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp -: end -_ACEOF -# If some macros were called several times there might be several times -# the same #defines, which is useless. Nevertheless, we may not want to -# sort them, since we want the *last* AC-DEFINE to be honored. -uniq confdefs.h | sed -n -f confdef2sed.sed >conftest.defines -sed 's/ac_d/ac_u/g' conftest.defines >conftest.undefs -rm -f confdef2sed.sed - -# This sed command replaces #undef with comments. This is necessary, for -# example, in the case of _POSIX_SOURCE, which is predefined and required -# on some systems where configure will not decide to define it. -cat >>conftest.undefs <<\_ACEOF -s,^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */, -_ACEOF - -# Break up conftest.defines because some shells have a limit on the size -# of here documents, and old seds have small limits too (100 cmds). -echo ' # Handle all the #define templates only if necessary.' >>$CONFIG_STATUS -echo ' if grep "^[ ]*#[ ]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS -echo ' # If there are no defines, we may have an empty if/fi' >>$CONFIG_STATUS -echo ' :' >>$CONFIG_STATUS -rm -f conftest.tail -while grep . conftest.defines >/dev/null -do - # Write a limited-size here document to $tmp/defines.sed. - echo ' cat >$tmp/defines.sed <>$CONFIG_STATUS - # Speed up: don't consider the non `#define' lines. - echo '/^[ ]*#[ ]*define/!b' >>$CONFIG_STATUS - # Work around the forget-to-reset-the-flag bug. - echo 't clr' >>$CONFIG_STATUS - echo ': clr' >>$CONFIG_STATUS - sed ${ac_max_here_lines}q conftest.defines >>$CONFIG_STATUS - echo 'CEOF - sed -f $tmp/defines.sed $tmp/in >$tmp/out - rm -f $tmp/in - mv $tmp/out $tmp/in -' >>$CONFIG_STATUS - sed 1,${ac_max_here_lines}d conftest.defines >conftest.tail - rm -f conftest.defines - mv conftest.tail conftest.defines -done -rm -f conftest.defines -echo ' fi # grep' >>$CONFIG_STATUS -echo >>$CONFIG_STATUS - -# Break up conftest.undefs because some shells have a limit on the size -# of here documents, and old seds have small limits too (100 cmds). -echo ' # Handle all the #undef templates' >>$CONFIG_STATUS -rm -f conftest.tail -while grep . conftest.undefs >/dev/null -do - # Write a limited-size here document to $tmp/undefs.sed. - echo ' cat >$tmp/undefs.sed <>$CONFIG_STATUS - # Speed up: don't consider the non `#undef' - echo '/^[ ]*#[ ]*undef/!b' >>$CONFIG_STATUS - # Work around the forget-to-reset-the-flag bug. - echo 't clr' >>$CONFIG_STATUS - echo ': clr' >>$CONFIG_STATUS - sed ${ac_max_here_lines}q conftest.undefs >>$CONFIG_STATUS - echo 'CEOF - sed -f $tmp/undefs.sed $tmp/in >$tmp/out - rm -f $tmp/in - mv $tmp/out $tmp/in -' >>$CONFIG_STATUS - sed 1,${ac_max_here_lines}d conftest.undefs >conftest.tail - rm -f conftest.undefs - mv conftest.tail conftest.undefs -done -rm -f conftest.undefs - -cat >>$CONFIG_STATUS <<\_ACEOF - # Let's still pretend it is `configure' which instantiates (i.e., don't - # use $as_me), people would be surprised to read: - # /* config.h. Generated by config.status. */ - if test x"$ac_file" = x-; then - echo "/* Generated by configure. */" >$tmp/config.h - else - echo "/* $ac_file. Generated by configure. */" >$tmp/config.h - fi - cat $tmp/in >>$tmp/config.h - rm -f $tmp/in + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; + esac \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + ;; + :H) + # + # CONFIG_HEADER + # if test x"$ac_file" != x-; then - if diff $ac_file $tmp/config.h >/dev/null 2>&1; then - { echo "$as_me:$LINENO: $ac_file is unchanged" >&5 -echo "$as_me: $ac_file is unchanged" >&6;} + { + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" + } >"$ac_tmp/config.h" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then + { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 +$as_echo "$as_me: $ac_file is unchanged" >&6;} else - ac_dir=`(dirname "$ac_file") 2>/dev/null || -$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$ac_file" : 'X\(//\)[^/]' \| \ - X"$ac_file" : 'X\(//\)$' \| \ - X"$ac_file" : 'X\(/\)' \| \ - . : '\(.\)' 2>/dev/null || -echo X"$ac_file" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } - /^X\(\/\/\)[^/].*/{ s//\1/; q; } - /^X\(\/\/\)$/{ s//\1/; q; } - /^X\(\/\).*/{ s//\1/; q; } - s/.*/./; q'` - { if $as_mkdir_p; then - mkdir -p "$ac_dir" - else - as_dir="$ac_dir" - as_dirs= - while test ! -d "$as_dir"; do - as_dirs="$as_dir $as_dirs" - as_dir=`(dirname "$as_dir") 2>/dev/null || -$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$as_dir" : 'X\(//\)[^/]' \| \ - X"$as_dir" : 'X\(//\)$' \| \ - X"$as_dir" : 'X\(/\)' \| \ - . : '\(.\)' 2>/dev/null || -echo X"$as_dir" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } - /^X\(\/\/\)[^/].*/{ s//\1/; q; } - /^X\(\/\/\)$/{ s//\1/; q; } - /^X\(\/\).*/{ s//\1/; q; } - s/.*/./; q'` - done - test ! -n "$as_dirs" || mkdir $as_dirs - fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 -echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} - { (exit 1); exit 1; }; }; } - - rm -f $ac_file - mv $tmp/config.h $ac_file + rm -f "$ac_file" + mv "$ac_tmp/config.h" "$ac_file" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 fi else - cat $tmp/config.h - rm -f $tmp/config.h + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ + || as_fn_error $? "could not create -" "$LINENO" 5 fi -done -_ACEOF + ;; -cat >>$CONFIG_STATUS <<\_ACEOF -{ (exit 0); exit 0; } + esac + +done # for ac_tag + + +as_fn_exit 0 _ACEOF -chmod +x $CONFIG_STATUS ac_clean_files=$ac_clean_files_save +test $ac_write_fail = 0 || + as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 + # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. @@ -8581,7 +7185,7 @@ if test "$no_create" != yes; then exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. - $ac_cs_success || { (exit 1); exit 1; } + $ac_cs_success || as_fn_exit 1 fi # @@ -8589,10 +7193,14 @@ fi # if test "$no_recursion" != yes; then - # Remove --cache-file and --srcdir arguments so they do not pile up. + # Remove --cache-file, --srcdir, and --disable-option-checking arguments + # so they do not pile up. ac_sub_configure_args= ac_prev= - for ac_arg in $ac_configure_args; do + eval "set x $ac_configure_args" + shift + for ac_arg + do if test -n "$ac_prev"; then ac_prev= continue @@ -8615,126 +7223,92 @@ if test "$no_recursion" != yes; then ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) ;; - *) ac_sub_configure_args="$ac_sub_configure_args $ac_arg" ;; + --disable-option-checking) + ;; + *) + case $ac_arg in + *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append ac_sub_configure_args " '$ac_arg'" ;; esac done # Always prepend --prefix to ensure using the same prefix # in subdir configurations. - ac_sub_configure_args="--prefix=$prefix $ac_sub_configure_args" + ac_arg="--prefix=$prefix" + case $ac_arg in + *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + ac_sub_configure_args="'$ac_arg' $ac_sub_configure_args" + + # Pass --silent + if test "$silent" = yes; then + ac_sub_configure_args="--silent $ac_sub_configure_args" + fi + + # Always prepend --disable-option-checking to silence warnings, since + # different subdirs can have different --enable and --with options. + ac_sub_configure_args="--disable-option-checking $ac_sub_configure_args" ac_popdir=`pwd` for ac_dir in : $subdirs; do test "x$ac_dir" = x: && continue # Do not complain, so a configure script can configure whichever # parts of a large source tree are present. - test -d $srcdir/$ac_dir || continue - - { echo "$as_me:$LINENO: configuring in $ac_dir" >&5 -echo "$as_me: configuring in $ac_dir" >&6;} - { if $as_mkdir_p; then - mkdir -p "$ac_dir" - else - as_dir="$ac_dir" - as_dirs= - while test ! -d "$as_dir"; do - as_dirs="$as_dir $as_dirs" - as_dir=`(dirname "$as_dir") 2>/dev/null || -$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$as_dir" : 'X\(//\)[^/]' \| \ - X"$as_dir" : 'X\(//\)$' \| \ - X"$as_dir" : 'X\(/\)' \| \ - . : '\(.\)' 2>/dev/null || -echo X"$as_dir" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } - /^X\(\/\/\)[^/].*/{ s//\1/; q; } - /^X\(\/\/\)$/{ s//\1/; q; } - /^X\(\/\).*/{ s//\1/; q; } - s/.*/./; q'` - done - test ! -n "$as_dirs" || mkdir $as_dirs - fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 -echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} - { (exit 1); exit 1; }; }; } + test -d "$srcdir/$ac_dir" || continue + ac_msg="=== configuring in $ac_dir (`pwd`/$ac_dir)" + $as_echo "$as_me:${as_lineno-$LINENO}: $ac_msg" >&5 + $as_echo "$ac_msg" >&6 + as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. -if test "$ac_dir" != .; then - ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` - # A "../" for each directory in $ac_dir_suffix. - ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` -else - ac_dir_suffix= ac_top_builddir= -fi +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix case $srcdir in - .) # No --srcdir option. We are building in place. + .) # We are building in place. ac_srcdir=. - if test -z "$ac_top_builddir"; then - ac_top_srcdir=. - else - ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` - fi ;; - [\\/]* | ?:[\\/]* ) # Absolute path. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; - ac_top_srcdir=$srcdir ;; - *) # Relative path. - ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix - ac_top_srcdir=$ac_top_builddir$srcdir ;; -esac - -# Do not use `cd foo && pwd` to compute absolute paths, because -# the directories may not exist. -case `pwd` in -.) ac_abs_builddir="$ac_dir";; -*) - case "$ac_dir" in - .) ac_abs_builddir=`pwd`;; - [\\/]* | ?:[\\/]* ) ac_abs_builddir="$ac_dir";; - *) ac_abs_builddir=`pwd`/"$ac_dir";; - esac;; -esac -case $ac_abs_builddir in -.) ac_abs_top_builddir=${ac_top_builddir}.;; -*) - case ${ac_top_builddir}. in - .) ac_abs_top_builddir=$ac_abs_builddir;; - [\\/]* | ?:[\\/]* ) ac_abs_top_builddir=${ac_top_builddir}.;; - *) ac_abs_top_builddir=$ac_abs_builddir/${ac_top_builddir}.;; - esac;; -esac -case $ac_abs_builddir in -.) ac_abs_srcdir=$ac_srcdir;; -*) - case $ac_srcdir in - .) ac_abs_srcdir=$ac_abs_builddir;; - [\\/]* | ?:[\\/]* ) ac_abs_srcdir=$ac_srcdir;; - *) ac_abs_srcdir=$ac_abs_builddir/$ac_srcdir;; - esac;; -esac -case $ac_abs_builddir in -.) ac_abs_top_srcdir=$ac_top_srcdir;; -*) - case $ac_top_srcdir in - .) ac_abs_top_srcdir=$ac_abs_builddir;; - [\\/]* | ?:[\\/]* ) ac_abs_top_srcdir=$ac_top_srcdir;; - *) ac_abs_top_srcdir=$ac_abs_builddir/$ac_top_srcdir;; - esac;; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix - cd $ac_dir + cd "$ac_dir" # Check for guested configure; otherwise get Cygnus style configure. - if test -f $ac_srcdir/configure.gnu; then - ac_sub_configure="$SHELL '$ac_srcdir/configure.gnu'" - elif test -f $ac_srcdir/configure; then - ac_sub_configure="$SHELL '$ac_srcdir/configure'" - elif test -f $ac_srcdir/configure.in; then - ac_sub_configure=$ac_configure + if test -f "$ac_srcdir/configure.gnu"; then + ac_sub_configure=$ac_srcdir/configure.gnu + elif test -f "$ac_srcdir/configure"; then + ac_sub_configure=$ac_srcdir/configure + elif test -f "$ac_srcdir/configure.in"; then + # This should be Cygnus configure. + ac_sub_configure=$ac_aux_dir/configure else - { echo "$as_me:$LINENO: WARNING: no configuration information is in $ac_dir" >&5 -echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: no configuration information is in $ac_dir" >&5 +$as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2;} ac_sub_configure= fi @@ -8743,23 +7317,25 @@ echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2;} # Make the cache file name correct relative to the subdirectory. case $cache_file in [\\/]* | ?:[\\/]* ) ac_sub_cache_file=$cache_file ;; - *) # Relative path. - ac_sub_cache_file=$ac_top_builddir$cache_file ;; + *) # Relative name. + ac_sub_cache_file=$ac_top_build_prefix$cache_file ;; esac - { echo "$as_me:$LINENO: running $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir" >&5 -echo "$as_me: running $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir" >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: running $SHELL $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir" >&5 +$as_echo "$as_me: running $SHELL $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir" >&6;} # The eval makes quoting arguments work. - eval $ac_sub_configure $ac_sub_configure_args \ - --cache-file=$ac_sub_cache_file --srcdir=$ac_srcdir || - { { echo "$as_me:$LINENO: error: $ac_sub_configure failed for $ac_dir" >&5 -echo "$as_me: error: $ac_sub_configure failed for $ac_dir" >&2;} - { (exit 1); exit 1; }; } + eval "\$SHELL \"\$ac_sub_configure\" $ac_sub_configure_args \ + --cache-file=\"\$ac_sub_cache_file\" --srcdir=\"\$ac_srcdir\"" || + as_fn_error $? "$ac_sub_configure failed for $ac_dir" "$LINENO" 5 fi - cd $ac_popdir + cd "$ac_popdir" done fi +if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi @@ -8791,70 +7367,62 @@ perl subst sample-config/template-object/switch.cfg echo "" echo "" -echo "$as_me:$LINENO: result: *** Configuration summary for $PKG_NAME $PKG_VERSION $PKG_REL_DATE ***:" >&5 -echo "${ECHO_T}*** Configuration summary for $PKG_NAME $PKG_VERSION $PKG_REL_DATE ***:" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: *** Configuration summary for $PKG_NAME $PKG_VERSION $PKG_REL_DATE ***:" >&5 +$as_echo "*** Configuration summary for $PKG_NAME $PKG_VERSION $PKG_REL_DATE ***:" >&6; } echo "" echo " General Options:" echo " -------------------------" -echo "$as_me:$LINENO: result: Nagios executable: $nagios_name" >&5 -echo "${ECHO_T} Nagios executable: $nagios_name" >&6 -echo "$as_me:$LINENO: result: Nagios user/group: $nagios_user,$nagios_grp" >&5 -echo "${ECHO_T} Nagios user/group: $nagios_user,$nagios_grp" >&6 -echo "$as_me:$LINENO: result: Command user/group: $command_user,$command_grp" >&5 -echo "${ECHO_T} Command user/group: $command_user,$command_grp" >&6 -if test x$USEPERL = xyes; then -if test x$PERLCACHE = xyes; then -echo "$as_me:$LINENO: result: Embedded Perl: yes, with caching" >&5 -echo "${ECHO_T} Embedded Perl: yes, with caching" >&6 -else -echo "$as_me:$LINENO: result: Embedded Perl: yes, without caching" >&5 -echo "${ECHO_T} Embedded Perl: yes, without caching" >&6 -fi -else -echo "$as_me:$LINENO: result: Embedded Perl: no" >&5 -echo "${ECHO_T} Embedded Perl: no" >&6 -fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Nagios executable: $nagios_name" >&5 +$as_echo " Nagios executable: $nagios_name" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Nagios user/group: $nagios_user,$nagios_grp" >&5 +$as_echo " Nagios user/group: $nagios_user,$nagios_grp" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Command user/group: $command_user,$command_grp" >&5 +$as_echo " Command user/group: $command_user,$command_grp" >&6; } if test x$USE_EVENTBROKER = xyes; then -echo "$as_me:$LINENO: result: Event Broker: yes" >&5 -echo "${ECHO_T} Event Broker: yes" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Event Broker: yes" >&5 +$as_echo " Event Broker: yes" >&6; } else -echo "$as_me:$LINENO: result: Event Broker: no" >&5 -echo "${ECHO_T} Event Broker: no" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Event Broker: no" >&5 +$as_echo " Event Broker: no" >&6; } fi -echo "$as_me:$LINENO: result: Install \${prefix}: $prefix" >&5 -echo "${ECHO_T} Install \${prefix}: $prefix" >&6 -echo "$as_me:$LINENO: result: Lock file: $lockfile" >&5 -echo "${ECHO_T} Lock file: $lockfile" >&6 -echo "$as_me:$LINENO: result: Check result directory: $CHECKRESULTDIR" >&5 -echo "${ECHO_T} Check result directory: $CHECKRESULTDIR" >&6 -echo "$as_me:$LINENO: result: Init directory: $init_dir" >&5 -echo "${ECHO_T} Init directory: $init_dir" >&6 -echo "$as_me:$LINENO: result: Apache conf.d directory: $HTTPD_CONF" >&5 -echo "${ECHO_T} Apache conf.d directory: $HTTPD_CONF" >&6 -echo "$as_me:$LINENO: result: Mail program: $MAIL_PROG" >&5 -echo "${ECHO_T} Mail program: $MAIL_PROG" >&6 -echo "$as_me:$LINENO: result: Host OS: $host_os" >&5 -echo "${ECHO_T} Host OS: $host_os" >&6 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Install \${prefix}: $prefix" >&5 +$as_echo " Install \${prefix}: $prefix" >&6; } +incdir=`eval echo $includedir` +if test x$incdir = x$prefix/include; then + includedir=$prefix/include/nagios +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Install \${includedir}: $includedir" >&5 +$as_echo " Install \${includedir}: $includedir" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Lock file: $lockfile" >&5 +$as_echo " Lock file: $lockfile" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Check result directory: $CHECKRESULTDIR" >&5 +$as_echo " Check result directory: $CHECKRESULTDIR" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Init directory: $init_dir" >&5 +$as_echo " Init directory: $init_dir" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Apache conf.d directory: $HTTPD_CONF" >&5 +$as_echo " Apache conf.d directory: $HTTPD_CONF" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Mail program: $MAIL_PROG" >&5 +$as_echo " Mail program: $MAIL_PROG" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Host OS: $host_os" >&5 +$as_echo " Host OS: $host_os" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: IOBroker Method: $IOBROKER_METHOD" >&5 +$as_echo " IOBroker Method: $IOBROKER_METHOD" >&6; } echo "" echo " Web Interface Options:" echo " ------------------------" -echo "$as_me:$LINENO: result: HTML URL: http://localhost$htmurl/" >&5 -echo "${ECHO_T} HTML URL: http://localhost$htmurl/" >&6 -echo "$as_me:$LINENO: result: CGI URL: http://localhost$cgiurl/" >&5 -echo "${ECHO_T} CGI URL: http://localhost$cgiurl/" >&6 -echo "$as_me:$LINENO: result: Traceroute (used by WAP): $PATH_TO_TRACEROUTE" >&5 -echo "${ECHO_T} Traceroute (used by WAP): $PATH_TO_TRACEROUTE" >&6 - - - +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: HTML URL: http://localhost$htmurl/" >&5 +$as_echo " HTML URL: http://localhost$htmurl/" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: CGI URL: http://localhost$cgiurl/" >&5 +$as_echo " CGI URL: http://localhost$cgiurl/" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Traceroute (used by WAP): $PATH_TO_TRACEROUTE" >&5 +$as_echo " Traceroute (used by WAP): $PATH_TO_TRACEROUTE" >&6; } echo "" echo "" echo "Review the options above for accuracy. If they look okay," echo "type 'make all' to compile the main program and CGIs." echo "" - diff --git a/configure.in b/configure.ac similarity index 68% rename from configure.in rename to configure.ac index b575b02..d3a4c7f 100644 --- a/configure.in +++ b/configure.ac @@ -5,13 +5,14 @@ define([AC_CACHE_LOAD],) define([AC_CACHE_SAVE],) AC_INIT(base/nagios.c) -AC_CONFIG_HEADER(include/config.h include/snprintf.h) +AC_CONFIG_HEADER(include/config.h lib/snprintf.h lib/iobroker.h) AC_PREFIX_DEFAULT(/usr/local/nagios) PKG_NAME=nagios -PKG_VERSION="3.5.1" -PKG_HOME_URL="http://www.nagios.org/" -PKG_REL_DATE="08-30-2013" + +PKG_VERSION="4.3.2" +PKG_HOME_URL="https://www.nagios.org/" +PKG_REL_DATE="2017-05-09" dnl Figure out how to invoke "install" and what install options to use. AC_PROG_INSTALL @@ -20,16 +21,25 @@ AC_SUBST(INSTALL) dnl What OS are we running? AC_CANONICAL_HOST +AC_CONFIG_FILES([html/index.php]) + dnl Checks for programs. AC_PROG_CC AC_PROG_MAKE_SET +AC_PROG_LN_S AC_PATH_PROG([STRIP],[strip],[true]) dnl Checks for header files. AC_HEADER_STDC AC_HEADER_TIME AC_HEADER_SYS_WAIT -AC_CHECK_HEADERS(arpa/inet.h ctype.h dirent.h errno.h fcntl.h getopt.h grp.h libgen.h limits.h math.h netdb.h netinet/in.h pthread.h pthreads.h pwd.h regex.h signal.h socket.h stdarg.h string.h strings.h sys/mman.h sys/types.h sys/time.h sys/resource.h sys/wait.h sys/socket.h sys/stat.h sys/timeb.h sys/un.h sys/ipc.h sys/msg.h sys/poll.h syslog.h uio.h unistd.h locale.h wchar.h) +AC_CHECK_HEADERS(arpa/inet.h ctype.h dirent.h errno.h fcntl.h getopt.h grp.h) +AC_CHECK_HEADERS(libgen.h limits.h math.h netdb.h netinet/in.h pwd.h regex.h) +AC_CHECK_HEADERS(signal.h socket.h stdarg.h string.h strings.h sys/loadavg.h) +AC_CHECK_HEADERS(sys/mman.h sys/types.h sys/time.h sys/resource.h sys/wait.h) +AC_CHECK_HEADERS(sys/socket.h sys/stat.h sys/timeb.h sys/un.h sys/ipc.h) +AC_CHECK_HEADERS(sys/msg.h sys/poll.h syslog.h uio.h unistd.h locale.h wchar.h) +AC_CHECK_HEADERS(sys/prctl.h) dnl Checks for typedefs, structures, and compiler characteristics. AC_C_CONST @@ -61,10 +71,11 @@ else fi fi -AC_CHECK_FUNC(vsnprintf,,SNPRINTF_O=../common/snprintf.o) -AC_CHECK_FUNC(snprintf,,SNPRINTF_O=../common/snprintf.o) -AC_CHECK_FUNC(asprintf,,SNPRINTF_O=../common/snprintf.o) -AC_CHECK_FUNC(vasprintf,,SNPRINTF_O=../common/snprintf.o) +AC_CHECK_FUNC(vsnprintf,,SNPRINTF_O=../lib/snprintf.o) +AC_CHECK_FUNC(snprintf,,SNPRINTF_O=../lib/snprintf.o) +AC_CHECK_FUNC(asprintf,,SNPRINTF_O=../lib/snprintf.o) +AC_CHECK_FUNC(vasprintf,,SNPRINTF_O=../lib/snprintf.o) +AC_CHECK_FUNCS(sigaction) AC_CACHE_CHECK([for C99 vsnprintf],ac_cv_HAVE_C99_VSNPRINTF,[ AC_TRY_RUN([ @@ -122,79 +133,26 @@ AC_TRY_COMPILE([#include [AC_DEFINE(SOCKET_SIZE_TYPE, int, [typedef for socket size]) AC_MSG_RESULT(int)]) -dnl Test for pthreads support - taken from ICU FreeBSD Port configure script -THREADLIBS="" -have_pthreads="no" - -dnl FreeBSD: Try ports/linuxthreads first - Mammad Zadeh -dnl FreeBSD -pthread check - Jonathan McDowell -AC_DEFUN([AC_PTHREAD_FREEBSD],[ - AC_CHECK_LIB(lthread,pthread_create,[ - CFLAGS="-D_THREAD_SAFE -I/usr/local/include/pthread/linuxthreads -I/usr/include $CFLAGS" - THREADLIBS="-L/usr/local/lib -llthread -llgcc_r" - ],[ - AC_MSG_CHECKING([if we need -pthread for threads]) - AC_CACHE_VAL(ac_ldflag_pthread,[ - ac_save_LDFLAGS="$LDFLAGS" - LDFLAGS="-pthread $LDFLAGS" - AC_TRY_LINK([ - char pthread_create(); - ], - pthread_create();, - eval "ac_ldflag_pthread=yes", - eval "ac_ldflag_pthread=no" - ), - THREADLIBS="$ac_save_LDFLAGS" - ]) - if eval "test \"`echo $ac_ldflag_pthread`\" = yes"; then - AC_MSG_RESULT(yes) - else - AC_MSG_RESULT(no) - fi - ],-L/usr/local/lib) - ]) - -dnl Test for HPUX cma threads first.. -AC_CHECK_LIB(cma,pthread_create,THREADLIBS="$THREADLIBS -lpthread") -if test $ac_cv_lib_cma_pthread_create = yes; then - have_pthreads="yes" -fi - -dnl special pthread handling -dnl AIX uses pthreads instead of pthread, and HP/UX uses cma -dnl FreeBSD users -pthread -AC_CHECK_LIB(pthread,pthread_create,THREADLIBS="$THREADLIBS -lpthread") -if test $ac_cv_lib_pthread_pthread_create = yes; then - have_pthreads="yes" -else - dnl For HP 11 - AC_CHECK_LIB(pthread,pthread_mutex_init,THREADLIBS="$THREADLIBS -lpthread") - if test $ac_cv_lib_pthread_pthread_mutex_init = yes; then - have_pthreads="yes" - fi -fi - -dnl AIX uses pthreads instead of pthread -if test $have_pthreads = "no"; then - AC_CHECK_LIB(pthreads,pthread_create,THREADLIBS="$THREADLIBS -lpthreads") - if test $ac_cv_lib_pthreads_pthread_create = yes; then - have_pthreads="yes" - fi -fi - -dnl all other thread tests fail, try BSD's -pthread -if test $have_pthreads = "no"; then - AC_PTHREAD_FREEBSD -fi - -AC_SUBST(THREADLIBS) - dnl Solaris needs rt or posix4 libraries for nanosleep() AC_SEARCH_LIBS(nanosleep,[rt posix4],,[ echo "Error: nanosleep() needed for timing operations." exit 1 ]) +case $host_os in +*bsd*|darwin*) + root_grp=wheel + ;; +*) + root_grp=root + ;; +esac + +AC_ARG_WITH(root_group,AC_HELP_STRING([--with-root-group=],[sets group name for installing init]),root_grp=$withval) +AC_SUBST(root_grp) +INIT_OPTS="-o root -g $root_grp" +AC_SUBST(INIT_OPTS) + AC_ARG_WITH(nagios_user,AC_HELP_STRING([--with-nagios-user=],[sets user name to run nagios]),nagios_user=$withval,nagios_user=nagios) AC_ARG_WITH(nagios_group,AC_HELP_STRING([--with-nagios-group=],[sets group name to run nagios]),nagios_grp=$withval,nagios_grp=nagios) AC_SUBST(nagios_user) @@ -213,7 +171,12 @@ AC_SUBST(COMMAND_OPTS) dnl Check for location of mail program MAIL_PROG=no -AC_ARG_WITH(mail,--with-mail= sets path to equivalent program to mail,MAIL_PROG=$withval,MAIL_PROG=no) +AC_ARG_WITH(mail, + AC_HELP_STRING([--with-mail=], + [sets path to equivalent program to mail]), + MAIL_PROG=$withval, + MAIL_PROG=no +) if test x$MAIL_PROG = xno; then AC_PATH_PROG(MAIL_PROG,mail) fi @@ -225,12 +188,25 @@ AC_SUBST(MAIL_PROG) dnl Check for location of Apache conf.d directory HTTP_CONF=no -AC_ARG_WITH(httpd_conf,--with-httpd-conf= sets path to Apache conf.d directory,HTTPD_CONF=$withval,HTTPD_CONF=no) +AC_ARG_WITH(httpd_conf, + AC_HELP_STRING([--with-httpd-conf=], + [sets path to Apache conf.d directory]), + HTTPD_CONF=$withval, + HTTPD_CONF=no +) +LN_HTTPD_SITES_ENABLED=0 if test x$HTTPD_CONF = xno; then if test -d /etc/httpd/conf.d; then HTTPD_CONF="/etc/httpd/conf.d" elif test -d /etc/apache2/conf.d; then HTTPD_CONF="/etc/apache2/conf.d" + elif test -d /etc/apache2/sites-available; then + HTTPD_CONF="/etc/apache2/sites-available" + if test -d /etc/apache2/sites-enabled; then + LN_HTTPD_SITES_ENABLED=1 + fi + elif test -d /etc/apache2/sites-enabled; then + HTTPD_CONF="/etc/apache2/sites-enabled" elif test -d /etc/apache/conf.d; then HTTPD_CONF="/etc/apache/conf.d" else @@ -238,10 +214,16 @@ if test x$HTTPD_CONF = xno; then fi fi AC_SUBST(HTTPD_CONF) +AC_SUBST(LN_HTTPD_SITES_ENABLED) dnl Location of check result path CHECKRESULTDIR=no -AC_ARG_WITH(checkresult-dir,--with-checkresult-dir= sets path to check results spool directory,CHECKRESULTDIR=$withval,CHECKRESULTDIR=no) +AC_ARG_WITH(checkresult-dir, + AC_HELP_STRING([--with-checkresult-dir=], + [sets path to check results spool directory]), + CHECKRESULTDIR=$withval, + CHECKRESULTDIR=no +) if test x$CHECKRESULTDIR = xno; then CHECKRESULTDIR="$localstatedir/spool/checkresults" fi @@ -249,7 +231,12 @@ AC_SUBST(CHECKRESULTDIR) dnl Location of check result path TMPDIR=no -AC_ARG_WITH(temp-dir,--with-temp-dir= sets path to temp directory,TMPDIR=$withval,TMPDIR=no) +AC_ARG_WITH(temp-dir, + AC_HELP_STRING([--with-temp-dir=], + [sets path to temp directory]), + TMPDIR=$withval, + TMPDIR=no +) if test x$TMPDIR = xno; then TMPDIR="/tmp" fi @@ -270,114 +257,150 @@ elif test -d /sbin/init.d; then fi dnl User can override init script location -AC_ARG_WITH(init_dir,--with-init-dir= sets directory to place init script into,init_dir=$withval) +AC_ARG_WITH(init_dir, + AC_HELP_STRING([--with-init-dir=], + [sets directory to place init script into]), + init_dir=$withval +) AC_SUBST(init_dir) dnl User can override lock file location -AC_ARG_WITH(lockfile,--with-lockfile= sets path and file name for lock file,lockfile=$withval,lockfile=$localstatedir/nagios.lock) +AC_ARG_WITH(lockfile, + AC_HELP_STRING([--with-lockfile=], + [sets path and file name for lock file]), + lockfile=$withval, + lockfile=$localstatedir/nagios.lock +) AC_SUBST(lockfile) +dnl Determine the library to be used by the iobroker -dnl Default xdata routines... -XSDTYPE=default -XCDTYPE=default -XRDTYPE=default -XODTYPE=template -XPDTYPE=default -XDDTYPE=default +dnl epoll_*() is linux specific and was added to glibc 2.3.2, so we +dnl check for 2.4 and use epoll() if we're on that version or later. -XSDCOMMENT= -XCDCOMMENT= -XRDCOMMENT= -XODCOMMENT= -XPDCOMMENT= -XDDCOMMENT= +case $host_os in +linux*) + AC_MSG_CHECKING(for glibc at least version 2.4) + AC_TRY_CPP( + [ +#include +#if defined(__GLIBC__) && defined(__linux) +#include +# if !__GLIBC_PREREQ(2, 4) +# error GLIBC too old +# endif +#else +# error Not using GLIBC +#endif + ], + [GLIBC_NEWER_2_4=1; AC_MSG_RESULT(yes)], + [GLIBC_NEWER_2_4=0; AC_MSG_RESULT(no)] + ) + if test $GLIBC_NEWER_2_4 -eq 1; then + AC_CHECK_HEADER([sys/epoll.h]) + fi + ;; +esac +AC_CHECK_HEADER([sys/select.h]) -USE_MYSQL=no -USE_PGSQL=no - -dnl Status data -AC_DEFINE_UNQUOTED(USE_XSDDEFAULT,,[use default routines (in xdata/xsddefault.*) for status data I/O...]) -XSDC="xsddefault.c" -XSDH="xsddefault.h" -XSDCOMMENT="Default (text file)" -echo "We'll use default routines (in xdata/xsddefault.*) for status data I/O..." -AC_SUBST(XSDC) -AC_SUBST(XSDH) - - -dnl Comment data -AC_DEFINE_UNQUOTED(USE_XCDDEFAULT,,[use default routines (in xdata/xcddefault.*) for comment data I/O...]) -XCDC="xcddefault.c" -XCDH="xcddefault.h" -XCDCOMMENT="Default (text file)" -echo "We'll use default routines (in xdata/xcddefault.*) for comment data I/O..." -AC_SUBST(XCDC) -AC_SUBST(XCDH) - - -dnl Retention data -AC_DEFINE_UNQUOTED(USE_XRDDEFAULT,,[use default routines (in xdata/xrddefault.*) for retention data I/O...]) -XRDC="xrddefault.c" -XRDH="xrddefault.h" -XRDCOMMENT="Default (text file)" -echo "We'll use default routines (in xdata/xrddefault.*) for retention data I/O..." -AC_SUBST(XRDC) -AC_SUBST(XRDH) - - -dnl Object data -AC_DEFINE_UNQUOTED(USE_XODTEMPLATE,,[use template-based routines (in xdata/xodtemplate.*) for object data I/O...]) -XODC="xodtemplate.c" -XODH="xodtemplate.h" -XODCOMMENT="Template-based (text file)" -echo "We'll use template-based routines (in xdata/xodtemplate.*) for object data I/O..." -AC_SUBST(XODC) -AC_SUBST(XODH) - - - -dnl Performance data -AC_DEFINE_UNQUOTED(USE_XPDDEFAULT,,[use default routines (in xdata/xpddefault.*) for performance data I/O...]) -XPDC="xpddefault.c" -XPDH="xpddefault.h" -XPDCOMMENT="Default (external commands)" -echo "We'll use default routines (in xdata/xpddefault.*) for performance data I/O..." -AC_SUBST(XPDC) -AC_SUBST(XPDH) - - -dnl Downtime data -AC_DEFINE_UNQUOTED(USE_XDDDEFAULT,,[use default routines (in xdata/xdddefault.*) for scheduled downtime data I/O...]) -XDDC="xdddefault.c" -XDDH="xdddefault.h" -XDDCOMMENT="Default (text file)" -echo "We'll use default routines (in xdata/xdddefault.*) for scheduled downtime data I/O..." -AC_SUBST(XDDC) -AC_SUBST(XDDH) +AC_ARG_WITH(iobroker, + AC_HELP_STRING([--with-iobroker=], + [specify the method to use with iobroker: epoll, poll, or select]), + IOBROKER_METHOD=$withval, + IOBROKER_METHOD="none" +) +case $IOBROKER_METHOD in +epoll*) + if test $GLIBC_NEWER_2_4 -eq 1 -a x$ac_cv_header_sys_epoll_h = xyes ; then + AC_DEFINE([IOBROKER_USES_EPOLL]) + else + echo "\"epoll\" is not available as an iobroker method." + echo "Please use one of the other options." + exit 1 + fi + ;; +poll*) + if test x$ac_cv_header_sys_poll_h = xyes -o x$ac_cv_header_poll_h = xyes ; then + AC_DEFINE([IOBROKER_USES_POLL]) + else + echo "\"poll\" is not available as an iobroker method." + echo "Please use one of the other options." + exit 1 + fi + ;; +select*) + if test x$ac_cv_header_sys_select_h = xyes ; then + AC_DEFINE([IOBROKER_USES_SELECT]) + else + echo "\"select\" is not available as an iobroker method." + echo "Please use one of the other options." + exit 1 + fi + ;; +none*) + if test $GLIBC_NEWER_2_4 -eq 1 -a x$ac_cv_header_sys_epoll_h = xyes ; then + AC_DEFINE([IOBROKER_USES_EPOLL]) + IOBROKER_METHOD="epoll" + elif test x$ac_cv_header_sys_poll_h = xyes -o x$ac_cv_header_poll_h = xyes ; then + AC_DEFINE([IOBROKER_USES_POLL]) + IOBROKER_METHOD="poll" + elif test x$ac_cv_header_sys_select_h = xyes ; then + AC_DEFINE([IOBROKER_USES_SELECT]) + IOBROKER_METHOD="select" + else + echo "There are no available options for iobroker polling" + exit 1 + fi + ;; +*) + echo "\"$IOBROKER_METHOD\" is not a valid method for --with-iobroker" + exit 1 + ;; +esac dnl Optional GD library and include paths -AC_ARG_WITH(gd-lib,--with-gd-lib=DIR sets location of the gd library,[ - LDFLAGS="${LDFLAGS} -L${withval}" - LD_RUN_PATH="${withval}${LD_RUN_PATH:+:}${LD_RUN_PATH}" - ]) -AC_ARG_WITH(gd-inc,--with-gd-inc=DIR sets location of the gd include files,[ - CFLAGS="${CFLAGS} -I${withval}" - ]) +AC_ARG_WITH(gd-lib, + AC_HELP_STRING([--with-gd-lib=DIR],[sets location of the gd library]), + [ + LDFLAGS="${LDFLAGS} -L${withval}" + LD_RUN_PATH="${withval}${LD_RUN_PATH:+:}${LD_RUN_PATH}" + ] +) +AC_ARG_WITH(gd-inc, + AC_HELP_STRING([--with-gd-inc=DIR],[sets location of the gd include files]), + [CFLAGS="${CFLAGS} -I${withval}"] +) TRYGD=yep +dnl 'corewindow' is now disabled. Allow it to be enabled if someone wants it +COREWINDOW=no +AC_ARG_ENABLE(corewindow, + AC_HELP_STRING([--enable-corewindow], + [enables the 'corewindow' URL argument]), + COREWINDOW=yes +) +AC_SUBST(COREWINDOW) + dnl statusmap CGI enabled by default, unless users chooses not to use it TRYSTATUSMAP=yep -AC_ARG_ENABLE(statusmap,--disable-statusmap=disables compilation of statusmap CGI,TRYSTATUSMAP=nope) +AC_ARG_ENABLE(statusmap, + AC_HELP_STRING([--disable-statusmap], + [disables compilation of statusmap CGI]), + TRYSTATUSMAP=nope +) dnl statuswrl CGI enabled by default, unless users chooses not to use it TRYSTATUSWRL=yep -AC_ARG_ENABLE(statuswrl,--disable-statuswrl=disables compilation of statuswrl (VRML) CGI,TRYSTATUSWRL=nope) +AC_ARG_ENABLE(statuswrl, + AC_HELP_STRING([--disable-statuswrl], + [disables compilation of statuswrl (VRML) CGI]), + TRYSTATUSWRL=nope +) if test x$TRYSTATUSWRL = xyep; then AC_DEFINE_UNQUOTED(USE_STATUSWRL,,[statuswrl CGI enabled by default, unless users chooses not to use it]) @@ -527,19 +550,39 @@ if test x$TRYGD = xyep; then fi fi -AC_ARG_WITH(cgiurl,--with-cgiurl= sets URL for cgi programs (do not use a trailing slash),cgiurl=$withval,cgiurl=/nagios/cgi-bin) -AC_ARG_WITH(htmurl,--with-htmurl= sets URL for public html,htmurl=$withval,htmurl=/nagios) +AC_ARG_WITH(cgiurl, + AC_HELP_STRING([--with-cgiurl=], + [sets URL for cgi programs (do not use a trailing slash)]), + cgiurl=$withval, + cgiurl=/nagios/cgi-bin +) +AC_ARG_WITH(htmurl, + AC_HELP_STRING([--with-htmurl=], + [sets URL for public html]), + htmurl=$withval, + htmurl=/nagios +) AC_SUBST(htmurl) AC_SUBST(cgiurl) USE_NANOSLEEP=yes -AC_ARG_ENABLE(nanosleep,--enable-nanosleep enables use of nanosleep (instead of sleep) in event timing,USE_NANOSLEEP=$enableval,USE_NANOSLEEP=yes) +AC_ARG_ENABLE(nanosleep, + AC_HELP_STRING([--enable-nanosleep], + [enables use of nanosleep (instead of sleep) in event timing]), + USE_NANOSLEEP=$enableval, + USE_NANOSLEEP=yes +) if test x$USE_NANOSLEEP = xyes; then AC_DEFINE_UNQUOTED(USE_NANOSLEEP,,[enables use of nanosleep (instead of sleep)]) fi USE_EVENTBROKER=yes -AC_ARG_ENABLE(event-broker,--enable-event-broker enables integration of event broker routines,USE_EVENTBROKER=$enableval,USE_EVENTBROKER=yes) +AC_ARG_ENABLE(event-broker, + AC_HELP_STRING([--enable-event-broker], + [enables integration of event broker routines]), + USE_EVENTBROKER=$enableval, + USE_EVENTBROKER=yes +) BROKER_LDFLAGS="" BROKERLIBS=""; @@ -605,6 +648,7 @@ if test x$USE_EVENTBROKER = xyes; then case $host_os in solaris2*|sysv4*) MOD_LDFLAGS="-G" + MOD_CFLAGS="-fPIC" ;; aix4*|aix5*) #MOD_LDFLAGS="-G -bnoentry -bexpall" @@ -625,7 +669,7 @@ if test x$USE_EVENTBROKER = xyes; then MOD_LDFLAGS="-shared" MOD_CFLAGS="-fPIC" ;; - freebsd*) + *bsd*) MOD_LDFLAGS="-shared" MOD_CFLAGS="-fPIC" ;; @@ -638,6 +682,11 @@ if test x$USE_EVENTBROKER = xyes; then AC_SUBST(MOD_CFLAGS) AC_SUBST(MOD_LDFLAGS) + dnl - flags for compiling workers + WORKER_CFLAGS="-I ../../include -I ../.." + WORKER_LDFLAGS="-L ../../lib -l nagios" + AC_SUBST(WORKER_CFLAGS) + AC_SUBST(WORKER_LDFLAGS) AC_DEFINE_UNQUOTED(USE_EVENT_BROKER,,[defined to bring in the event broker objects]) BROKER_O="broker.o nebmods.o" @@ -647,65 +696,15 @@ if test x$USE_EVENTBROKER = xyes; then fi -USEPERL=no; -INSTALLPERLSTUFF=no; -AC_ARG_ENABLE(embedded-perl,--enable-embedded-perl will enable embedded Perl interpreter,[ - USEPERL=$enableval - ] - ,USEPERL=no) - -PERLCACHE=yes; -AC_ARG_WITH(perlcache,--with-perlcache turns on cacheing of internally compiled Perl scripts,[ - PERLCACHE=$withval - ] - ,[ - AC_DEFINE(DO_CLEAN,"1",[whether to clean cached compiled perl]) - PERLCACHE=yes; - ]) - -dnl Is embedded Perl being compiled in? -if test x$USEPERL = xyes; then - - AC_DEFINE_UNQUOTED(EMBEDDEDPERL,,[Is embedded Perl being compiled in?]) - PERLLIBS="`perl -MExtUtils::Embed -e ldopts`" - PERLDIR="`perl -MConfig -e 'print $Config{installsitearch}'`" - CFLAGS="${CFLAGS} `perl -MExtUtils::Embed -e ccopts`" - USEPERL=yes - INSTALLPERLSTUFF=yes; - PERLXSI_O=perlxsi.o - OBJS="${OBJS} ${PERLXSI_O}" - echo "creating base/perlxsi.c" - perl -MExtUtils::Embed -e xsinit -- -o base/perlxsi.c - - echo "Embedded Perl interpreter will be compiled in..." - - dnl Is caching enabled? - if test x$PERLCACHE = xyes; then - AC_DEFINE(DO_CLEAN,"0",[whether to clean cached compiled perl]) - PERLCACHE=yes; - echo "Internally compiled Perl scripts will be cached..." - else - AC_DEFINE(DO_CLEAN,"1",[whether to clean cached compiled perl]) - echo "Internally compiled Perl scripts will NOT be cached..." - fi -fi - -dnl Test if we're using threaded Perl (patch by Chip Ach) -if test x$USEPERL = xyes; then - if (perl -e 'use Config;exit -1 unless ($Config{'usethreads'});'); then - echo "Using threaded perl" - AC_DEFINE_UNQUOTED(THREADEDPERL,,[defined if we're using threaded Perl]) - fi -fi - - dnl Option for compiling under CYGWIN nagios_name=nagios nagiostats_name=nagiostats cygwin=no -AC_ARG_ENABLE(cygwin,--enable-cygwin enables building under the CYGWIN environment,[ - cygwin=$enableval - ]) +AC_ARG_ENABLE(cygwin, + AC_HELP_STRING([--enable-cygwin], + [enables building under the CYGWIN environment]), + [cygwin=$enableval] +) if test x$cygwin = xyes; then CFLAGS="${CFLAGS} -DCYGWIN" nagios_name=nagios.exe; @@ -781,17 +780,21 @@ fi AC_SUBST(USE_LIBTAP) AC_SUBST(CGIEXTRAS) AC_SUBST(GDLIBS) -AC_SUBST(PERLLIBS) -AC_SUBST(PERLDIR) -AC_SUBST(PERLXSI_O) AC_SUBST(BASEEXTRALIBS) AC_SUBST(INITDIR) -AC_SUBST(INSTALLPERLSTUFF) AC_SUBST(USE_EVENTBROKER) AC_PATH_PROG(PERL,perl) +if test -z "$PERL"; then + AC_MSG_ERROR([Cannot continue without perl!]) +fi -AC_OUTPUT(Makefile subst pkginfo base/Makefile common/Makefile contrib/Makefile cgi/Makefile html/Makefile module/Makefile xdata/Makefile daemon-init t/Makefile t-tap/Makefile) +AC_PATH_PROG(UNZIP,unzip) +if test -z "$UNZIP"; then + AC_MSG_ERROR([Cannot continue without unzip!]) +fi + +AC_OUTPUT(Makefile lib/Makefile subst pkginfo base/Makefile common/Makefile contrib/Makefile cgi/Makefile html/Makefile module/Makefile worker/Makefile worker/ping/Makefile xdata/Makefile daemon-init t/Makefile t-tap/Makefile) perl subst include/locations.h @@ -832,27 +835,24 @@ echo " -------------------------" AC_MSG_RESULT([ Nagios executable: $nagios_name]) AC_MSG_RESULT([ Nagios user/group: $nagios_user,$nagios_grp]) AC_MSG_RESULT([ Command user/group: $command_user,$command_grp]) -if test x$USEPERL = xyes; then -if test x$PERLCACHE = xyes; then -AC_MSG_RESULT([ Embedded Perl: yes, with caching]) -else -AC_MSG_RESULT([ Embedded Perl: yes, without caching]) -fi -else -AC_MSG_RESULT([ Embedded Perl: no]) -fi if test x$USE_EVENTBROKER = xyes; then AC_MSG_RESULT([ Event Broker: yes]) else AC_MSG_RESULT([ Event Broker: no]) fi AC_MSG_RESULT([ Install \${prefix}: $prefix]) +incdir=`eval echo $includedir` +if test x$incdir = x$prefix/include; then + includedir=$prefix/include/nagios +fi +AC_MSG_RESULT([ Install \${includedir}: $includedir]) AC_MSG_RESULT([ Lock file: $lockfile]) AC_MSG_RESULT([ Check result directory: $CHECKRESULTDIR]) AC_MSG_RESULT([ Init directory: $init_dir]) AC_MSG_RESULT([ Apache conf.d directory: $HTTPD_CONF]) AC_MSG_RESULT([ Mail program: $MAIL_PROG]) AC_MSG_RESULT([ Host OS: $host_os]) +AC_MSG_RESULT([ IOBroker Method: $IOBROKER_METHOD]) echo "" echo " Web Interface Options:" @@ -862,19 +862,8 @@ AC_MSG_RESULT([ HTML URL: http://localhost$htmurl/]) AC_MSG_RESULT([ CGI URL: http://localhost$cgiurl/]) AC_MSG_RESULT([ Traceroute (used by WAP): $PATH_TO_TRACEROUTE]) -dnl echo "" -dnl echo " External Data Routines:" -dnl echo " ------------------------" - -dnl AC_MSG_RESULT([ Status data: $XSDCOMMENT]) -dnl AC_MSG_RESULT([ Comment data: $XCDCOMMENT]) -dnl AC_MSG_RESULT([ Downtime data: $XDDCOMMENT]) -dnl AC_MSG_RESULT([ Peformance data: $XPDCOMMENT]) - - echo "" echo "" echo "Review the options above for accuracy. If they look okay," echo "type 'make all' to compile the main program and CGIs." echo "" - diff --git a/contrib/.gitignore b/contrib/.gitignore index 4f1e93a..593aa77 100644 --- a/contrib/.gitignore +++ b/contrib/.gitignore @@ -1,2 +1,4 @@ -perlxsi.c Makefile +convertcfg +daemon-chk.cgi +nagios-worker diff --git a/contrib/Makefile.in b/contrib/Makefile.in index addf145..9a4661e 100644 --- a/contrib/Makefile.in +++ b/contrib/Makefile.in @@ -5,13 +5,14 @@ ############################### CC=@CC@ -CFLAGS=@CFLAGS@ @DEFS@ +CFLAGS=-I.. @CFLAGS@ @DEFS@ LDFLAGS=@LDFLAGS@ @LIBS@ # Source code directories SRC_INCLUDE=../include SRC_COMMON=../common SRC_CGI=../cgi +SRC_LIB=../lib # Generated automatically from configure script SNPRINTF_O=@SNPRINTF_O@ @@ -25,7 +26,7 @@ CGIDIR=@sbindir@ BINDIR=@bindir@ CGIS=traceroute.cgi daemonchk.cgi -UTILS=mini_epn new_mini_epn convertcfg +UTILS=convertcfg ALL=$(CGIS) $(UTILS) @@ -40,10 +41,11 @@ COMMON_H=$(SRC_INCLUDE)/config.h $(SRC_INCLUDE)/common.h $(SRC_INCLUDE)/location all: $(ALL) clean: - rm -f convertcfg daemonchk.cgi mini_epn new_mini_epn core *.o + rm -f convertcfg daemonchk.cgi core *.o rm -f */*/*~ rm -f */*~ rm -f *~ + rm -rf rpmbuild *.rpm distclean: clean rm -f Makefile @@ -59,23 +61,17 @@ install: ############################################################################## # rules and dependencies for actual target programs -daemonchk.cgi: daemonchk.o $(CGI_O) $(CGI_H) $(COMMON_H) - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(CGI_O) +$(SRC_LIB)/libnagios.a: + make -C $(SRC_LIB) libnagios.a + +daemonchk.cgi: daemonchk.o $(CGI_O) $(CGI_H) $(COMMON_H) $(SRC_LIB)/libnagios.a + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(CGI_O) $(SRC_LIB)/libnagios.a daemonchk.o: daemonchk.c - $(CC) $(CLFAGS) -c -o $@ $< -I$(SRC_INCLUDE) + $(CC) $(CFLAGS) -c -o $@ $< -I$(SRC_INCLUDE) -mini_epn: mini_epn.c - perl -MExtUtils::Embed -e xsinit - $(CC) $(CFLAGS) -c perlxsi.c `perl -MExtUtils::Embed -e ccopts` - $(CC) $(CFLAGS) -c mini_epn.c `perl -MExtUtils::Embed -e ccopts` - $(CC) $(CFLAGS) $(LDFLAGS) perlxsi.o mini_epn.o `perl -MExtUtils::Embed -e ccopts -e ldopts` -o $@ - -new_mini_epn: new_mini_epn.c - perl -MExtUtils::Embed -e xsinit - $(CC) $(CFLAGS) -c perlxsi.c `perl -MExtUtils::Embed -e ccopts` - $(CC) $(CFLAGS) -c new_mini_epn.c `perl -MExtUtils::Embed -e ccopts` - $(CC) $(CFLAGS) $(LDFLAGS) perlxsi.o new_mini_epn.o `perl -MExtUtils::Embed -e ccopts -e ldopts` -o $@ +nagios-worker: nagios-worker.c + $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) $(LIBS) $(SRC_LIB)/libnagios.a ############################################################################## # dependencies @@ -88,3 +84,31 @@ $(CGI_O): $(CGI_C) %.cgi : %.c $(CC) $(CFLAGS) $(LDFLAGS) $< $(CGI_O) -o $@ + +############################################################################## +# rpm making automation for CentOS/RHEL. + +ARCH ?= $(shell arch) +ifeq ($(ARCH),x86_64) +RPM_ARCH := x86_64 +else + ifeq ($(ARCH),i686) +RPM_ARCH := i386 + else +$(error Unknown arch "$(ARCH)".) + endif +endif + +rpm: + # create nagios tar ball. + @(cd ..;rm -f nagios-@VERSION@) + @(cd ..;ln -s . nagios-@VERSION@) + @(cd ..;tar zhcf nagios-@VERSION@.tar.gz --exclude nagios-@VERSION@/nagios-@VERSION@.tar.gz --exclude nagios-@VERSION@/nagios-@VERSION@ --exclude RCS --exclude CVS --exclude build-* --exclude *~ --exclude .git* nagios-@VERSION@/) + @(cd ..;rm -f nagios-@VERSION@) + # build the rpm using rpmbuild from ./rmbuild as topdir + @rm -rf rpmbuild && mkdir -p rpmbuild/SOURCES + @cp ../nagios-@VERSION@.tar.gz rpmbuild/SOURCES/nagios-@VERSION@.tar.gz + @rpmbuild -ba --define "_topdir ${PWD}/rpmbuild" ../nagios.spec + @mv rpmbuild/RPMS/$(RPM_ARCH)/*.rpm . + @ls -l *.rpm + diff --git a/contrib/README b/contrib/README index fac2630..bd6e2be 100644 --- a/contrib/README +++ b/contrib/README @@ -22,7 +22,7 @@ Additional CGIs: ---------------- - traceroute.cgi is (surprise) a CGI that allows you to do a traceroute - to a specific IP address. Simply do a 'chmod +x' to make it executeable + to a specific IP address. Simply do a 'chmod +x' to make it executable and place it in the CGI directory (i.e. /usr/local/nagios/sbin). Requires Perl. @@ -37,12 +37,7 @@ Miscellaneous Goodies: Apache to require password authentication for access to the web interface. -- mini_epn.c is a mini embedded Perl interpreter that can be used to - test the feasibility of running various Perl plugins with the - embedded Perl interpreter compiled in. - - - - - - +- Automated rpm making. + 1. ./configure # to generate contrib/Makefile + 2. cd contrib ; make rpm + 3. *.rpm will be generated in contrib directory. diff --git a/contrib/convertcfg.c b/contrib/convertcfg.c index 15bf22b..9f93a3f 100644 --- a/contrib/convertcfg.c +++ b/contrib/convertcfg.c @@ -61,7 +61,7 @@ int main(int argc, char **argv) { printf("\tcontactgroups\n"); printf("\thosts\n"); printf("\thostgroups\n"); - printf("\thostgroupescalationss\n"); + printf("\thostgroupescalations\n"); printf("\tservices\n"); printf("\tservicedependencies\n"); printf("\tserviceescalations\n"); @@ -306,7 +306,6 @@ int main(int argc, char **argv) { printf("\tnotifications_enabled\t\t1\t; Host notifications are enabled\n"); printf("\tevent_handler_enabled\t\t1\t; Host event handler is enabled\n"); printf("\tflap_detection_enabled\t\t1\t; Flap detection is enabled\n"); - /*printf("\tfailure_prediction_enabled\t1\t; Failure prediction is enabled\n");*/ printf("\tprocess_perf_data\t\t1\t; Process performance data\n"); printf("\tretain_status_information\t1\t; Retain status information across program restarts\n"); printf("\tretain_nonstatus_information\t1\t; Retain non-status information across program restarts\n"); @@ -427,7 +426,6 @@ int main(int argc, char **argv) { printf("\tnotifications_enabled\t\t1\t; Service notifications are enabled\n"); printf("\tevent_handler_enabled\t\t1\t; Service event handler is enabled\n"); printf("\tflap_detection_enabled\t\t1\t; Flap detection is enabled\n"); - /*printf("\tfailure_prediction_enabled\t1\t; Failure prediction is enabled\n");*/ printf("\tprocess_perf_data\t\t1\t; Process performance data\n"); printf("\tretain_status_information\t1\t; Retain status information across program restarts\n"); printf("\tretain_nonstatus_information\t1\t; Retain non-status information across program restarts\n"); diff --git a/contrib/daemonchk.c b/contrib/daemonchk.c index 78716e5..eedd868 100644 --- a/contrib/daemonchk.c +++ b/contrib/daemonchk.c @@ -174,7 +174,6 @@ static int process_cgivars(void) { /* do some basic length checking on the variable identifier to prevent buffer overflows */ if(strlen(variables[x]) >= MAX_INPUT_BUFFER - 1) { - x++; continue; } } @@ -191,7 +190,7 @@ static void get_expire_time_string(time_t *raw_time, char *buffer, int buffer_le int second; int year; char *weekdays[7] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; - char *months[12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sept", "Oct", "Nov", "Dec"}; + char *months[12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; if(raw_time == NULL) time(&t); diff --git a/contrib/epn_nagios.h b/contrib/epn_nagios.h deleted file mode 100644 index fea7cad..0000000 --- a/contrib/epn_nagios.h +++ /dev/null @@ -1,26 +0,0 @@ -/******** BEGIN EMBEDDED PERL INTERPRETER DECLARATIONS ********/ - -#include -#include - -#include -#undef ctime /* don't need perl's threaded version */ -#undef printf /* can't use perl's printf until initialized */ - -/* In perl.h (or friends) there is a macro that defines sighandler as Perl_sighandler, so we must #undef it so we can use our sighandler() function */ -#undef sighandler - - -/* and we don't need perl's reentrant versions */ -#undef localtime -#undef getpwnam -#undef getgrnam -#undef strerror - -#ifdef aTHX -EXTERN_C void xs_init(pTHX); -#else -EXTERN_C void xs_init(void); -#endif - -/******** END EMBEDDED PERL INTERPRETER DECLARATIONS ********/ diff --git a/contrib/eventhandlers/distributed-monitoring/obsessive_svc_handler b/contrib/eventhandlers/distributed-monitoring/obsessive_svc_handler index ece9e99..84b3d41 100755 --- a/contrib/eventhandlers/distributed-monitoring/obsessive_svc_handler +++ b/contrib/eventhandlers/distributed-monitoring/obsessive_svc_handler @@ -1,7 +1,7 @@ #!/bin/sh # OBSESSIVE_SVC_HANDLER -# Written by Ethan Galstad (nagios@nagils.org) +# Written by Ethan Galstad (nagios@nagios.org) # Last Modified: 07-19-2001 # # This script is intended to run as the OCSP command diff --git a/contrib/exfoliation/images/logos/netbsd.gif b/contrib/exfoliation/images/logos/netbsd.gif new file mode 100644 index 0000000..fd7459b Binary files /dev/null and b/contrib/exfoliation/images/logos/netbsd.gif differ diff --git a/contrib/exfoliation/images/logos/netbsd.jpg b/contrib/exfoliation/images/logos/netbsd.jpg new file mode 100644 index 0000000..b2f0510 Binary files /dev/null and b/contrib/exfoliation/images/logos/netbsd.jpg differ diff --git a/contrib/exfoliation/images/logos/netbsd.png b/contrib/exfoliation/images/logos/netbsd.png new file mode 100644 index 0000000..11548b4 Binary files /dev/null and b/contrib/exfoliation/images/logos/netbsd.png differ diff --git a/contrib/exfoliation/images/logos/suse.gif b/contrib/exfoliation/images/logos/suse.gif new file mode 100644 index 0000000..13dc726 Binary files /dev/null and b/contrib/exfoliation/images/logos/suse.gif differ diff --git a/contrib/exfoliation/images/logos/suse.jpg b/contrib/exfoliation/images/logos/suse.jpg new file mode 100644 index 0000000..b9b8da0 Binary files /dev/null and b/contrib/exfoliation/images/logos/suse.jpg differ diff --git a/contrib/exfoliation/images/logos/suse.png b/contrib/exfoliation/images/logos/suse.png new file mode 100644 index 0000000..50534c2 Binary files /dev/null and b/contrib/exfoliation/images/logos/suse.png differ diff --git a/contrib/exfoliation/readme.txt b/contrib/exfoliation/readme.txt index fa9ae54..bcd1118 100644 --- a/contrib/exfoliation/readme.txt +++ b/contrib/exfoliation/readme.txt @@ -11,7 +11,7 @@ those from this tarball. For example: cd /opt/nagios/share tar xvfz exfoliation.tgz -On debian/unbuntu installations you might have to modify side.html to include +On debian/ubuntu installations you might have to modify side.html to include the common.css stylesheet by adding a line like this in the head section: diff --git a/contrib/exfoliation/stylesheets/common.css b/contrib/exfoliation/stylesheets/common.css index 6d8e1aa..ace7df0 100644 --- a/contrib/exfoliation/stylesheets/common.css +++ b/contrib/exfoliation/stylesheets/common.css @@ -96,6 +96,7 @@ div.navsectiontitle { background-color: #efefef; border:1px solid #dddddd; } + div.navsectionlinks { margin: 3px 0 0 0; } @@ -105,14 +106,14 @@ ul.navsectionlinks { padding: 0; list-style: none; } -ul.navsectionlinks li { } +ul.navsectionlinks li { } ul.navsectionlinks li a { font-weight: bold; font-size: 9pt; text-decoration: none; padding: 0 0 0 15px; - /* background: transparent url(../images/greendot.gif) no-repeat scroll 0 0; */ - + /* background: transparent url(../images/greendot.gif) no-repeat scroll 0 0; */ + } ul.navsectionlinks li ul { margin: 0px; @@ -121,8 +122,8 @@ ul.navsectionlinks li ul { } ul.navsectionlinks li ul li { } ul.navsectionlinks li a:hover { -/* background: transparent url(../images/orangedot.gif) no-repeat scroll 0 0; */ -color: #8391cd; +/* background: transparent url(../images/orangedot.gif) no-repeat scroll 0 0; */ +color: #8391cd; } ul.navsectionlinks li ul li a { background: none; @@ -138,6 +139,23 @@ ul.navsectionlinks li ul li ul { list-style: none; } +div.navsectionheader { + padding: 0; + margin: 0; +} +div.navsectionheader ul { + margin: 0; + padding: 0; + list-style: none; +} +div.navsectionheader ul li { + font-size: 9pt; + font-weight: bold; + padding: 0 0 0 15px; +} +div.navsectionheader ul li ul li { + font-weight: normal; +} .navbarsearch { margin: 5px 0 0 0; @@ -149,99 +167,97 @@ ul.navsectionlinks li ul li ul { .navbarsearch fieldset legend { font-size: 8pt; } -.navbarsearch input{ +.navbarsearch input { font-size: 9pt; } - -#splashpage{ + +#splashpage { text-align: center; } -#mainbrandsplash{ +#mainbrandsplash { font-size: 12pt; font-weight: bold; margin: 0 0 35px 0; } -#maincopy{ +#maincopy { margin: 0 0 15px 0; } -#currentversioninfo{ +#currentversioninfo { font-size: 12pt; } -#currentversioninfo .product{ +#currentversioninfo .product { font-size: 14pt; font-weight: bold; } -#currentversioninfo .version{ +#currentversioninfo .version { font-size: 14pt; font-weight: bold; } -#currentversioninfo .releasedate{ +#currentversioninfo .releasedate { font-size: 11pt; margin: 5px 0 0 0; } -#currentversioninfo .checkforupdates{ +#currentversioninfo .checkforupdates { font-size: 11pt; font-weight: bold; } -#currentversioninfo .whatsnew{ +#currentversioninfo .whatsnew { font-size: 11pt; font-weight: bold; margin: 50px 0 0 0; } -#updateversioninfo{ +#updateversioninfo { margin: 15px auto 35px auto; width: 400px; } -.updatechecksdisabled{ +#updateversioninfo div.submessage { + clear: left; +} +.updatechecksdisabled { background-color: #FF9F9F; border: 1px solid red; padding: 10px; } -.updatechecksdisabled div.warningmessage{ +.updatechecksdisabled div.warningmessage { font-weight: bold; } -#updateversioninfo div.submessage{ - clear: left; -} -.updateavailable{ +.updateavailable { background-color: #9FD4FF; border: 1px solid blue; padding: 10px; } -.updateavailable div.updatemessage{ +.updateavailable div.updatemessage { font-size: 12pt; font-weight: bold; } - -#splashpage #mainfooter{ - /*margin: 100px 0 0 0;*/ + +#splashpage #mainfooter { clear: both; font-size: 8pt; padding-top: 35px; + margin: auto; + width: 800px; } -#splashpage #mainfooter .disclaimer{ - /*width: 80%;*/ +#splashpage #mainfooter .disclaimer { margin: auto; } -#splashpage #mainfooter .logos{ +#splashpage #mainfooter .logos { margin: 15px 0 0 0; } - - table.infoBox { width: 100%; } td.infoBox { font-size: 8pt; padding: 0 0 1em 0; white-space: nowrap; } div.infoBoxTitle { font-size: 10pt; font-weight: bold; } div.infoBoxBadProcStatus { font-size: 8pt; font-weight: bold; color: red; } -.linkBox { font-size: 8pt; padding: 1; } +.linkBox { font-size: 8pt; padding: 1px; } table.linkBox td { white-space: nowrap; } -.filter { font-size: 8pt; padding: 1; } +.filter { font-size: 8pt; padding: 1px; } .filterTitle { font-size: 9pt; font-weight: bold; } .filterName { font-size: 8pt; text-align: right; font-weight: bold; } .filterValue { font-size: 8pt; } @@ -255,19 +271,19 @@ table.linkBox td { white-space: nowrap; } table.data { padding: 0; } th.data { font-size: 9pt; text-align: left; padding: 0 3px 0 3px; border-bottom: 1px solid #777777; color: #333333; } -.dataOdd { font-size: 8pt; background-color: #e7e7e7; padding: 0 4 0 4; } -.dataEven { font-size: 8pt; background-color: #f4f2f2; padding: 0 4 0 4; } +.dataOdd { font-size: 8pt; background-color: #e7e7e7; padding: 0px 4px 0px 4px; } +.dataEven { font-size: 8pt; background-color: #f4f2f2; padding: 0px 4px 0px 4px; } .dataTitle { font-size: 12pt; text-align: center; font-weight: bold; } .dataSubTitle { font-size: 10pt; text-align: center; font-weight: bold; } -.optBox { font-size: 9pt; white-space: nowrap; padding: 2 0 0 0; } +.optBox { font-size: 9pt; white-space: nowrap; padding: 2px 0px 0px 0px; } .optBoxTitle { font-size: 10pt; font-weight: bold; text-align: center; } -.optBoxRequiredItem { font-size: 9pt; text-align: right; padding: 0 5 0 5; color: red; } -.optBoxItem { font-size: 9pt; text-align: right; padding: 0 5 0 5; } +.optBoxRequiredItem { font-size: 9pt; text-align: right; padding: 0px 5px 0px 5px; color: red; } +.optBoxItem { font-size: 9pt; text-align: right; padding: 0px 5px 0px 5px; } .optBoxValue { font-size: 9pt; } .optionBoxTitle { font-size: 10pt; text-align: center; font-weight: bold; } -.optionBox { font-size: 10pt; padding: 2; } +.optionBox { font-size: 10pt; padding: 2px; } .navBoxTitle { font-size: 10pt; font-weight: bold; white-space: nowrap; } .navBoxItem { font-size: 8pt; } @@ -293,16 +309,16 @@ th.data { font-size: 9pt; text-align: left; padding: 0 3px 0 3px; border-b .dateSelectSubTitle { font-size: 9pt; text-align: right; } .dateSelectItem { font-size: 9pt; } -.popupText { font-size: 8pt; background-color: #eeeeaa; border: 1px solid #777777; padding: 10 10 10 10; } +.popupText { font-size: 8pt; background-color: #eeeeaa; border: 1px solid #777777; padding: 10px 10px 10px 10px; } -.hostImportantProblem { font-size: 8pt; background-color: #88aadd; border: 1px solid #aaaaaa; padding: 0 5 0 5; } -.hostUnimportantProblem { font-size: 8pt; background-color: #aaccff; border: 1px solid #888888; padding: 0 5 0 5; } +.hostImportantProblem { font-size: 8pt; background-color: #88aadd; border: 1px solid #aaaaaa; padding: 0px 5px 0px 5px; } +.hostUnimportantProblem { font-size: 8pt; background-color: #aaccff; border: 1px solid #888888; padding: 0px 5px 0px 5px; } -.serviceImportantProblem { font-size: 8pt; background-color: #88aadd; border: 1px solid #aaaaaa; padding: 0 5 0 5; } -.serviceUnimportantProblem { font-size: 8pt; background-color: #aaccff; border: 1px solid #888888; padding: 0 5 0 5; } +.serviceImportantProblem { font-size: 8pt; background-color: #88aadd; border: 1px solid #aaaaaa; padding: 0px 5px 0px 5px; } +.serviceUnimportantProblem { font-size: 8pt; background-color: #aaccff; border: 1px solid #888888; padding: 0px 5px 0px 5px; } -.outageImportantProblem { font-size: 8pt; background-color: #88aadd; border: 1px solid #aaaaaa; padding: 0 5 0 5; } -.outageUnimportantProblem { font-size: 8pt; background-color: #aaccff; border: 1px solid #888888; padding: 0 5 0 5; } +.outageImportantProblem { font-size: 8pt; background-color: #88aadd; border: 1px solid #aaaaaa; padding: 0px 5px 0px 5px; } +.outageUnimportantProblem { font-size: 8pt; background-color: #aaccff; border: 1px solid #888888; padding: 0px 5px 0px 5px; } /* Some nagios configurations have side.html rather than side.php and define */ @@ -313,7 +329,7 @@ th.data { font-size: 9pt; text-align: left; padding: 0 3px 0 3px; border-b margin: 5px 0 10px 0; padding: 2px; background-color: #efefef; - border:v1px solid #dddddd; + border: 1px solid #dddddd; } .NavBarItem { @@ -330,41 +346,56 @@ th.data { font-size: 9pt; text-align: left; padding: 0 3px 0 3px; border-b } - + #splashboxes { - /*border: 1px solid blue;*/ - margin: auto; - width: 90%; - } -.splashbox{ - padding: 5px; - margin: 5px 5px 5px; - border: 1px solid #AAAAAA; - float: left; - text-align: left; - height: 140px; - } -.splashbox h2{ - margin: 0px; - font-size: 12pt; - } -.splashbox ul{ - margin: 0; - padding: 5px 5px 5px 15px; - } -.splashbox ul li{ - clear: both; - } -#splashbox1 { - width: 250px; - } -#splashbox2 { - width: 500px; - } + margin: auto; + width: 794px; +} + +.splashbox { + padding: 5px; + margin: 5px; + border: 1px solid #AAAAAA; + float: left; + text-align: left; + height: 140px; +} +.splashbox h2 { + margin: 0; + font-size: 12pt; +} +.splashbox ul { + margin: 0; + padding: 5px 5px 5px 15px; +} +.splashbox ul li { + clear: both; +} + +.splashbox-media { + margin: 5px; +} +.splashbox3-empty { + margin: 5px; + border: 1px solid #AAAAAA; + width: 238px; + height: 150px; +} +.splashbox3-full { + margin: 5px; + width: 240px; + height: 152px; +} +.splashbox-clear { + clear: both; +} + +#splashbox1, #splashbox2, #splashbox4 { + width: 250px; +} #splashbox3 { - width: 250px; - clear: both; - } -#splashbox4 { - width: 500px; - } \ No newline at end of file + float: left; +} +#splashbox5 { + width: 500px; +} diff --git a/contrib/exfoliation/stylesheets/notifications.css b/contrib/exfoliation/stylesheets/notifications.css index 1138025..c2ae4bf 100644 --- a/contrib/exfoliation/stylesheets/notifications.css +++ b/contrib/exfoliation/stylesheets/notifications.css @@ -19,6 +19,7 @@ TH.notifications { font-size: 9pt; text-align: left; padding: 0 3px 0 3px; bo .notificationsCRITICAL { background-color: #f88888; border: 1px solid #777777; padding: 0 4 0 4; } .notificationsACKNOWLEDGEMENT { background-color: #aaaaaa; border: 1px solid #777777; padding: 0 4 0 4; } .notificationsCUSTOM { background-color: #778899; border: 1px solid #777777; padding: 0 4 0 4; } +.notificationsDOWNTIME { background-color: #aaccff; border: 1px solid #777777; padding: 0 4 0 4; } /* these are dark colors */ .notificationsHOSTUP { background-color: #88d066; border: 1px solid #777777; padding: 0 4 0 4; } @@ -26,4 +27,5 @@ TH.notifications { font-size: 9pt; text-align: left; padding: 0 3px 0 3px; bo .notificationsHOSTUNREACHABLE { background-color: #ffbb55; border: 1px solid #777777; padding: 0 4 0 4; } .notificationsHOSTACKNOWLEDGEMENT { background-color: #aaaaaa; border: 1px solid #777777; padding: 0 4 0 4; } .notificationsHOSTCUSTOM { background-color: #778899; border: 1px solid #777777; padding: 0 4 0 4; } +.notificationsHOSTDOWNTIME { background-color: #aaccff; border: 1px solid #777777; padding: 0 4 0 4; } diff --git a/contrib/mini_epn.c b/contrib/mini_epn.c deleted file mode 100644 index 83c5cb3..0000000 --- a/contrib/mini_epn.c +++ /dev/null @@ -1,122 +0,0 @@ -/* - mini_epn.c - -*/ - -#include -#include -#include "epn_nagios.h" - -#define MAX_INPUT_CHARS 1024 - -static PerlInterpreter *my_perl = NULL; - -int main(int argc, char **argv, char **env) { - - /* - #ifdef aTHX - dTHX; - #endif - */ - - char *embedding[] = { "", "p1.pl" }; - char *plugin_output ; - char fname[MAX_INPUT_CHARS]; - char *args[] = {"", "0", "", "", NULL }; - char command_line[MAX_INPUT_CHARS]; - int exitstatus; - int pclose_result; - - if((my_perl = perl_alloc()) == NULL) { - printf("%s\n", "Error: Could not allocate memory for embedded Perl interpreter!"); - exit(1); - } - perl_construct(my_perl); - exitstatus = perl_parse(my_perl, xs_init, 2, embedding, NULL); - if(!exitstatus) { - - exitstatus = perl_run(my_perl); - - while(printf("Enter file name: ") && fgets(command_line, MAX_INPUT_CHARS - 1, stdin)) { - SV *plugin_hndlr_cr; - STRLEN n_a; - int count = 0 ; - - dSP; - - command_line[strlen(command_line) - 1] = '\0'; - - strncpy(fname, command_line, strcspn(command_line, " ")); - fname[strcspn(command_line, " ")] = '\x0'; - args[0] = fname ; - args[3] = command_line + strlen(fname) + 1 ; - - args[2] = ""; - - /* call our perl interpreter to compile and optionally cache the command */ - - ENTER; - SAVETMPS; - PUSHMARK(SP); - - XPUSHs(sv_2mortal(newSVpv(args[0], 0))); - XPUSHs(sv_2mortal(newSVpv(args[1], 0))); - XPUSHs(sv_2mortal(newSVpv(args[2], 0))); - XPUSHs(sv_2mortal(newSVpv(args[3], 0))); - - PUTBACK; - - count = call_pv("Embed::Persistent::eval_file", G_SCALAR | G_EVAL); - - SPAGAIN; - - /* check return status */ - if(SvTRUE(ERRSV)) { - (void) POPs; - - pclose_result = -2; - printf("embedded perl ran %s with error %s\n", fname, SvPVX(ERRSV)); - continue; - } - else { - plugin_hndlr_cr = newSVsv(POPs); - - PUTBACK; - FREETMPS; - LEAVE; - } - - ENTER; - SAVETMPS; - PUSHMARK(SP); - - XPUSHs(sv_2mortal(newSVpv(args[0], 0))); - XPUSHs(sv_2mortal(newSVpv(args[1], 0))); - XPUSHs(plugin_hndlr_cr); - XPUSHs(sv_2mortal(newSVpv(args[3], 0))); - - PUTBACK; - - count = perl_call_pv("Embed::Persistent::run_package", G_EVAL | G_ARRAY); - - SPAGAIN; - - plugin_output = POPpx ; - pclose_result = POPi ; - - printf("embedded perl plugin return code and output was: %d & '%s'\n", pclose_result, plugin_output); - - PUTBACK; - FREETMPS; - LEAVE; - - } - - } - - - PL_perl_destruct_level = 0; - perl_destruct(my_perl); - perl_free(my_perl); - exit(exitstatus); - } diff --git a/contrib/nagios-qh.rb b/contrib/nagios-qh.rb new file mode 100755 index 0000000..c2d2f7a --- /dev/null +++ b/contrib/nagios-qh.rb @@ -0,0 +1,139 @@ +#!/usr/bin/env ruby + +# Simple interface to interact with the Query Handler +# Daniel Wittenberg + +require "socket" +require 'optparse' + +$DEBUG="false" +$DEBUGLOG="" + +def debug(msg) + if($DEBUG == "true") + if($DEBUGLOG != "") + File.open("#{$DEBUGLOG}",'a') {|f| f.puts("DEBUG: #{msg}")} + else + puts("DEBUG: #{msg}") + end + end +end + +def send_cmd(cmd, mysock) + mysock="/var/nagios/rw/nagios.qh" if mysock.nil? + cmd=cmd.chomp + debug("Starting send_cmd with command: #{cmd}") + + if(cmd == "quit" or cmd == "exit") + exit(0) + end + + # If we forget to start with a command type assume # + if(! cmd.start_with?('#') and ! cmd.start_with?('@')) + cmd = "##{cmd}" + end + + # Cleanup the space if they forget you can't have one + cmd.gsub!(/^#\s+/,"#") + cmd.gsub!(/^@\s+/,"@") + + # If no socket we might as well bail + if(! File.socket?(mysock)) + puts "Not a socket (#{mysock}) sucker!" + exit(1) + end + + debug("Writing command to socket: #{cmd}") + # open socket and lets get to work! + UNIXSocket.open("#{mysock}") do |socket| + cmd=cmd + '' + socket.send("#{cmd}\000", 0) + socket.flush + while line = socket.gets # Read lines from the socket + puts line.chop # And print with platform line terminator + end + if(! cmd.start_with?('#')) + socket.close + puts "" + end + end +end + +def print_usage() + puts " +Simple command-line interface to Nagios Query Handler + + -h, --help Show this help message. + + -d, --debug Turn on debug mode + + -s, --socket Specify the query handler socket + (default: /var/nagios/rw/nagios.qh) + + -c, --cmd Run a specific command and exit + " + exit +end + +####################################### +# __ __ _____ _ _ +# | \/ | /\ |_ _| \ | | +# | \ / | / \ | | | \| | +# | |\/| | / /\ \ | | | . ` | +# | | | |/ ____ \ _| |_| |\ | +# |_| |_/_/ \_\_____|_| \_| +# +####################################### + +options = {} +optparse = OptionParser.new do |opts| + opts.banner = "Usage: $0 [options]" + + opts.on('-d','--debug','Debugging mode on') do + options[:debug] = true + $DEBUG="true" + end + opts.on('-h','--help','Help') do + print_usage() + end + opts.on('-s','--socket [socket]','Query Handler Socket') do |socket| + options[:socket] = socket + end + opts.on('-c','--command command','Command') do|command| + options[:cmd] = command + end +end + +optparse.parse! + +# If debug mode let's print our options so we confirm what our input was +options.each do |o,v| + debug("#{o}=#{v}") +end + +if(options[:cmd]) + send_cmd("##{options[:cmd]}", options[:socket]) + exit + puts "Command not specified" + print_usage() +end + +puts "Welcome to Nagios Query handler, here's a list of handlers available:" +puts "" + +# We'll give the users a nudge to know what to type next +send_cmd("#help list", options[:socket]) + +puts "use @ for running queries such as '@nerd subscribe servicechecks'" +puts "" +puts "quit or exit will quit interactive mode" + +puts "" + +STDOUT.sync = true +print("qh> ") +while input = STDIN.gets + send_cmd(input, options[:socket]) + STDOUT.sync = true + print("qh> ") +end diff --git a/contrib/nagios-worker.c b/contrib/nagios-worker.c new file mode 100644 index 0000000..6cab57e --- /dev/null +++ b/contrib/nagios-worker.c @@ -0,0 +1,92 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include + +#include "../lib/snprintf.h" +#include "../lib/nsock.h" +#include "../lib/worker.h" + +void usage(char *progname) +{ + printf("Usage: %s [--name ] \n", progname); +} + +int main(int argc, char *argv[]) +{ + int sd, i, ret; + char *path = NULL, *name = NULL, *cmd = NULL, response[128]; + + if (argc < 2) { + usage(argv[0]); + return 1; + } + + for (i = 1; i < argc; i++) { + char *opt, *arg = argv[i]; + if (*arg != '-') { + if (!path) { + path = arg; + continue; + } + usage(argv[0]); + } + if (!strcmp(arg, "-h") || !strcmp(arg, "--help")) { + usage(argv[0]); + return 0; + } + + if ((opt = strchr(arg, '='))) { + opt = '\0'; + opt++; + } + else if (i < argc - 1) { + opt = argv[i + 1]; + i++; + } + else { + usage(argv[0]); + return 1; + } + + if (!strcmp(arg, "--name")) { + name = opt; + } + } + + if (!path) + usage(argv[0]); + + if (!name) + name = basename(argv[0]); + + sd = nsock_unix(path, NSOCK_TCP | NSOCK_CONNECT); + if (sd < 0) { + printf("Couldn't open socket: %s\n", nsock_strerror(sd)); + return 1; + } + + nsock_printf_nul(sd, "@wproc register name=%s\n", name); + + /* + * we read only 3 bytes here, as we don't want to read any + * commands from Nagios before we've entered the worker loop + */ + ret = read(sd, response, 3); + if (ret <= 0) { + printf("Failed to read response: %s\n", strerror(errno)); + return 1; + } + if (ret == 3 && !memcmp(response, "OK", 3)) + printf("Connected. Wahoo\n"); + else { + ret = read(sd, response + 3, sizeof(response) - 3); + printf("Error: %s\n", response); + return 1; + } + + enter_worker(sd, start_cmd); + return 0; +} diff --git a/contrib/new_mini_epn.c b/contrib/new_mini_epn.c deleted file mode 100644 index 51a8f49..0000000 --- a/contrib/new_mini_epn.c +++ /dev/null @@ -1,255 +0,0 @@ -/* - new_mini_epn.c - -*/ - -#include -#include -#include "epn_nagios.h" - -/* - * DO_CLEAN must be a pointer to a char string - */ - -#define DO_CLEAN "0" - -static PerlInterpreter *my_perl = NULL; - -/* - * <=== Align Right - * 56 spaces from left margin - * Do N O T use T A B S in #define code. - * - * Indent level == 4 spaces - */ - -#define DO_READLINE \ - "$_ = defined($term) " \ - " ? $term->readline($prompt) " \ - " : do { " \ - " print $prompt; " \ - " chomp($_ = <>); " \ - " $_; " \ - " }; " \ - "die qq(That's all folks.\\n) " \ - " unless $_ && ! /^\\s*$/ ; " \ - "$_; " - -#define INIT_TERM_READLINE \ - "use vars qw($term $prompt $OUT); " \ - \ - "eval { require Term::ReadLine; }; " \ - "unless ($@) { " \ - " $term = new Term::ReadLine 'new_mini_epn'; " \ - "} else { " \ - " warn qq(Install Term::ReadLine for arrow key access to history, filename completion etc.); " \ - "} " \ - \ - "$OUT = $term->OUT " \ - " if defined($term); " \ - "$prompt = 'plugin command line: '; " - -void run_plugin(char *command_line) { - -#ifdef aTHX - dTHX; -#endif - - SV *plugin_hndlr_cr ; - STRLEN n_a ; - int count = 0 ; - int pclose_result; - char *plugin_output; - char fname[128]; - char *args[] = {"", "", "", "", NULL }; - - dSP; - - strncpy(fname, command_line, strcspn(command_line, " ")); - fname[strcspn(command_line, " ")] = '\0'; - - /* - * Arguments passsed to Perl sub Embed::Persistent::run_package - */ - - /* - * filename containing plugin - */ - args[0] = fname ; - /* - * Do _not_ cache the compiled plugin - */ - args[1] = DO_CLEAN ; - /* - * pointer to plugin arguments - */ - - args[3] = command_line + strlen(fname) + 1 ; - - ENTER; - SAVETMPS; - PUSHMARK(SP); - - XPUSHs(sv_2mortal(newSVpv(args[0], 0))); - XPUSHs(sv_2mortal(newSVpv(args[1], 0))); - XPUSHs(sv_2mortal(newSVpv(args[2], 0))); - XPUSHs(sv_2mortal(newSVpv(args[3], 0))); - - PUTBACK; - - call_pv("Embed::Persistent::eval_file", G_SCALAR | G_EVAL); - - SPAGAIN ; - - if(SvTRUE(ERRSV)) { - (void) POPs; - - printf("embedded perl compiled plugin %s with error: %s - skipping plugin\n", fname, SvPVX(ERRSV)); - return; - } - else { - plugin_hndlr_cr = newSVsv(POPs); - - PUTBACK ; - FREETMPS ; - LEAVE ; - } - /* - * Push the arguments to Embed::Persistent::run_package onto - * the Perl stack. - */ - ENTER; - SAVETMPS; - PUSHMARK(SP); - - XPUSHs(sv_2mortal(newSVpv(args[0], 0))); - XPUSHs(sv_2mortal(newSVpv(args[1], 0))); - XPUSHs(plugin_hndlr_cr); - XPUSHs(sv_2mortal(newSVpv(args[3], 0))); - - PUTBACK; - - count = call_pv("Embed::Persistent::run_package", G_ARRAY); - - SPAGAIN; - - plugin_output = POPpx ; - pclose_result = POPi ; - - printf("embedded perl plugin return code and output was: %d & %s\n", pclose_result, plugin_output) ; - - PUTBACK; - FREETMPS; - LEAVE; - - return ; - - } - -SV * my_eval_pv(char *pv) { - - SV* result; - - /* - * eval_pv(..., TRUE) means die if Perl traps an error - */ - result = eval_pv(pv, TRUE) ; - return result ; - } - -char * get_command_line(void) { - - /* debug - * printf("%s\n", INIT_TERM_READLINE) ; - */ - SV *cmd_line ; - char *command_line ; - - cmd_line = my_eval_pv(DO_READLINE) ; - command_line = SvPVX(cmd_line) ; - /* command_line = SvPV(cmd_line, n_a) ; */ - return command_line ; - } - -void init_term_readline(void) { - (void) my_eval_pv(INIT_TERM_READLINE) ; - } - -void init_embedded_perl(void) { - char *embedding[] = { "", "p1.pl" }; - /* embedding takes the place of argv[] ($argv[0] is the program name. - * - which is not given to Perl). - * Note that the number of args (ie the number of elements in embedding - * [argc] is the third argument of perl_parse(). - */ - int exitstatus; - char buffer[132]; - - if((my_perl = perl_alloc()) == NULL) { - snprintf(buffer, sizeof(buffer), "Error: Could not allocate memory for embedded Perl interpreter!\n"); - buffer[sizeof(buffer) - 1] = '\x0'; - printf("%s\n", buffer); - exit(1); - } - - perl_construct(my_perl); - exitstatus = perl_parse(my_perl, xs_init, 2, embedding, NULL); - PL_exit_flags |= PERL_EXIT_DESTRUCT_END; - /* Why is perl_run() necessary ? - * It is needed if the code parsed by perl_parse() has - * any runtime semantics (eg code that gets eval'd, - * behaviour that depends on constants etc). - */ - exitstatus = perl_run(my_perl); - - if(exitstatus) { - printf("%s\n", "perl_run() failed."); - exit(1); - } - } - -void deinit_embedded_perl(void) { - - PL_perl_destruct_level = 0; - perl_destruct(my_perl); - perl_free(my_perl); - } - - -int main(int argc, char **argv, char **env) { - - init_embedded_perl(); - /* Calls Perl to load and construct a new - * Term::ReadLine object. - */ - - init_term_readline(); - - while(1) { - /* - * get_command_line calls Perl to get a scalar from stdin - */ - - /* Perl Term::ReadLine::readline() method chomps the "\n" - * from the end of the input. - */ - char *cmd, *end; - /* Allow any length command line */ - cmd = (get_command_line()) ; - - // Trim leading whitespace - while(isspace(*cmd)) cmd++; - - // Trim trailing whitespace - end = cmd + strlen(cmd) - 1; - while(end > cmd && isspace(*end)) end--; - - // Write new null terminator - *(end + 1) = 0; - - run_plugin(cmd) ; - } - - deinit_embedded_perl(); - } - diff --git a/contrib/p1.pl b/contrib/p1.pl deleted file mode 100644 index 27a734c..0000000 --- a/contrib/p1.pl +++ /dev/null @@ -1,851 +0,0 @@ - package Embed::Persistent; - -# $Id$ - -# $Log$ -# Revision 1.5 2005-01-18 13:52:15+11 anwsmh -# 1 Set log level back to RETICENT and log file name to a placeholder for dist. -# -# Revision 1.4 2005-01-18 13:26:12+11 anwsmh -# 1 Major changes for Perl >= 5.6 -# 1.1 tieing STDERR to ErrorTrap caused a SEGV in libperl because of -# misuse of the open statement. -# 1.2 STDERR is now aliased to the handle associated with a log file -# opened if logging is enabled. -# - - -# p1.pl for Nagios 2.0 - -# Only major changes are that STDOUT is redirected to a scalar -# by means of a tied filehandle so that it can be returned to Nagios -# without the need for a syscall to read() -# - -use strict ; -use vars '%Cache' ; -use Text::ParseWords qw(parse_line) ; - -use constant RETICENT => 1 ; -use constant GARRULOUS => 0 ; -use constant DEBUG => 0 ; - -use constant EPN_STDERR_LOG => '/Path/to/embedded/Perl/Nagios/Logfile' ; - -use constant TEXT_RETICENT => <<'RETICENT' ; - -package OutputTrap; - -# -# Methods for use by tied STDOUT in embedded PERL module. -# -# Simply ties STDOUT to a scalar and emulates serial semantics. -# - -sub TIEHANDLE { - my ($class) = @_; - my $me ; - bless \$me, $class; -} - -sub PRINT { - my $self = shift; - $$self .= join("",@_); -} - -sub PRINTF { - my $self = shift; - my $fmt = shift; - $$self .= sprintf($fmt,@_); -} - -sub READLINE { - my $self = shift; - # Perl code other than plugins may print nothing; in this case return "(No output!)\n". - return(defined $$self ? $$self : "(No output!)\n"); -} - -sub CLOSE { - my $self = shift; -} - -package Embed::Persistent; - -sub valid_package_name { - my($string) = @_; - $string =~ s/([^A-Za-z0-9\/])/sprintf("_%2x",unpack("C",$1))/eg; - # second pass only for words starting with a digit - $string =~ s|/(\d)|sprintf("/_%2x",unpack("C",$1))|eg; - - # Dress it up as a real package name - $string =~ s|/|::|g; - return "Embed::" . $string; - } - -# Perl 5.005_03 only traps warnings for errors classed by perldiag -# as Fatal (eg 'Global symbol """"%s"""" requires explicit package name'). -# Therefore treat all warnings as fatal. - -sub throw_exception { - my $warn = shift ; - return if $warn =~ /^Subroutine CORE::GLOBAL::exit redefined/ ; - die $warn ; -} - -sub eval_file { - my $filename = shift; - my $delete = shift; - - my $pn = substr($filename, rindex($filename,"/")+1); - my $package = valid_package_name($pn); - my $mtime = -M $filename ; - if ( defined $Cache{$package}{mtime} && - $Cache{$package}{mtime} <= $mtime) { - # we have compiled this subroutine already, - # it has not been updated on disk, nothing left to do - } - else { - local *FH; - # FIXME - error handling - open FH, $filename or die "'$filename' $!"; - local($/) = undef; - my $sub = ; - close FH; - # cater for routines that expect to get args without progname - # and for those using @ARGV - $sub = qq(\nshift(\@_);\n\@ARGV=\@_;\nlocal \$^W=1;\n$sub) ; - - # cater for scripts that have embedded EOF symbols (__END__) - $sub =~ s/__END__/\;}\n__END__/; - - # wrap the code into a subroutine inside our unique package - my $eval = qq{ - package main; - use subs 'CORE::GLOBAL::exit'; - sub CORE::GLOBAL::exit { die "ExitTrap: \$_[0] ($package)"; } - package $package; sub hndlr { $sub } - }; - $Cache{$package}{plugin_error} = 0 ; - # suppress warning display. - local $SIG{__WARN__} = \&throw_exception ; - { - # hide our variables within this block - my ($filename, $mtime, $package, $sub); - eval $eval; - } - # $@ is set for any warning and error. This guarantees that the plugin will not be run. - if ($@) { - # Log eval'd text of plugin. - # Correct the line number of the error by removing the lines added (the subroutine prologue) by Embed::eval_file. - my $i = 1 ; - $eval =~ s/^/sprintf('%10d ', $i++)/meg ; - $Cache{$package}{plugin_error} = $@ ; - $Cache{$package}{mtime} = $mtime unless $delete; - # If the compilation fails, leave nothing behind that may affect subsequent compilations. - die; - - } - - #cache it unless we're cleaning out each time - $Cache{$package}{mtime} = $mtime unless $delete; - - } -} - -sub run_package { - my $filename = shift; - my $delete = shift; - my $tmpfname = shift; - my $ar = shift; - my $pn = substr($filename, rindex($filename,"/")+1); - my $package = valid_package_name($pn); - my $res = 3; - - tie (*STDOUT, 'OutputTrap'); - - my @a = &parse_line('\s+', 0, $ar) ; - - if ( $Cache{$package}{plugin_error} ) { - untie *STDOUT; - # return unknown - return (3, '**ePN' . " '$pn' " . $Cache{$package}{plugin_error} . "\n") ; - } - - local $SIG{__WARN__} = \&throw_exception ; - eval { $package->hndlr(@a); }; - - if ($@) { - if ($@ =~ /^ExitTrap: /) { - # For normal plugin exit the ExitTrap string is set by the - # redefined CORE::GLOBAL::exit sub calling die to return a string =~ /^ExitTrap: -?\d+ $package/ - # However, there is only _one_ exit sub so the last plugin to be compiled sets _its_ - # package name. - $res = 0; - } else { - # get return code (which may be negative) - if ($@ =~ /^ExitTrap: (-?\d+)/) { - $res = $1; - } else { - # run time error/abnormal plugin termination; exit was not called in plugin - # return unknown - $res = 3; - - chomp $@ ; - # correct line number reported by eval for the prologue added by eval_file - $@ =~ s/(\d+)\.$/($1 - 8)/e ; - print STDOUT '**ePN', " '$pn' ", $@, "\n" ; - # Don't run it again until the plugin is recompiled (clearing $Cache{$package}{plugin_error}) - # Note that the plugin should be handle any run time errors (such as timeouts) - # that may occur in service checking. - - # FIXME - doesn't work under both 5.005 and 5.8.0. The cached value of plugin error is reset somehow. - # $Cache{$package}{plugin_error} = $@ ; - } - } - } - # !! - my $plugin_output = ; - untie *STDOUT; - return ($res, $plugin_output) ; -} - -1; - -RETICENT - -use constant TEXT_GARRULOUS => <<'GARRULOUS' ; - -BEGIN { - open STDERRLOG, '>> ' . EPN_STDERR_LOG - or die "Can't open '" . EPN_STDERR_LOG . " for append: $!" ; -} - -package OutputTrap; - -# -# Methods for use by tied STDOUT in embedded PERL module. -# -# Simply ties STDOUT to a scalar and emulates serial semantics. -# - -sub TIEHANDLE { - my ($class) = @_; - my $me ; - bless \$me, $class; -} - -sub PRINT { - my $self = shift; - $$self .= join("",@_); -} - -sub PRINTF { - my $self = shift; - my $fmt = shift; - $$self .= sprintf($fmt,@_); -} - -sub READLINE { - my $self = shift; - # Perl code other than plugins may print nothing; in this case return "(No output!)\n". - return(defined $$self ? $$self : "(No output!)\n"); -} - -sub CLOSE { - my $self = shift; -} - -package Embed::Persistent; - -sub valid_package_name { - my($string) = @_; - $string =~ s/([^A-Za-z0-9\/])/sprintf("_%2x",unpack("C",$1))/eg; - # second pass only for words starting with a digit - $string =~ s|/(\d)|sprintf("/_%2x",unpack("C",$1))|eg; - - # Dress it up as a real package name - $string =~ s|/|::|g; - return "Embed::" . $string; - } - -# Perl 5.005_03 only traps warnings for errors classed by perldiag -# as Fatal (eg 'Global symbol """"%s"""" requires explicit package name'). -# Therefore treat all warnings as fatal. - -sub throw_exception { - my $warn = shift ; - return if $warn =~ /^Subroutine CORE::GLOBAL::exit redefined/ ; - die $warn ; -} - -sub eval_file { - my $filename = shift; - my $delete = shift; - - *STDERR = *STDERRLOG ; - - my $pn = substr($filename, rindex($filename,"/")+1); - my $package = valid_package_name($pn); - my $mtime = -M $filename ; - if ( defined $Cache{$package}{mtime} && - $Cache{$package}{mtime} <= $mtime) { - # we have compiled this subroutine already, - # it has not been updated on disk, nothing left to do - } - else { - local *FH; - # FIXME - error handling - open FH, $filename or die "'$filename' $!"; - local($/) = undef; - my $sub = ; - close FH; - # cater for routines that expect to get args without progname - # and for those using @ARGV - $sub = qq(\nshift(\@_);\n\@ARGV=\@_;\nlocal \$^W=1;\n$sub) ; - - # cater for scripts that have embedded EOF symbols (__END__) - $sub =~ s/__END__/\;}\n__END__/; - - # wrap the code into a subroutine inside our unique package - my $eval = qq{ - package main; - use subs 'CORE::GLOBAL::exit'; - sub CORE::GLOBAL::exit { die "ExitTrap: \$_[0] ($package)"; } - package $package; sub hndlr { $sub } - }; - $Cache{$package}{plugin_error} = 0 ; - # suppress warning display. - local $SIG{__WARN__} = \&throw_exception ; - { - # hide our variables within this block - my ($filename, $mtime, $package, $sub); - eval $eval; - } - # $@ is set for any warning and error. This guarantees that the plugin will not be run. - if ($@) { - # Log eval'd text of plugin. - # Correct the line number of the error by removing the lines added (the subroutine prologue) by Embed::eval_file. - my $i = 1 ; - $eval =~ s/^/sprintf('%10d ', $i++)/meg ; - print STDERR '[', time(), ']', qq( **ePN '$pn' error '$@' in text "\n$eval"\n) ; - $Cache{$package}{plugin_error} = $@ ; - $Cache{$package}{mtime} = $mtime unless $delete; - # If the compilation fails, leave nothing behind that may affect subsequent compilations. - die; - - } - - #cache it unless we're cleaning out each time - $Cache{$package}{mtime} = $mtime unless $delete; - - } -} - -sub run_package { - my $filename = shift; - my $delete = shift; - my $tmpfname = shift; - my $ar = shift; - my $pn = substr($filename, rindex($filename,"/")+1); - my $package = valid_package_name($pn); - my $res = 3; - - tie (*STDOUT, 'OutputTrap'); - - my @a = &parse_line('\s+', 0, $ar) ; - - if ( $Cache{$package}{plugin_error} ) { - untie *STDOUT; - # return unknown - return (3, '**ePN' . " '$pn' " . $Cache{$package}{plugin_error} . "\n") ; - } - - local $SIG{__WARN__} = \&throw_exception ; - eval { $package->hndlr(@a); }; - - if ($@) { - if ($@ =~ /^ExitTrap: /) { - # For normal plugin exit the ExitTrap string is set by the - # redefined CORE::GLOBAL::exit sub calling die to return a string =~ /^ExitTrap: -?\d+ $package/ - # However, there is only _one_ exit sub so the last plugin to be compiled sets _its_ - # package name. - $res = 0; - } else { - # get return code (which may be negative) - if ($@ =~ /^ExitTrap: (-?\d+)/) { - $res = $1; - } else { - # run time error/abnormal plugin termination; exit was not called in plugin - # return unknown - $res = 3; - - chomp $@ ; - # correct line number reported by eval for the prologue added by eval_file - $@ =~ s/(\d+)\.$/($1 - 8)/e ; - print STDOUT '**ePN', " '$pn' ", $@, "\n" ; - # Don't run it again until the plugin is recompiled (clearing $Cache{$package}{plugin_error}) - # Note that the plugin should be handle any run time errors (such as timeouts) - # that may occur in service checking. - - # FIXME - doesn't work under both 5.005 and 5.8.0. The cached value of plugin error is reset somehow. - # $Cache{$package}{plugin_error} = $@ ; - } - } - } - # !! - my $plugin_output = ; - untie *STDOUT; - return ($res, $plugin_output) ; -} - -1; - -GARRULOUS - -use constant TEXT_DEBUG => <<'DEBUG' ; - -BEGIN { - open STDERRLOG, '>> ' . EPN_STDERR_LOG - or die "Can't open '" . EPN_STDERR_LOG . " for append: $!" ; -} - -package OutputTrap; - -# -# Methods for use by tied STDOUT in embedded PERL module. -# -# Simply ties STDOUT to a scalar and emulates serial semantics. -# - -sub TIEHANDLE { - my ($class) = @_; - my $me ; - bless \$me, $class; -} - -sub PRINT { - my $self = shift; - $$self .= join("",@_); -} - -sub PRINTF { - my $self = shift; - my $fmt = shift; - $$self .= sprintf($fmt,@_); -} - -sub READLINE { - my $self = shift; - # Perl code other than plugins may print nothing; in this case return "(No output!)\n". - return(defined $$self ? $$self : "(No output!)\n"); -} - -sub CLOSE { - my $self = shift; -} - -package Embed::Persistent; - -sub valid_package_name { - my($string) = @_; - $string =~ s/([^A-Za-z0-9\/])/sprintf("_%2x",unpack("C",$1))/eg; - # second pass only for words starting with a digit - $string =~ s|/(\d)|sprintf("/_%2x",unpack("C",$1))|eg; - - # Dress it up as a real package name - $string =~ s|/|::|g; - return "Embed::" . $string; - } - -# Perl 5.005_03 only traps warnings for errors classed by perldiag -# as Fatal (eg 'Global symbol """"%s"""" requires explicit package name'). -# Therefore treat all warnings as fatal. - -sub throw_exception { - my $warn = shift ; - return if $warn =~ /^Subroutine CORE::GLOBAL::exit redefined/ ; - print STDERR " ... throw_exception: calling die $warn\n" ; - die $warn ; -} - -sub eval_file { - my $filename = shift; - my $delete = shift; - - *STDERR = *STDERRLOG ; - - my $pn = substr($filename, rindex($filename,"/")+1); - my $package = valid_package_name($pn); - my $mtime = -M $filename ; - if ( defined $Cache{$package}{mtime} && - $Cache{$package}{mtime} <= $mtime) { - # we have compiled this subroutine already, - # it has not been updated on disk, nothing left to do - print STDERR "(I) \$mtime: $mtime, \$Cache{$package}{mtime}: '$Cache{$package}{mtime}' - already compiled $package->hndlr.\n"; - } - else { - print STDERR "(I) \$mtime: $mtime, \$Cache{$package}{mtime}: '$Cache{$package}{mtime}' - Compiling or recompiling \$filename: $filename.\n" ; - local *FH; - # FIXME - error handling - open FH, $filename or die "'$filename' $!"; - local($/) = undef; - my $sub = ; - close FH; - # cater for routines that expect to get args without progname - # and for those using @ARGV - $sub = qq(\nshift(\@_);\n\@ARGV=\@_;\nlocal \$^W=1;\n$sub) ; - - # cater for scripts that have embedded EOF symbols (__END__) - $sub =~ s/__END__/\;}\n__END__/; - - # wrap the code into a subroutine inside our unique package - my $eval = qq{ - package main; - use subs 'CORE::GLOBAL::exit'; - sub CORE::GLOBAL::exit { die "ExitTrap: \$_[0] ($package)"; } - package $package; sub hndlr { $sub } - }; - $Cache{$package}{plugin_error} = 0 ; - # suppress warning display. - local $SIG{__WARN__} = \&throw_exception ; - { - # hide our variables within this block - my ($filename, $mtime, $package, $sub); - eval $eval; - } - # $@ is set for any warning and error. This guarantees that the plugin will not be run. - if ($@) { - # Log eval'd text of plugin. - # Correct the line number of the error by removing the lines added (the subroutine prologue) by Embed::eval_file. - # $@ =~ s/line (\d+)\.\n/'line ' . ($1 - 8) . ".\n"/ge ; - my $i = 1 ; - $eval =~ s/^/sprintf('%10d ', $i++)/meg ; - print STDERR '[', time(), ']', qq( **ePN '$pn' error '$@' in text "\n$eval"\n) ; - $Cache{$package}{plugin_error} = $@ ; - $Cache{$package}{mtime} = $mtime unless $delete; - # If the compilation fails, leave nothing behind that may affect subsequent compilations. - die; - - } - - #cache it unless we're cleaning out each time - $Cache{$package}{mtime} = $mtime unless $delete; - - } -} - -sub run_package { - my $filename = shift; - my $delete = shift; - my $tmpfname = shift; - my $ar = shift; - my $pn = substr($filename, rindex($filename,"/")+1); - my $package = valid_package_name($pn); - my $res = 3; - - use Data::Dumper ; - print STDERR Data::Dumper->Dump([\%Cache], [qw(%Cache)]) ; - - tie (*STDOUT, 'OutputTrap'); - - my @a = &parse_line('\s+', 0, $ar) ; - - if ( $Cache{$package}{plugin_error} ) { - untie *STDOUT; - # return unknown - print STDERR " ... eval failed in eval_file, run_package returning (3, **ePN '$pn' '$Cache{$package}{plugin_error}'\\n)\n" ; - return (3, '**ePN' . " '$pn' " . $Cache{$package}{plugin_error} . "\n") ; - } - - local $SIG{__WARN__} = \&throw_exception ; - eval { $package->hndlr(@a); }; - - if ($@) { - if ($@ =~ /^ExitTrap: /) { - # For normal plugin exit the ExitTrap string is set by the - # redefined CORE::GLOBAL::exit sub calling die to return a string =~ /^ExitTrap: -?\d+ $package/ - # However, there is only _one_ exit sub so the last plugin to be compiled sets _its_ - # package name. - $res = 0; - } else { - # get return code (which may be negative) - if ($@ =~ /^ExitTrap: (-?\d+)/) { - $res = $1; - } else { - # run time error/abnormal plugin termination; exit was not called in plugin - # return unknown - $res = 3; - - chomp $@ ; - # correct line number reported by eval for the prologue added by eval_file - $@ =~ s/(\d+)\.$/($1 - 8)/e ; - print STDOUT '**ePN', " '$pn' ", $@, "\n" ; - # Don't run it again until the plugin is recompiled (clearing $Cache{$package}{plugin_error}) - # Note that the plugin should be handle any run time errors (such as timeouts) - # that may occur in service checking. - - # FIXME - doesn't work under both 5.005 and 5.8.0. The cached value of plugin error is reset somehow. - # $Cache{$package}{plugin_error} = $@ ; - } - } - } - # !! - my $plugin_output = ; - untie *STDOUT; - print STDERR " ... run_package returning ('$res', '$plugin_output')\n" ; - return ($res, $plugin_output) ; -} - -1; - -DEBUG - -SWITCH: { - eval TEXT_RETICENT, last SWITCH if RETICENT ; - eval TEXT_GARRULOUS, last SWITCH if GARRULOUS ; - eval TEXT_DEBUG, last SWITCH if DEBUG ; - die "Please set one of (use constant statements) RETICENT, GARRULOUS or DEBUG in code.\n" ; -} - -1 ; - -=head1 NAME - -p1.pl - Perl program to provide Perl code persistence for the Nagios project (http://www.Nagios.Org). - -This program attempts to provide a mod_perl like facility for Nagios. - -=head1 SYNOPSIS - -Edit the text to set the values of (the 'use constant' statements) the log path, B, and any one -(only) of the boolean log level flags B, B, and B. The default is to set RETICENT, and -to use S</var/epn_stderr.log> as the log path. - -The log level flags determine the amount and type of messages logged in the log path. - -The RETICENT log level results in similar behaviour to former versions of p1.pl. -In particular, the log file EPN_STDERR_LOG will B be opened. - -=head1 DESCRIPTION - -Nagios is a program to monitor service availability; it does this by scheduling 'plugins' - discrete programs -that check a service and output a line of text describing the service state intended for -those responsible for the service and exit with a coded value to relay the same information to Nagios. - -Plugins, like CGIs, can be coded in Perl. The persistence framework embeds a Perl interpreter in Nagios to - -=over 4 - -=item * reduce the time taken for the Perl compile and execute cycle. - -=item * eliminate the need for the shell to fork and exec Perl. - -=item * eliminate the need for Nagios to fork a process (with popen) to run the Perl code. - -=item * eliminate reloading of frequently used modules. - -=back - -and all the good things mentioned in the B man page under 'Maintaining a persistent interpreter'. - -Plugin syntax errors (possibly introduced when the plugin is transformed by the persistence framework) and run-time -errors are logged depending on the log level flags. - -Regardless of the log level, plugin run-time and syntax errors, are returned to Nagios as the 'plugin output'. These messages -appear in the Nagios log like S<**ePN 'check_test' Global symbol "$status" requires explicit package name at (eval 54) line 15.> - -=over 4 - -=item * GARRULOUS - -=over 8 - -=item 1 opens an extra output stream in the path given by the value of EPN_STDERR_LOG. - -=item 2 logs a listing of plugin errors, followed by a dump of the plugin source - as transformed by -the persistence framework - each time the plugin source file modification time stamp is changed (either -by correcting the syntax error or touching the file). - -=back - -An example of such a listing is - - [1074760243] **ePN 'check_test' error 'Global symbol "$status" requires explicit package name at (eval 54) line 15. ' in text " - 1 - 2 package main; - 3 use subs 'CORE::GLOBAL::exit'; - 4 sub CORE::GLOBAL::exit { die "ExitTrap: $_[0] (Embed::check_5ftest)"; } - 5 package Embed::check_5ftest; sub hndlr { - 6 shift(@_); - 7 @ARGV=@_; - 8 local $^W=1; - 9 #!/usr/bin/perl -w - 10 - 11 # This plugin always does what it is told. - 12 - 13 use strict ; - 14 - 15 $status = shift @ARGV ; - 16 # my $status = shift @ARGV ; - 17 $status ||= 'fail' ; - 18 - 19 my $invert = 1 ; - 20 - 21 $status = lc($status) ; - 22 - 23 $status = ( ( $invert and $status eq 'ok' ) ? 'fail' : - 24 ( $invert and $status eq 'fail' ) ? 'ok' : - 25 $status ) ; - 26 - 27 $status eq 'ok' and do { - 28 print "Ok. Got a \"$status\". Expecting \"OK\".\n" ; - 29 exit 0 ; - 30 } ; - 31 - 32 $status eq 'fail' and do { - 33 print "Failed. Got a \"$status\". Expecting \"FAIL\".\n" ; - 34 exit 2 ; - 35 } ; - 36 - 37 # print "Mmmm. Looks like I got an "$status\" when expecting an \"ok\" or \"fail\".\n" ; - 38 print "Mmmm. Looks like I got an \"$status\" when expecting an \"ok\" or \"fail\".\n" ; - 39 exit 3 ; - 40 } - 41 " - -Note that the plugin text (lines 9 to 39 inclusive) has been transformed by the persistence frame work to -E<10>1 override the exit sub in package main - -E<10>2 create a new package from the plugin file name, here Embed::check_5ftest - -E<10>3 wrap the plugin in a subroutine named hndlr within the new package - -E<10>4 handle the argument list the same way as for a method call, restoring @ARGV from the remaining -arguments - -E<10>5 Setting the warning level to trap all warnings (note that the -w option to Perl is no -longer significant because the shebang line is not fed to exec()). - -=item * DEBUG - -This setting is intended only for hacking this code. In addition to the garrulous messages - -=over 8 - -=item 1 enter, leave messages - -=item 2 dump of %Cache data structure - -=back - -=item * RETICENT - -This is the default verbosity level and recommended for production use. One line only of compile or run -time errors is reported in the Nagios log. There are no other output streams. - -=back - -=head1 SUBROUTINES - -Unless otherwise stated, all subroutines take two (2) arguments :- - -=over 4 - -=item 1 plugin_filename - string (called from C) or scalar(called from Perl): the path to the plugin. - -=item 2 DO_CLEAN - boolean: set if plugin is not to be cached. Defaults to 0. - -Setting this flag means that the plugin is compiled each time it is executed. Nagios B sets this flag when the -Nagios is compiled with the configure setting --with-perlcache. - -=back - -=over 4 - -=item Embed::Persistent::eval_file( plugin_filename, DO_CLEAN ) - -E<10> -Returns nothing. - - -eval_file() transforms the plugin to a subroutine in a package, compiles the string containing the -transformed plugin, caches the plugin file modification time (to avoid recompiling it), and caches -any errors returned by the compilation. - -If the plugin has been modified or has not been compiled before, the plugin is transformed to a subroutine in a new package by - -creating a package name from the plugin file name (C) - -turning off subroutine redefinition warnings (C) - -overriding CORE::GLOBAL::exit from within package main (C) -This allows the plugin to call exit without taking down the persistence framework. - -prepending the plugin text with code to let the plugin function as a subroutine. This code sets up -the plugin argument vector (@ARGV) from the subroutine arguments and turns on warnings. -(C<$sub = qq(\nshift(\@_);\n\@ARGV=\@_;\nlocal \$^W=1;\n$sub)>). - -writing the plugin as the subroutine named 'hndlr' in the new package (C) - - -The plugin compilation, performed by C, caches C<$@> if the transformed plugin has syntax errors. - - -=item Embed::Persistent::run_package( plugin_filename, DO_CLEAN, '', plugin_argument_string ) - -E<10> -Returns (plugin_return_code, plugin_output) - -run_package() - -=back - -=head1 BUGS - -This framework does nothing to prevent the memory leaks mentioned in B, relying on operator intervention. - -Probably the best way of doing so is by periodically scheduling - -=over 4 - -=item 1 A check of the memory used by the Nagios process (by running for example the standard Nagios plugin check_vsz) - -=item 2 Restarting Nagios with the (supplied with Nagios) startup script (restart command). - - -=back - -If you do periodocally restart Nagios, make sure that - -=over 4 - -=item 1 plugins all set the PATH environment variable if they need other system binaries (otherwise, if the -init script is excec'd by cron, the PATH will be reset and the plugins will fail - but only when reatsrted by cron). - -=item 2 that the group owning the Nagios command pipe is the same as the Nagios group (otherwise, the restarted -Nagios will not be able to read from the command pipe). - -=back - -Nagios installations using the persistence framework must monitor the memory use of the Nagios process and stop/start it when -the usage is exorbidant (eg, for a site with 400 services on 200 hosts and custom Perl plugins used for about 10% of the -service checks, the Nagios process uses ~80 MB after 20-30 days runningi with Perl 5.005 [Memory usage is -B greater with recent Perls]. It is usually stopped and started at this point). - -Note that a HUP signal is B sufficient to deallocate the Perl memory; the Nagios process must be stopped and started. - - -=head1 AUTHOR - -Originally by Stephen Davies. - -Now maintained by Stanley Hopcroft who retains responsibility for the 'bad bits'. - -=head1 COPYRIGHT - -Copyright (c) 2004 Stanley Hopcroft. All rights reserved. -This program is free software; you can redistribute it and/or modify -it under the same terms as Perl itself. - -=cut - diff --git a/contrib/traceroute.cgi b/contrib/traceroute.cgi index 0ba34f5..abea7f1 100644 --- a/contrib/traceroute.cgi +++ b/contrib/traceroute.cgi @@ -66,10 +66,10 @@ print "\n\n"; print "
Type:
"; print ""; print "
"; print "
traceroute
"; -print "Genereated by $self
"; +print "Generated by $self
"; print "Last Updated: $mdate
"; print "Updated every $refresh seconds
"; -print "Nagios® - www.nagios.org
"; +print "Nagios® - www.nagios.org
"; print "Logged in as $ENV{'REMOTE_USER'}
"; print "
"; diff --git a/daemon-init.in b/daemon-init.in index 98f35e5..af1498c 100644 --- a/daemon-init.in +++ b/daemon-init.in @@ -1,12 +1,12 @@ #!/bin/sh -# +# # chkconfig: 345 99 01 # description: Nagios network monitor -# +# processname: nagios # File : nagios # # Author : Jorge Sanchez Aymar (jsanchez@lanchile.cl) -# +# # Changelog : # # 1999-07-09 Karl DeBisschop @@ -28,76 +28,22 @@ # Description: Starts and stops the Nagios monitor # used to provide network services status. # +### BEGIN INIT INFO +# Provides: nagios +# Required-Start: $local_fs $syslog $network +# Required-Stop: $local_fs $syslog $network +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Starts and stops the Nagios monitoring server +# Description: Starts and stops the Nagios monitoring server +### END INIT INFO -# Load any extra environment variables for Nagios and its plugins -if test -f /etc/sysconfig/nagios; then - . /etc/sysconfig/nagios -fi - -status_nagios () -{ - - if test -x $NagiosCGI/daemonchk.cgi; then - if $NagiosCGI/daemonchk.cgi -l $NagiosRunFile; then - return 0 - else - return 1 - fi - else - if ps -p $NagiosPID > /dev/null 2>&1; then - return 0 - else - return 1 - fi - fi - - return 1 -} - - -printstatus_nagios() -{ - - if status_nagios $1 $2; then - echo "nagios (pid $NagiosPID) is running..." - else - echo "nagios is not running" - fi -} - - -killproc_nagios () -{ - - kill $2 $NagiosPID - -} - - -pid_nagios () -{ - - if test ! -f $NagiosRunFile; then - echo "No lock file found in $NagiosRunFile" - exit 1 - fi - - NagiosPID=`head -n 1 $NagiosRunFile` -} - - -# Source function library -# Solaris doesn't have an rc.d directory, so do a test first -if [ -f /etc/rc.d/init.d/functions ]; then - . /etc/rc.d/init.d/functions -elif [ -f /etc/init.d/functions ]; then - . /etc/init.d/functions -fi - +# Our install-time configuration. prefix=@prefix@ exec_prefix=@exec_prefix@ NagiosBin=@bindir@/nagios NagiosCfgFile=@sysconfdir@/nagios.cfg +NagiosCfgtestFile=@localstatedir@/nagios.configtest NagiosStatusFile=@localstatedir@/status.dat NagiosRetentionFile=@localstatedir@/retention.dat NagiosCommandFile=@localstatedir@/rw/nagios.cmd @@ -108,79 +54,214 @@ NagiosLockFile=nagios NagiosCGIDir=@sbindir@ NagiosUser=@nagios_user@ NagiosGroup=@nagios_grp@ - +checkconfig="true" + +# Source function library +# Some *nix do not have an rc.d directory, so do a test first +if [ -f /etc/rc.d/init.d/functions ]; then + . /etc/rc.d/init.d/functions +elif [ -f /etc/init.d/functions ]; then + . /etc/init.d/functions +elif [ -f /lib/lsb/init-functions ]; then + . /lib/lsb/init-functions +fi + +# Load any extra environment variables for Nagios and its plugins. +if test -f /etc/sysconfig/nagios; then + . /etc/sysconfig/nagios +fi + +# Automate addition of RAMDISK based on environment variables +USE_RAMDISK=${USE_RAMDISK:-0} +if test "$USE_RAMDISK" -ne 0 && test "$RAMDISK_SIZE"X != "X"; then + ramdisk=`mount |grep "${RAMDISK_DIR} type tmpfs"` + if [ "$ramdisk"X == "X" ]; then + mkdir -p -m 0755 ${RAMDISK_DIR} + mount -t tmpfs -o size=${RAMDISK_SIZE}m tmpfs ${RAMDISK_DIR} + mkdir -p -m 0755 ${RAMDISK_DIR}/checkresults + chown -h -R $NagiosUser:$NagiosGroup ${RAMDISK_DIR} + fi +fi + + +check_config () +{ + rm -f "$NagiosCfgtestFile"; + if test -e "$NagiosCfgtestFile"; then + echo "ERROR: Could not delete '$NagiosCfgtestFile'" + exit 8 + fi + + TMPFILE=$(mktemp /tmp/.configtest.XXXXXXXX) + $NagiosBin -vp $NagiosCfgFile > "$TMPFILE" + WARN=`grep ^"Total Warnings:" "$TMPFILE" |awk -F: '{print \$2}' |sed s/' '//g` + ERR=`grep ^"Total Errors:" "$TMPFILE" |awk -F: '{print \$2}' |sed s/' '//g` + + if test "$WARN" = "0" && test "${ERR}" = "0"; then + echo "OK - Configuration check verified" > $NagiosCfgtestFile + chmod 0644 $NagiosCfgtestFile + chown -h $NagiosUser:$NagiosGroup $NagiosCfgtestFile + /bin/rm "$TMPFILE" + return 0 + elif test "${ERR}" = "0"; then + # Write the errors to a file we can have a script watching for. + echo "WARNING: Warnings in config files - see log for details: $NagiosCfgtestFile" > $NagiosCfgtestFile + egrep -i "(^warning|^error)" "$TMPFILE" >> $NagiosCfgtestFile + chmod 0644 $NagiosCfgtestFile + chown -h $NagiosUser:$NagiosGroup $NagiosCfgtestFile + /bin/rm "$TMPFILE" + return 0 + else + # Write the errors to a file we can have a script watching for. + echo "ERROR: Errors in config files - see log for details: $NagiosCfgtestFile" > $NagiosCfgtestFile + egrep -i "(^warning|^error)" "$TMPFILE" >> $NagiosCfgtestFile + chmod 0644 $NagiosCfgtestFile + chown -h $NagiosUser:$NagiosGroup $NagiosCfgtestFile + cat "$TMPFILE" + exit 8 + fi +} + + +status_nagios () +{ + if test -x $NagiosCGI/daemonchk.cgi; then + if $NagiosCGI/daemonchk.cgi -l $NagiosRunFile > /dev/null 2>&1; then return 0; fi + else + if ps -p $NagiosPID > /dev/null 2>&1; then return 0; fi + fi + + return 1 +} + +printstatus_nagios () +{ + if status_nagios; then + echo "nagios (pid $NagiosPID) is running..." + else + echo "nagios is not running" + fi +} + +killproc_nagios () +{ + kill -s "$1" $NagiosPID +} + +pid_nagios () +{ + if test ! -f $NagiosRunFile; then + echo "No lock file found in $NagiosRunFile" + exit 1 + fi + + NagiosPID=`head -n 1 $NagiosRunFile` +} + +remove_commandfile () +{ + # Removing a stalled command file, while there are processes trying/waiting to write into it, + # will deadlock those processes in a blocking open() system call. To allow such processes to + # die on a broken pipe, the pipe must be opened for reading without actually reading from it, + # which is what dd does here. To avoid a chicken-egg problem, the pipe is renamed beforehand. + # In order for the dd to not deadlock when there is no writing process, it is executed in the + # background in a subshell together with an empty echo to have at least one writing process. + + # see http://unix.stackexchange.com/questions/335406/opening-named-pipe-blocks-forever-if-pipe-is-deleted-without-being-connected + + if [ -p $NagiosCommandFile ]; then + mv -f $NagiosCommandFile $NagiosCommandFile~ + (dd if=$NagiosCommandFile~ count=0 2>/dev/null & echo -n "" >$NagiosCommandFile~) + fi + + rm -f $NagiosCommandFile $NagiosCommandFile~ +} + # Check that nagios exists. if [ ! -f $NagiosBin ]; then - echo "Executable file $NagiosBin not found. Exiting." + echo "Executable file $NagiosBin not found. Exiting." exit 1 fi # Check that nagios.cfg exists. if [ ! -f $NagiosCfgFile ]; then - echo "Configuration file $NagiosCfgFile not found. Exiting." + echo "Configuration file $NagiosCfgFile not found. Exiting." exit 1 fi - + # See how we were called. case "$1" in start) echo -n "Starting nagios:" - $NagiosBin -v $NagiosCfgFile > /dev/null 2>&1; - if [ $? -eq 0 ]; then - su - $NagiosUser -c "touch $NagiosVarDir/nagios.log $NagiosRetentionFile" - rm -f $NagiosCommandFile - touch $NagiosRunFile - chown $NagiosUser:$NagiosGroup $NagiosRunFile - $NagiosBin -d $NagiosCfgFile - if [ -d $NagiosLockDir ]; then touch $NagiosLockDir/$NagiosLockFile; fi - echo " done." - exit 0 - else - echo "CONFIG ERROR! Start aborted. Check your Nagios configuration." - exit 1 + + if test "$checkconfig" = "true"; then + check_config + # check_config exits on configuration errors. fi + + if test -f $NagiosRunFile; then + NagiosPID=`head -n 1 $NagiosRunFile` + if status_nagios; then + echo " another instance of nagios is already running." + exit 0 + fi + fi + + touch $NagiosVarDir/nagios.log $NagiosRetentionFile + remove_commandfile + touch $NagiosRunFile + chown -h $NagiosUser:$NagiosGroup $NagiosRunFile $NagiosVarDir/nagios.log $NagiosRetentionFile + $NagiosBin -d $NagiosCfgFile + if [ -d $NagiosLockDir ]; then touch $NagiosLockDir/$NagiosLockFile; fi + + echo " done." ;; stop) - echo -n "Stopping nagios: " + echo -n "Stopping nagios:" pid_nagios - killproc_nagios nagios + killproc_nagios TERM - # now we have to wait for nagios to exit and remove its - # own NagiosRunFile, otherwise a following "start" could - # happen, and then the exiting nagios will remove the - # new NagiosRunFile, allowing multiple nagios daemons - # to (sooner or later) run - John Sellens + # now we have to wait for nagios to exit and remove its + # own NagiosRunFile, otherwise a following "start" could + # happen, and then the exiting nagios will remove the + # new NagiosRunFile, allowing multiple nagios daemons + # to (sooner or later) run - John Sellens #echo -n 'Waiting for nagios to exit .' - for i in 1 2 3 4 5 6 7 8 9 10 ; do - if status_nagios > /dev/null; then - echo -n '.' - sleep 1 - else - break - fi - done - if status_nagios > /dev/null; then - echo '' - echo 'Warning - nagios did not exit in a timely manner' - else - echo 'done.' - fi + for i in {1..90}; do + if status_nagios > /dev/null; then + echo -n '.' + sleep 1 + else + break + fi + done + if status_nagios > /dev/null; then + echo '' + echo 'Warning - nagios did not exit in a timely manner - Killing it!' + killproc_nagios KILL + else + echo ' done.' + fi - rm -f $NagiosStatusFile $NagiosRunFile $NagiosLockDir/$NagiosLockFile $NagiosCommandFile + remove_commandfile + rm -f $NagiosStatusFile $NagiosRunFile $NagiosLockDir/$NagiosLockFile ;; status) pid_nagios - printstatus_nagios nagios + printstatus_nagios ;; checkconfig) - printf "Running configuration check..." - $NagiosBin -v $NagiosCfgFile > /dev/null 2>&1; + if test "$checkconfig" = "true"; then + printf "Running configuration check...\n" + check_config + fi + if [ $? -eq 0 ]; then echo " OK." else @@ -190,47 +271,45 @@ case "$1" in ;; restart) - printf "Running configuration check..." - $NagiosBin -v $NagiosCfgFile > /dev/null 2>&1; - if [ $? -eq 0 ]; then - echo "done." - $0 stop - $0 start - else - echo " CONFIG ERROR! Restart aborted. Check your Nagios configuration." - exit 1 + if test "$checkconfig" = "true"; then + printf "Running configuration check...\n" + check_config fi + + $0 stop + $0 start ;; reload|force-reload) - printf "Running configuration check..." - $NagiosBin -v $NagiosCfgFile > /dev/null 2>&1; - if [ $? -eq 0 ]; then - echo "done." - if test ! -f $NagiosRunFile; then - $0 start - else - pid_nagios - if status_nagios > /dev/null; then - printf "Reloading nagios configuration..." - killproc_nagios nagios -HUP - echo "done" - else - $0 stop - $0 start - fi - fi + if test "$checkconfig" = "true"; then + printf "Running configuration check...\n" + check_config + fi + + if test ! -f $NagiosRunFile; then + $0 start else - echo " CONFIG ERROR! Reload aborted. Check your Nagios configuration." - exit 1 + pid_nagios + if status_nagios > /dev/null; then + printf "Reloading nagios configuration...\n" + killproc_nagios HUP + echo "done" + else + $0 stop + $0 start + fi fi ;; + configtest) + $NagiosBin -vp $NagiosCfgFile + ;; + *) - echo "Usage: nagios {start|stop|restart|reload|force-reload|status|checkconfig}" + echo "Usage: nagios {start|stop|restart|reload|force-reload|status|checkconfig|configtest}" exit 1 ;; esac - + # End of this script diff --git a/docs/api-incompat3to4.dox b/docs/api-incompat3to4.dox new file mode 100644 index 0000000..73938d6 --- /dev/null +++ b/docs/api-incompat3to4.dox @@ -0,0 +1,73 @@ +/**@page api_incompat3to4 API incompatibilities between Nagios 3 and 4 + +A list of API incompatibilities between Nagios 3 and 4. + +[TOC] + +@section globalvars Global Variables +@li event_list_{high,low} and event_list_{high,low}_tail are no more. +Instead there is "squeue_t *nagios_squeue", which is a single queue +to handle all timed events. +@li last_command_check, command_check_interval, external_command_buffer +and external_command_buffer_slots are no more. +@li check_result_list is no more +@li passive_check_result_list and passive_check_result_list_tail are no +more. + + +@section datastructures Data Structures +@li All primary objects have been given an 'id' field, which can be +used to store additional data about each object, or mark them in +bitmaps, or... +@li Container-ish pointers have been removed pretty much everywhere in +favour of testable libraries with specific lookup properties and +containers. This means 'next_hash' etc no longer exist in any object. +The 'next' pointers in primary objects still remain, but you should +avoid using them in favour of iterating over objects using the object +arrays. +@li next and prev have been removed from timed_event. It's no longer +possible to sanely loop over all queued elements, since the squeue +library keeps its types opaque. Adding an "squeue_foreach()" thing +would be as simple as running a breadth-first search in the pqueue +library that drives the squeue implementation. +@li The scheduled_downtime data type now has start_event and +stop_event. +@li nebstruct_program_status_data no longer has a last_command_check +var. +@li The passive_service_check data type is no more. +@li The data type circular_buffer has been removed. +@li The host object's notify_on_down, notify_on_up, notify_on_blablah +variables have been replaced with a single "notification_options" field +instead, which is a small hand-managed bitmask of the states we should +notify on, based on 1 << current_state. +@li As per above, with flap_detection_options +@li As per above, with stalking_options +@li As per the three above, with services +@li As per above, with dependencies which now have a "failure_options" +field instead of multiple "fail_on_foo" fields. +@li As per above with escalations, which now have an +"escalation_options" field instead of multiple "escalate on foo" fields. + +@section functions Functions +@li Event queue management functions have been significantly altered +to match the new scheduling queue implementation. add_event(), +remove_event(), reschedule_event() and schedule_new_event() are the +primary ones. +@li submit_external_command() and submit_raw_external_command() have +been removed, as has check_for_external_commands(). +@li All functions handling adding and removing objects to circular +buffers or other types of linked lists used for searching have been +removed. +@li The *host*_3x() functions are gone. They have been replaced with +versions without the _3x suffix. +@li run_sync_host_check_3x() is gone. perform_on_demand_host_check(), +which previously only called run_sync_host_check_3x(), now does +something sensible instead of calling out to a single helper. +@li Using the 'struct host_struct *foo' form of type-naming has been +obsoleted and will no longer work. Use 'struct host' instead. +@li Use of typedef'ed typenames for non-opaque structures is now +deprecated. The typedef's will be removed in Nagios 5, and modules +that wish to continue using them after that will have to add them +themselves. The new preferred form is 'struct host *foo', which +clearly shows that we're dealing with a non-opaque type. +*/ diff --git a/docs/config-incompat3to4.dox b/docs/config-incompat3to4.dox new file mode 100644 index 0000000..749d807 --- /dev/null +++ b/docs/config-incompat3to4.dox @@ -0,0 +1,119 @@ +/** @page configincompat3to4 Configuration Incompatibilities 3->4 + +This page lists configuration incompatibilities between Nagios 3 +and Nagios 4. + +[TOC] + +@section mainconfig Main Config File Options +Since command file handling has been redone, embedded perl has been +removed and the event execution loop now sits and waits on input from +worker processes rather than spending any time sleeping, the following +variables have been obsoleted, will yield a warning when encountered +and no longer have any effect on monitoring: +@li command_check_interval +@li external_command_buffer_slots +@li sleep_time +@li enable_failure_prediction +@li enable_embedded_perl +@li use_embedded_perl_implicitly +@li auth_file +@li p1_file + + +@section nestedgroups Nested Group Includes +In Nagios 3, it's possible to have groups include each other +cyclically, like this: +@verbatim +define hostgroup{ + hostgroup_name HG1 + alias Hostgroup 1 + hostgroup_members HG3 +} + +define hostgroup{ + hostgroup_name HG2 + alias Hostgroup 2 + hostgroup_members HG1 +} + +define hostgroup{ + hostgroup_name HG3 + alias Hostgroup 3 + hostgroup_members HG2 +} +@endverbatim +With Nagios 4, that will generate an error. The Nagios 3 behaviour +is that the first hostgroup, as determined by alphabetical sorting, +will get the members of its included groups, but the later ones in +the sorting will not get the members of the previous ones. Since +that is an error-prone and illogical way of assigning group members, +we now disallow it. + +This will work the same for all grouptypes. + +@section groupinherits Group Inheritance +Groups no longer inherit each others exclusions. Consider the +following scenario: +@verbatim +define host{ + use default-host-template + host_name A + alias linux Server1 + address 127.0.0.1 + hostgroups HG1 + contact_groups support-group +} +define hostgroup{ + hostgroup_name HG1 + alias Hostgroup 1 + hostgroup_members HG3 +} +define hostgroup{ + hostgroup_name HG3 + alias Hostgroup 3 + members E,F,H,!A + hostgroup_members HG2 +} +@endverbatim +In Nagios 3, A would *not* be a member of HG1. In Nagios 4, it will, +because the logic has been fixed so that group inclusion works only +with the actual members, and not the rules concerning how those +members were chosen. +If you want to carry over exclusions, you can instead make a template +and 'use' one hostgroup from another. + +The same goes for all group types, and not just hostgroups. + +@section oconfchanges Object Configuration Changes +@subsection Deprecations +The "obsess_over_host" (for hosts) and "obsess_over_service" (for +services) configuration variables have been renamed to simply "obsess". +The old values will serve as aliases for the duration of the Nagios 4 +lifetime and will be removed in Nagios 5. Users should adjust their +configurations accordingly. + +@subsection additions Additions +Services have two new configurable values: +@li parents +@li hourly_value + +The 'parents' directive can be used to suppress notifications for a +service in much the same way that it can be used for hosts. If all +parents of a particular service are in a non-OK state when the child +service enters a HARD state (and should have notified), notifications +will be suppressed for the child service. + +The 'hourly_value' directive can be used to set a service 'value' of +the service in question. It works in tandem with a new directive for +contacts ("minimum_value") in order to suppress notifications, and +UI's are encouraged to take it into account to display the most severe +and valuable errors in a more prominent fashion. Note that it has no +currency attached to it, so whether you interpret it as affected_users, +business_value or whatever is entirely up to you. + +Contacts have one new configurable value, namely 'minimum_value', which +sets the minimum notification value for which the contact should get +notified. The notification value is determined by the total value of +all objects affected by the problem. +*/ diff --git a/docs/mainpage.dox b/docs/mainpage.dox new file mode 100644 index 0000000..a72001a --- /dev/null +++ b/docs/mainpage.dox @@ -0,0 +1,4 @@ +/** @mainpage + +Technical and api documentation for Nagios. +*/ diff --git a/docs/queryhandlers.dox b/docs/queryhandlers.dox new file mode 100644 index 0000000..8c17e43 --- /dev/null +++ b/docs/queryhandlers.dox @@ -0,0 +1,130 @@ +/** @page qh Query Handler + +A brief intro to the Nagios query handler system + +[TOC] + +@section purpose Purpose +The purpose of the query handler is to provide Nagios Core and its +eventbroker modules with the ability to communicate directly with +the outside world through a well-defined API, as well as allowing +external apps a way to help out with various Nagios tasks. + +@section caveats Caveats +The query handlers run in the main thread. Nagios doesn't provide any +parallelism here and main Nagios will be blocked while a query is +running. As such, it's a very good idea to make ones queryhandlers +complete in as little time as possible. + +@section qh_registering Registering a query handler +This is really for module authors only. + +To register a query handler, you *must* have a function like the one +below: +the following arguments: +@code +int lala_query_handler(int sd, char *query, unsigned int query_len) +@endcode + +The parameters don't have to have those exact names, and the function +certainly doesn't have to be called "lala_query_handler()". We're not +quite that childish (well, we are, but we like to pretend we're not). +They will suffice for this explanation, however. +@li sd - The socket you should respond to. +@li query - The query, minus the address and the magic byte. +@li query_len - Length of the query, in bytes. + +The call to register it with Nagios so you get all queries directed +to the 'lala' address is then: +@code +qh_register_handler("lala", "The LaLa query handler", 0, +lala_query_handler); +@endcode + +The second argument is a description, which will be printed when +someone sends a help request. +@note It's a good idea to handle queries such as "help" and take +them to mean "print me some text telling me at least the basics +of how to use this query handler". + +@section syntax Syntax +The query language is remarkably simple (although each handler may +implement its own parsers that handle and do pretty much whatever +they want). The first byte is magic. If it's an at-sign, we expect +the queryer to persist and issue more queries after the first one. +If it's a hash-sign, the query handler will disconnect the client +as soon as it regains control from whatever handler registered for +the particular address. Each particular handler has some control +over this behaviour though, and can use specific return codes to +denote that it will take over the socket from the query handler. +If no at-sign and no hash-sign is present at the first byte, the +-1'th byte will be considered an at-sign, and the connection will +consequently be considered persistent. + +@subsection qh_examples Example queries +Subscribe for real-time push-events for servicechecks from the NERD radio: +@verbatim +@nerd subscribe servicechecks\0 +@endverbatim + +One-shot query the core query handler for current load-control options: +@verbatim +#core loadctl\0 +@endverbatim + +Get Nagios to say hi to you: +@verbatim +#echo Greetings, Exalted One +@endverbatim + +Ask the help handler to list registered handlers: +@verbatim +#help list +@endverbatim + + +@section icqh In-core query handlers +There are a few in-core query handlers. + +@subsection help The help service +The help query handler is quite possibly the most important one. It +can be used to list registered handlers (with short descriptions), +and can be used to get help about registered handlers (assuming +they've implemented it, that is). It should be noted that the ones +that *have* implemented it can also be queried directly for their +help output, like so: +@verbatim +@core help +@endverbatim + + +@subsection echo The echo service +As I'm sure you've already guessed, the echo service just prints the +inbound data right back at you. While that's not exactly nobel prize +winning material, it's actually pretty nifty to figure out how fast +Nagios can parse its inbound data, which in turn shows how fast it can +handle its inbound checkresults, which puts an upper cap on how many +checks Nagios can handle at any given time (although short bursts that +exceed that limit are ok and will be handled just fine). + +It can be addressed as such: +@verbatim +@echo foo bar baz said the bunny\0 +@endverbatim + +@subsection nerd Nagios Event Radio Dispatcher +The nerd radio is subscribed in fuller detail at @see nerd, but its +worth knowing that it's a core part of Nagios 4 and that it will +always be available. + +@subsection wproc Worker process manager +The worker process manager lets you register workers that can help out +with running checks, send notifications, run eventhandlers or whatever. + +In order to register a worker that only handles checks supposed to be +run by the plugins check_foo and check_bar (irrespective of where in +the paths they are), you'd do something like this: +@verbatim +@wproc register name=foobar;plugin=check_foo;plugin=check_bar\0 +@endverbatim +*/ diff --git a/docs/workers.dox b/docs/workers.dox new file mode 100644 index 0000000..82e29de --- /dev/null +++ b/docs/workers.dox @@ -0,0 +1,269 @@ +/** @page wprocs Worker Processes + +Everything related to worker processes. + +[TOC] + +@section philosophy Philosophy +The idea behind separate worker processes is to achieve protected +parallelization. Protected because a worker being naughty shouldn't +affect the core process, and parallel because we use multiple +workers. Ideally between 1.5 and 3 per CPU core available to us. + +Workers are free-standing processes, kept small, and with no +knowledge about Nagios' object structure or logic. The reason for +this is that small processes can achieve a lot more fork()s per +second than large processes (800/sec for a 300MB process against +13900/sec for a 1MB process). While workers can (and do) grow a +little bit in memory usage when it's running many checks in +parallel, they will still be a lot smaller than the primar Nagios +daemon, and the memory they occupy should be released once the +checks they're running are done. + +@section protocol Protocol +Workers use a text-based protocol to communicate with workers. It's +fairly simple and very easy to debug. The breakdown goes as follows: +@li A request consists of a sequence of key/value pairs. +@li A key is separated from its value with an equal sign ('='). +@li A key/value pair is separated from the next key/value pair with a +nul byte ('\0'). +@li Each request is separated from the next with a message delimiter +sequence made up by a one-byte followed by three nul bytes: "\1\0\0\0". +@li Keys cannot contain equal signs. +underscores and numbers. +@li Values cannot contain nul bytes. +@li Neither keys nor values can contain the message delimiter. +@li A zero-length value is considered to be the empty string. + +@note Even though it's technically legal to put almost anything in the +key field, you should stick to mnemonic names when extending the +protocol and just use lower case letters and underscores. +@note Keys are case sensitive. JOB_ID is *not* the same as job_id. + +@subsection apis API's +Worker processes communicate with Nagios using libnagios API's +exclusively. Since you're looking at a subpage of the documentation +for that documentation right now, I'll just assume you've found it. +Although using the libnagios api's when writing a worker is +completely optional, it's highly recommended. + +The key API's to use are: +@li nsock - for connecting to and communicating through the qh socket +@li kvvec - for parsing requests and building responses +@li worker - for utils and stuff nifty to have if you're a worker +@li runcmd - for spawning and reaping commands +@li squeue - for maintaining a queue of the running job's timeouts +@li iocache - for bulk-reading requests and parsing them +@li iobroker - for multiplexing between running tasks and the master +nagios process. + +@note In particular, have a look at the "parse_command_kvvec()" and +"finish_job()" functions in lib/worker.c. They will do a large part +of the request/response handling for you. + +@section registering Registering a worker - The handshake +Workers register with Nagios through the queryhandler, using a query +sent to the wproc handler. Since the query handler reserves the nul +byte as a magic delimiter for its messages, this one time we use the +semicolon instead, as is almost-standard in the internal-only +queryhandlers. Typically, the default worker process registers with a +query such as this: +@verbatim +@wproc register name=Core Worker $pid;pid=$pid\0 +@endverbatim + +Nagios will then respond with +@verbatim +OK\0 +@endverbatim +followed by a stream of commands. + +Nagios currently understands the following (short) list of special +keys: +@li pid - The pid of the worker process. Sometimes used to check if a +worker is online +@li name - Used to set the name of the worker +@li max_jobs - Used to tell Nagios how many concurrent jobs this +worker can handle +@li plugin - basename() or absolute path of specific plugins that this +worker wants to handle checks for. + +@note plugin can be given multiple times. It is valid for a single +single worker to say "plugin=check_snmp;plugin=check_iferrors", for +example. + +@note Many workers can register for the same plugin(s). They will +share the load in round-robin fashion. + +Complete C-code for registering a generic worker with Nagios follows: +@code +static int nagios_core_worker(const char *path) +{ + int sd, ret; + char response[128]; + + is_worker = 1; + + set_loadctl_defaults(); + + sd = nsock_unix(path, NSOCK_TCP | NSOCK_CONNECT); + if (sd < 0) { + printf("Failed to connect to query socket '%s': %s: %s\n", + path, nsock_strerror(sd), strerror(errno)); + return 1; + } + + ret = nsock_printf_nul(sd, "@wproc register name=Core Worker %d;pid=%d", getpid(), getpid()); + if (ret < 0) { + printf("Failed to register as worker.\n"); + return 1; + } + + ret = read(sd, response, 3); + if (ret != 3) { + printf("Failed to read response from wproc manager\n"); + return 1; + } + if (memcmp(response, "OK", 3)) { + read(sd, response + 3, sizeof(response) - 4); + response[sizeof(response) - 2] = 0; + printf("Failed to register with wproc manager: %s\n", response); + return 1; + } + + enter_worker(sd, start_cmd); + return 0; +} +@endcode + +The "enter_worker()" part actually refers to a libnagios function that +lives in worker.c. The set_loadctl_defaults() call can be ignored. +It's primarily intended to give sane defaults about how many jobs we +can run, so we (in theory) can tell Nagios that we're swamped in case +we run out of filedescriptors or child processes. + + + + +@subsection request Requests +A complete request looks like this (with C-style format codes +replaced with actual values, ofcourse): +@verbatim +job_id=%d\0type=%d\0command=%s\0timeout=%u\0\1\0\0\0 +@endverbatim + +Note that values can contain equal signs, but cannot contain nul +bytes, and cannot contain the message delimiter sequence. +By including nagios/lib/worker.h and using worker_ioc2msg() followed +by worker_kvvec2buf_prealloc(), you will get a parsed key/value vector +handed to you. Have a look in base/workers.c to see how it's done for +the core workers. + +@subsection responses Responses +Once the worker is done running a task, it hands over the result to +the master Nagios process and forgets it ever ran the job. The workers +take no further action, regardless of how the task went. The exception +is if the job timed out, or if the worker failed to even start the job, +in which case it should report the error to Nagios and only *then* +forget it ever got the job. + +The response is identical to the request in formatting but differs in +the understood keys. The request sent from Nagios to the worker must +precede the other result variables. In particular, the job_id must be +the first variable Nagios sees for it to parse the result as a job +result rather than as something else. + +The variables required for the response to a successfully executed job +on a registered worker process are as follows: +@li job_id - The job id (as received by Nagios) +@li type - The job type (as Nagios sent it) +@li start - Timeval struct for start value in $sec.$usec format +@li stop - Timeval struct for stop time in $sec.$usec format +@li runtime - Floating point value of runtime, in seconds +@li outstd - Output caught on stdout +@li outerr - Output caught on stderr +@li exited_ok - Boolean flag to denote if the job exited ok. A +non-zero return code can still be achieved +@li wait_status - Integer, as set by the wait() family of system calls + +The following should only be present when the worker is unable to +execute the check due to an error, or when it cannot provide all the +variables required for a successfully executed job due to arbitrary +system errors: +@li error_msg - An error message generated by the worker process +@li error_code - The error code generated by the worker process + +error_code 62 (ETIME - Timer expired) is reserved and means that the +job timed out. +@note *never* invent error codes in the range 0-10000, since we'll +want to reserve that for special cases. + + +The following are completely optional (for now): +@li command - The command we executed +@li timeout - The timeout Nagios requested for this job +@li ru_nsignals - The ru_nsignals field from the rusage struct +@li ru_nswap - The ru_nswap field from the rusage struct +@li ru_minflt - The ru_minflt field from the rusage struct +@li ru_majflt - The ru_majflt field from the rusage struct +@li ru_stime - The ru_stime field from the rusage struct +@li ru_utime - The ru_utime field from the rusage struct +@li ru_inblock - The ru_inblock field from the rusage struct +@li ru_oublock - The ru_oublock field from the rusage struct + +The meaning of the fields of the rusage struct can be viewed in the +section 2 man-page for the getrusage() system call. Normally, you +would access it by executing the following command: +@verbatim +man 2 getrusage +@endverbatim +Note that most systems do not support all the fields of the rusage +struct and may leave them empty if so. + +@section logging Logging +Worker processes can send events to the main Nagios process that +will end up in the nagios.log file. The format is the same as that in +requests and responses, but a log-message consists of a single +key/value pair, where the key is always 'log'. Consequently, a request +from a worker to the main process to log something looks like this: +@verbatim +log=A random message that will get logged to nagios.log\0 +@endverbatim + +It's worth noting that Nagios will prefix the message with the worker +process name, so as to make grep'ing easy when debugging experimental +workers. + +@section xchgexample Protocol Exchange Example +A register + execution of one job on a worker process will, with the +standard Nagios core worker look like this, after the worker process +has connected to the query handler socket but before it has sent +anything. Note that the nul-bytes separating key/value pairs have been +replaced with newline to enhance readability. Also note that this +depicts only the required steps, which go as follows: +@verbatim +Step 1, Worker: + @wproc register name=Worker Hoopla;max_jobs=100;pid=6196\0 +Step 2, Nagios: + OK\0 +Step 3, Nagios: + job_id=0 + type=2 + timeout=60 + command=/opt/plugins/check_ping -H localhost -w 40%,100.0 -c 60%,200.0 + \1\0\0\0 +Step 4, Worker: + job_id=0 + type=2 + timeout=60 + start=1355231532.000123 + stop=1355231532.994343 + runtime=0.994120 + exited_ok=1 + outstd=OK: RTA: 12.6ms; PL: 0%|rta=12.6ms;100.0;200.0;0;; pl=0%;40;60 + wait_status=0 + outerr= + \1\0\0\0 +@endverbatim +Steps 3 and 4 in this chain repeat indefinitely. +*/ diff --git a/doxy.conf b/doxy.conf new file mode 100644 index 0000000..36b99bc --- /dev/null +++ b/doxy.conf @@ -0,0 +1,32 @@ +PROJECT_NAME = Nagios +PROJECT_NUMBER = 4.3.2 +PROJECT_BRIEF = "Dev docs for Nagios core and neb-module hackers" + +INPUT = lib/ docs/ +FILE_PATTERNS = *.h *.dox +EXCLUDE_PATTERNS = worker.h +OUTPUT_DIRECTORY = Documentation +GENERATE_TAGFILE = Documentation/classes.tag +QUIET = YES +RECURSIVE = YES +GENERATE_LATEX = NO +GENERATE_HTML = YES + +TAB_SIZE = 4 +JAVADOC_AUTOBRIEF = YES +MACRO_EXPANSION = YES +EXPAND_ONLY_PREDEF = YES +OPTIMIZE_OUTPUT_FOR_C = YES +STRIP_CODE_COMMENTS = NO +FULL_PATH_NAMES = NO +CASE_SENSE_NAMES = YES +ENABLE_PREPROCESSING = YES +PREDEFINED = NODOXY "NAGIOS_DEPRECATED(a, b)=" +SEARCH_INCLUDES = YES +INCLUDE_GRAPH = YES +CLASS_GRAPH = YES +CLASS_DIAGRAMS = YES +COLLABORATION_GRAPH = YES +INCLUDED_BY_GRAPH = YES +CALL_GRAPH = YES +GRAPHICAL_HIERARCHY = YES diff --git a/html/Makefile.in b/html/Makefile.in index a977e35..60b7ef3 100644 --- a/html/Makefile.in +++ b/html/Makefile.in @@ -9,6 +9,7 @@ CFGDIR=@sysconfdir@ BINDIR=@bindir@ CGIDIR=@sbindir@ HTMLDIR=@datadir@ +datarootdir=@datarootdir@ INSTALL=@INSTALL@ INSTALL_OPTS=@INSTALL_OPTS@ COMMAND_OPTS=@COMMAND_OPTS@ @@ -16,6 +17,11 @@ COMMAND_OPTS=@COMMAND_OPTS@ CP=@CP@ all html: + (cd angularjs && unzip -u angular-1.3.9.zip) + (cd angularjs && unzip -u ui-utils-0.2.1.zip) + if [ ! -d bootstrap-3.3.0 ] ; then mkdir -p bootstrap-3.3.0 && ( cd bootstrap-3.3.0 && unzip -u ../bootstrap-3.3.0-dist.zip && mv dist/* . && rmdir dist ) ; fi + mkdir -p d3 + (cd d3 && unzip -u ../d3-3.5.3.zip) clean: rm -f *.cfg *.sub core @@ -27,6 +33,10 @@ clean: rm -f docs/images/*.jbf rm -f stylesheets/*~ rm -f js/*~ + rm -rf angularjs/angular-1.3.9 + rm -rf angularjs/ui-utils-0.2.1 + rm -rf bootstrap-3.3.0 + rm -rf d3 distclean: clean rm -f Makefile config.inc.php @@ -44,15 +54,45 @@ install: $(INSTALL) -m 775 $(INSTALL_OPTS) -d $(DESTDIR)$(HTMLDIR)/images $(INSTALL) -m 775 $(INSTALL_OPTS) -d $(DESTDIR)$(HTMLDIR)/images/logos $(INSTALL) -m 775 $(INSTALL_OPTS) -d $(DESTDIR)$(HTMLDIR)/includes - $(INSTALL) -m 775 $(INSTALL_OPTS) -d $(DESTDIR)$(HTMLDIR)/includes/rss - $(INSTALL) -m 775 $(INSTALL_OPTS) -d $(DESTDIR)$(HTMLDIR)/includes/rss/extlib $(INSTALL) -m 775 $(INSTALL_OPTS) -d $(DESTDIR)$(HTMLDIR)/ssi +# Directories for new CGI pages + $(INSTALL) -m 775 $(INSTALL_OPTS) -d $(DESTDIR)$(HTMLDIR)/angularjs + $(INSTALL) -m 775 $(INSTALL_OPTS) -d $(DESTDIR)$(HTMLDIR)/angularjs/angular-1.3.9 + $(INSTALL) -m 775 $(INSTALL_OPTS) -d $(DESTDIR)$(HTMLDIR)/angularjs/ui-utils-0.2.1 + $(INSTALL) -m 775 $(INSTALL_OPTS) -d $(DESTDIR)$(HTMLDIR)/bootstrap-3.3.0 + $(INSTALL) -m 775 $(INSTALL_OPTS) -d $(DESTDIR)$(HTMLDIR)/bootstrap-3.3.0/css + $(INSTALL) -m 775 $(INSTALL_OPTS) -d $(DESTDIR)$(HTMLDIR)/d3 + $(INSTALL) -m 775 $(INSTALL_OPTS) -d $(DESTDIR)$(HTMLDIR)/spin +# End of directories for new CGI pages $(INSTALL) -m 664 $(INSTALL_OPTS) robots.txt $(DESTDIR)$(HTMLDIR) # $(INSTALL) -m 664 $(INSTALL_OPTS) docs/robots.txt $(DESTDIR)$(HTMLDIR)/docs -# Remove old HTML files (PHP files are used now) +# Remove old files rm -f $(DESTDIR)$(HTMLDIR)/index.html rm -f $(DESTDIR)$(HTMLDIR)/main.html rm -f $(DESTDIR)$(HTMLDIR)/side.html + rm -f $(DESTDIR)$(HTMLDIR)/map.html + rm -f $(DESTDIR)$(HTMLDIR)/rss-* + rm -rf $(DESTDIR)$(HTMLDIR)/include/rss + $(INSTALL) -m 664 $(INSTALL_OPTS) jsonquery.html $(DESTDIR)$(HTMLDIR) +# New graphical CGI pages + $(INSTALL) -m 664 $(INSTALL_OPTS) graph-header.html $(DESTDIR)$(HTMLDIR) + $(INSTALL) -m 664 $(INSTALL_OPTS) histogram.html $(DESTDIR)$(HTMLDIR) + $(INSTALL) -m 664 $(INSTALL_OPTS) histogram-form.html $(DESTDIR)$(HTMLDIR) + $(INSTALL) -m 664 $(INSTALL_OPTS) histogram-graph.html $(DESTDIR)$(HTMLDIR) + $(INSTALL) -m 664 $(INSTALL_OPTS) histogram-links.html $(DESTDIR)$(HTMLDIR) + $(INSTALL) -m 664 $(INSTALL_OPTS) infobox.html $(DESTDIR)$(HTMLDIR) + $(INSTALL) -m 664 $(INSTALL_OPTS) map.php $(DESTDIR)$(HTMLDIR) + $(INSTALL) -m 664 $(INSTALL_OPTS) map-directive.html $(DESTDIR)$(HTMLDIR) + $(INSTALL) -m 664 $(INSTALL_OPTS) map-form.html $(DESTDIR)$(HTMLDIR) + $(INSTALL) -m 664 $(INSTALL_OPTS) map-links.html $(DESTDIR)$(HTMLDIR) + $(INSTALL) -m 664 $(INSTALL_OPTS) map-popup.html $(DESTDIR)$(HTMLDIR) + $(INSTALL) -m 664 $(INSTALL_OPTS) trends.html $(DESTDIR)$(HTMLDIR) + $(INSTALL) -m 664 $(INSTALL_OPTS) trends-form.html $(DESTDIR)$(HTMLDIR) + $(INSTALL) -m 664 $(INSTALL_OPTS) trends-graph.html $(DESTDIR)$(HTMLDIR) + $(INSTALL) -m 664 $(INSTALL_OPTS) trends-host-yaxis.html $(DESTDIR)$(HTMLDIR) + $(INSTALL) -m 664 $(INSTALL_OPTS) trends-links.html $(DESTDIR)$(HTMLDIR) + $(INSTALL) -m 664 $(INSTALL_OPTS) trends-service-yaxis.html $(DESTDIR)$(HTMLDIR) +# End of new graphical CGI pages for file in *.php; \ do $(INSTALL) -m 664 $(INSTALL_OPTS) $$file $(DESTDIR)$(HTMLDIR); done # for file in media/*.wav; \ @@ -79,10 +119,16 @@ install: do $(INSTALL) -m 664 $(INSTALL_OPTS) $$file $(DESTDIR)$(HTMLDIR)/images/logos; done for file in includes/*.*; \ do $(INSTALL) -m 664 $(INSTALL_OPTS) $$file $(DESTDIR)$(HTMLDIR)/includes; done - for file in includes/rss/*.*; \ - do $(INSTALL) -m 664 $(INSTALL_OPTS) $$file $(DESTDIR)$(HTMLDIR)/includes/rss; done - for file in includes/rss/extlib/*.*; \ - do $(INSTALL) -m 664 $(INSTALL_OPTS) $$file $(DESTDIR)$(HTMLDIR)/includes/rss/extlib; done +# Support files for new graphical CGIs + $(INSTALL) -m 664 $(INSTALL_OPTS) angularjs/angular-1.3.9/angular.min.js $(DESTDIR)$(HTMLDIR)/angularjs/angular-1.3.9 + $(INSTALL) -m 664 $(INSTALL_OPTS) angularjs/angular-1.3.9/angular.min.js.map $(DESTDIR)$(HTMLDIR)/angularjs/angular-1.3.9 + $(INSTALL) -m 664 $(INSTALL_OPTS) angularjs/ui-bootstrap-tpls-0.12.0.min.js $(DESTDIR)$(HTMLDIR)/angularjs + $(INSTALL) -m 664 $(INSTALL_OPTS) angularjs/ui-utils-0.2.1/ui-utils.js $(DESTDIR)$(HTMLDIR)/angularjs/ui-utils-0.2.1 + $(INSTALL) -m 664 $(INSTALL_OPTS) bootstrap-3.3.0/css/bootstrap.min.css $(DESTDIR)$(HTMLDIR)/bootstrap-3.3.0/css + $(INSTALL) -m 664 $(INSTALL_OPTS) bootstrap-3.3.0/css/bootstrap-theme.min.css $(DESTDIR)$(HTMLDIR)/bootstrap-3.3.0/css + $(INSTALL) -m 664 $(INSTALL_OPTS) d3/d3.min.js $(DESTDIR)$(HTMLDIR)/d3 + $(INSTALL) -m 664 $(INSTALL_OPTS) spin/spin.min.js $(DESTDIR)$(HTMLDIR)/spin +# End of support files for new graphical CGIs install-unstripped: $(MAKE) install diff --git a/html/angularjs/angular-1.3.9.zip b/html/angularjs/angular-1.3.9.zip new file mode 100644 index 0000000..6443595 Binary files /dev/null and b/html/angularjs/angular-1.3.9.zip differ diff --git a/html/angularjs/ui-bootstrap-tpls-0.12.0.min.js b/html/angularjs/ui-bootstrap-tpls-0.12.0.min.js new file mode 100644 index 0000000..ae71363 --- /dev/null +++ b/html/angularjs/ui-bootstrap-tpls-0.12.0.min.js @@ -0,0 +1,10 @@ +/* + * angular-ui-bootstrap + * http://angular-ui.github.io/bootstrap/ + + * Version: 0.12.0 - 2014-11-16 + * License: MIT + */ +angular.module("ui.bootstrap",["ui.bootstrap.tpls","ui.bootstrap.transition","ui.bootstrap.collapse","ui.bootstrap.accordion","ui.bootstrap.alert","ui.bootstrap.bindHtml","ui.bootstrap.buttons","ui.bootstrap.carousel","ui.bootstrap.dateparser","ui.bootstrap.position","ui.bootstrap.datepicker","ui.bootstrap.dropdown","ui.bootstrap.modal","ui.bootstrap.pagination","ui.bootstrap.tooltip","ui.bootstrap.popover","ui.bootstrap.progressbar","ui.bootstrap.rating","ui.bootstrap.tabs","ui.bootstrap.timepicker","ui.bootstrap.typeahead"]),angular.module("ui.bootstrap.tpls",["template/accordion/accordion-group.html","template/accordion/accordion.html","template/alert/alert.html","template/carousel/carousel.html","template/carousel/slide.html","template/datepicker/datepicker.html","template/datepicker/day.html","template/datepicker/month.html","template/datepicker/popup.html","template/datepicker/year.html","template/modal/backdrop.html","template/modal/window.html","template/pagination/pager.html","template/pagination/pagination.html","template/tooltip/tooltip-html-unsafe-popup.html","template/tooltip/tooltip-popup.html","template/popover/popover.html","template/progressbar/bar.html","template/progressbar/progress.html","template/progressbar/progressbar.html","template/rating/rating.html","template/tabs/tab.html","template/tabs/tabset.html","template/timepicker/timepicker.html","template/typeahead/typeahead-match.html","template/typeahead/typeahead-popup.html"]),angular.module("ui.bootstrap.transition",[]).factory("$transition",["$q","$timeout","$rootScope",function(a,b,c){function d(a){for(var b in a)if(void 0!==f.style[b])return a[b]}var e=function(d,f,g){g=g||{};var h=a.defer(),i=e[g.animation?"animationEndEventName":"transitionEndEventName"],j=function(){c.$apply(function(){d.unbind(i,j),h.resolve(d)})};return i&&d.bind(i,j),b(function(){angular.isString(f)?d.addClass(f):angular.isFunction(f)?f(d):angular.isObject(f)&&d.css(f),i||h.resolve(d)}),h.promise.cancel=function(){i&&d.unbind(i,j),h.reject("Transition cancelled")},h.promise},f=document.createElement("trans"),g={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd",transition:"transitionend"},h={WebkitTransition:"webkitAnimationEnd",MozTransition:"animationend",OTransition:"oAnimationEnd",transition:"animationend"};return e.transitionEndEventName=d(g),e.animationEndEventName=d(h),e}]),angular.module("ui.bootstrap.collapse",["ui.bootstrap.transition"]).directive("collapse",["$transition",function(a){return{link:function(b,c,d){function e(b){function d(){j===e&&(j=void 0)}var e=a(c,b);return j&&j.cancel(),j=e,e.then(d,d),e}function f(){k?(k=!1,g()):(c.removeClass("collapse").addClass("collapsing"),e({height:c[0].scrollHeight+"px"}).then(g))}function g(){c.removeClass("collapsing"),c.addClass("collapse in"),c.css({height:"auto"})}function h(){if(k)k=!1,i(),c.css({height:0});else{c.css({height:c[0].scrollHeight+"px"});{c[0].offsetWidth}c.removeClass("collapse in").addClass("collapsing"),e({height:0}).then(i)}}function i(){c.removeClass("collapsing"),c.addClass("collapse")}var j,k=!0;b.$watch(d.collapse,function(a){a?h():f()})}}}]),angular.module("ui.bootstrap.accordion",["ui.bootstrap.collapse"]).constant("accordionConfig",{closeOthers:!0}).controller("AccordionController",["$scope","$attrs","accordionConfig",function(a,b,c){this.groups=[],this.closeOthers=function(d){var e=angular.isDefined(b.closeOthers)?a.$eval(b.closeOthers):c.closeOthers;e&&angular.forEach(this.groups,function(a){a!==d&&(a.isOpen=!1)})},this.addGroup=function(a){var b=this;this.groups.push(a),a.$on("$destroy",function(){b.removeGroup(a)})},this.removeGroup=function(a){var b=this.groups.indexOf(a);-1!==b&&this.groups.splice(b,1)}}]).directive("accordion",function(){return{restrict:"EA",controller:"AccordionController",transclude:!0,replace:!1,templateUrl:"template/accordion/accordion.html"}}).directive("accordionGroup",function(){return{require:"^accordion",restrict:"EA",transclude:!0,replace:!0,templateUrl:"template/accordion/accordion-group.html",scope:{heading:"@",isOpen:"=?",isDisabled:"=?"},controller:function(){this.setHeading=function(a){this.heading=a}},link:function(a,b,c,d){d.addGroup(a),a.$watch("isOpen",function(b){b&&d.closeOthers(a)}),a.toggleOpen=function(){a.isDisabled||(a.isOpen=!a.isOpen)}}}}).directive("accordionHeading",function(){return{restrict:"EA",transclude:!0,template:"",replace:!0,require:"^accordionGroup",link:function(a,b,c,d,e){d.setHeading(e(a,function(){}))}}}).directive("accordionTransclude",function(){return{require:"^accordionGroup",link:function(a,b,c,d){a.$watch(function(){return d[c.accordionTransclude]},function(a){a&&(b.html(""),b.append(a))})}}}),angular.module("ui.bootstrap.alert",[]).controller("AlertController",["$scope","$attrs",function(a,b){a.closeable="close"in b,this.close=a.close}]).directive("alert",function(){return{restrict:"EA",controller:"AlertController",templateUrl:"template/alert/alert.html",transclude:!0,replace:!0,scope:{type:"@",close:"&"}}}).directive("dismissOnTimeout",["$timeout",function(a){return{require:"alert",link:function(b,c,d,e){a(function(){e.close()},parseInt(d.dismissOnTimeout,10))}}}]),angular.module("ui.bootstrap.bindHtml",[]).directive("bindHtmlUnsafe",function(){return function(a,b,c){b.addClass("ng-binding").data("$binding",c.bindHtmlUnsafe),a.$watch(c.bindHtmlUnsafe,function(a){b.html(a||"")})}}),angular.module("ui.bootstrap.buttons",[]).constant("buttonConfig",{activeClass:"active",toggleEvent:"click"}).controller("ButtonsController",["buttonConfig",function(a){this.activeClass=a.activeClass||"active",this.toggleEvent=a.toggleEvent||"click"}]).directive("btnRadio",function(){return{require:["btnRadio","ngModel"],controller:"ButtonsController",link:function(a,b,c,d){var e=d[0],f=d[1];f.$render=function(){b.toggleClass(e.activeClass,angular.equals(f.$modelValue,a.$eval(c.btnRadio)))},b.bind(e.toggleEvent,function(){var d=b.hasClass(e.activeClass);(!d||angular.isDefined(c.uncheckable))&&a.$apply(function(){f.$setViewValue(d?null:a.$eval(c.btnRadio)),f.$render()})})}}}).directive("btnCheckbox",function(){return{require:["btnCheckbox","ngModel"],controller:"ButtonsController",link:function(a,b,c,d){function e(){return g(c.btnCheckboxTrue,!0)}function f(){return g(c.btnCheckboxFalse,!1)}function g(b,c){var d=a.$eval(b);return angular.isDefined(d)?d:c}var h=d[0],i=d[1];i.$render=function(){b.toggleClass(h.activeClass,angular.equals(i.$modelValue,e()))},b.bind(h.toggleEvent,function(){a.$apply(function(){i.$setViewValue(b.hasClass(h.activeClass)?f():e()),i.$render()})})}}}),angular.module("ui.bootstrap.carousel",["ui.bootstrap.transition"]).controller("CarouselController",["$scope","$timeout","$interval","$transition",function(a,b,c,d){function e(){f();var b=+a.interval;!isNaN(b)&&b>0&&(h=c(g,b))}function f(){h&&(c.cancel(h),h=null)}function g(){var b=+a.interval;i&&!isNaN(b)&&b>0?a.next():a.pause()}var h,i,j=this,k=j.slides=a.slides=[],l=-1;j.currentSlide=null;var m=!1;j.select=a.select=function(c,f){function g(){if(!m){if(j.currentSlide&&angular.isString(f)&&!a.noTransition&&c.$element){c.$element.addClass(f);{c.$element[0].offsetWidth}angular.forEach(k,function(a){angular.extend(a,{direction:"",entering:!1,leaving:!1,active:!1})}),angular.extend(c,{direction:f,active:!0,entering:!0}),angular.extend(j.currentSlide||{},{direction:f,leaving:!0}),a.$currentTransition=d(c.$element,{}),function(b,c){a.$currentTransition.then(function(){h(b,c)},function(){h(b,c)})}(c,j.currentSlide)}else h(c,j.currentSlide);j.currentSlide=c,l=i,e()}}function h(b,c){angular.extend(b,{direction:"",active:!0,leaving:!1,entering:!1}),angular.extend(c||{},{direction:"",active:!1,leaving:!1,entering:!1}),a.$currentTransition=null}var i=k.indexOf(c);void 0===f&&(f=i>l?"next":"prev"),c&&c!==j.currentSlide&&(a.$currentTransition?(a.$currentTransition.cancel(),b(g)):g())},a.$on("$destroy",function(){m=!0}),j.indexOfSlide=function(a){return k.indexOf(a)},a.next=function(){var b=(l+1)%k.length;return a.$currentTransition?void 0:j.select(k[b],"next")},a.prev=function(){var b=0>l-1?k.length-1:l-1;return a.$currentTransition?void 0:j.select(k[b],"prev")},a.isActive=function(a){return j.currentSlide===a},a.$watch("interval",e),a.$on("$destroy",f),a.play=function(){i||(i=!0,e())},a.pause=function(){a.noPause||(i=!1,f())},j.addSlide=function(b,c){b.$element=c,k.push(b),1===k.length||b.active?(j.select(k[k.length-1]),1==k.length&&a.play()):b.active=!1},j.removeSlide=function(a){var b=k.indexOf(a);k.splice(b,1),k.length>0&&a.active?j.select(b>=k.length?k[b-1]:k[b]):l>b&&l--}}]).directive("carousel",[function(){return{restrict:"EA",transclude:!0,replace:!0,controller:"CarouselController",require:"carousel",templateUrl:"template/carousel/carousel.html",scope:{interval:"=",noTransition:"=",noPause:"="}}}]).directive("slide",function(){return{require:"^carousel",restrict:"EA",transclude:!0,replace:!0,templateUrl:"template/carousel/slide.html",scope:{active:"=?"},link:function(a,b,c,d){d.addSlide(a,b),a.$on("$destroy",function(){d.removeSlide(a)}),a.$watch("active",function(b){b&&d.select(a)})}}}),angular.module("ui.bootstrap.dateparser",[]).service("dateParser",["$locale","orderByFilter",function(a,b){function c(a){var c=[],d=a.split("");return angular.forEach(e,function(b,e){var f=a.indexOf(e);if(f>-1){a=a.split(""),d[f]="("+b.regex+")",a[f]="$";for(var g=f+1,h=f+e.length;h>g;g++)d[g]="",a[g]="$";a=a.join(""),c.push({index:f,apply:b.apply})}}),{regex:new RegExp("^"+d.join("")+"$"),map:b(c,"index")}}function d(a,b,c){return 1===b&&c>28?29===c&&(a%4===0&&a%100!==0||a%400===0):3===b||5===b||8===b||10===b?31>c:!0}this.parsers={};var e={yyyy:{regex:"\\d{4}",apply:function(a){this.year=+a}},yy:{regex:"\\d{2}",apply:function(a){this.year=+a+2e3}},y:{regex:"\\d{1,4}",apply:function(a){this.year=+a}},MMMM:{regex:a.DATETIME_FORMATS.MONTH.join("|"),apply:function(b){this.month=a.DATETIME_FORMATS.MONTH.indexOf(b)}},MMM:{regex:a.DATETIME_FORMATS.SHORTMONTH.join("|"),apply:function(b){this.month=a.DATETIME_FORMATS.SHORTMONTH.indexOf(b)}},MM:{regex:"0[1-9]|1[0-2]",apply:function(a){this.month=a-1}},M:{regex:"[1-9]|1[0-2]",apply:function(a){this.month=a-1}},dd:{regex:"[0-2][0-9]{1}|3[0-1]{1}",apply:function(a){this.date=+a}},d:{regex:"[1-2]?[0-9]{1}|3[0-1]{1}",apply:function(a){this.date=+a}},EEEE:{regex:a.DATETIME_FORMATS.DAY.join("|")},EEE:{regex:a.DATETIME_FORMATS.SHORTDAY.join("|")}};this.parse=function(b,e){if(!angular.isString(b)||!e)return b;e=a.DATETIME_FORMATS[e]||e,this.parsers[e]||(this.parsers[e]=c(e));var f=this.parsers[e],g=f.regex,h=f.map,i=b.match(g);if(i&&i.length){for(var j,k={year:1900,month:0,date:1,hours:0},l=1,m=i.length;m>l;l++){var n=h[l-1];n.apply&&n.apply.call(k,i[l])}return d(k.year,k.month,k.date)&&(j=new Date(k.year,k.month,k.date,k.hours)),j}}}]),angular.module("ui.bootstrap.position",[]).factory("$position",["$document","$window",function(a,b){function c(a,c){return a.currentStyle?a.currentStyle[c]:b.getComputedStyle?b.getComputedStyle(a)[c]:a.style[c]}function d(a){return"static"===(c(a,"position")||"static")}var e=function(b){for(var c=a[0],e=b.offsetParent||c;e&&e!==c&&d(e);)e=e.offsetParent;return e||c};return{position:function(b){var c=this.offset(b),d={top:0,left:0},f=e(b[0]);f!=a[0]&&(d=this.offset(angular.element(f)),d.top+=f.clientTop-f.scrollTop,d.left+=f.clientLeft-f.scrollLeft);var g=b[0].getBoundingClientRect();return{width:g.width||b.prop("offsetWidth"),height:g.height||b.prop("offsetHeight"),top:c.top-d.top,left:c.left-d.left}},offset:function(c){var d=c[0].getBoundingClientRect();return{width:d.width||c.prop("offsetWidth"),height:d.height||c.prop("offsetHeight"),top:d.top+(b.pageYOffset||a[0].documentElement.scrollTop),left:d.left+(b.pageXOffset||a[0].documentElement.scrollLeft)}},positionElements:function(a,b,c,d){var e,f,g,h,i=c.split("-"),j=i[0],k=i[1]||"center";e=d?this.offset(a):this.position(a),f=b.prop("offsetWidth"),g=b.prop("offsetHeight");var l={center:function(){return e.left+e.width/2-f/2},left:function(){return e.left},right:function(){return e.left+e.width}},m={center:function(){return e.top+e.height/2-g/2},top:function(){return e.top},bottom:function(){return e.top+e.height}};switch(j){case"right":h={top:m[k](),left:l[j]()};break;case"left":h={top:m[k](),left:e.left-f};break;case"bottom":h={top:m[j](),left:l[k]()};break;default:h={top:e.top-g,left:l[k]()}}return h}}}]),angular.module("ui.bootstrap.datepicker",["ui.bootstrap.dateparser","ui.bootstrap.position"]).constant("datepickerConfig",{formatDay:"dd",formatMonth:"MMMM",formatYear:"yyyy",formatDayHeader:"EEE",formatDayTitle:"MMMM yyyy",formatMonthTitle:"yyyy",datepickerMode:"day",minMode:"day",maxMode:"year",showWeeks:!0,startingDay:0,yearRange:20,minDate:null,maxDate:null}).controller("DatepickerController",["$scope","$attrs","$parse","$interpolate","$timeout","$log","dateFilter","datepickerConfig",function(a,b,c,d,e,f,g,h){var i=this,j={$setViewValue:angular.noop};this.modes=["day","month","year"],angular.forEach(["formatDay","formatMonth","formatYear","formatDayHeader","formatDayTitle","formatMonthTitle","minMode","maxMode","showWeeks","startingDay","yearRange"],function(c,e){i[c]=angular.isDefined(b[c])?8>e?d(b[c])(a.$parent):a.$parent.$eval(b[c]):h[c]}),angular.forEach(["minDate","maxDate"],function(d){b[d]?a.$parent.$watch(c(b[d]),function(a){i[d]=a?new Date(a):null,i.refreshView()}):i[d]=h[d]?new Date(h[d]):null}),a.datepickerMode=a.datepickerMode||h.datepickerMode,a.uniqueId="datepicker-"+a.$id+"-"+Math.floor(1e4*Math.random()),this.activeDate=angular.isDefined(b.initDate)?a.$parent.$eval(b.initDate):new Date,a.isActive=function(b){return 0===i.compare(b.date,i.activeDate)?(a.activeDateId=b.uid,!0):!1},this.init=function(a){j=a,j.$render=function(){i.render()}},this.render=function(){if(j.$modelValue){var a=new Date(j.$modelValue),b=!isNaN(a);b?this.activeDate=a:f.error('Datepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.'),j.$setValidity("date",b)}this.refreshView()},this.refreshView=function(){if(this.element){this._refreshView();var a=j.$modelValue?new Date(j.$modelValue):null;j.$setValidity("date-disabled",!a||this.element&&!this.isDisabled(a))}},this.createDateObject=function(a,b){var c=j.$modelValue?new Date(j.$modelValue):null;return{date:a,label:g(a,b),selected:c&&0===this.compare(a,c),disabled:this.isDisabled(a),current:0===this.compare(a,new Date)}},this.isDisabled=function(c){return this.minDate&&this.compare(c,this.minDate)<0||this.maxDate&&this.compare(c,this.maxDate)>0||b.dateDisabled&&a.dateDisabled({date:c,mode:a.datepickerMode})},this.split=function(a,b){for(var c=[];a.length>0;)c.push(a.splice(0,b));return c},a.select=function(b){if(a.datepickerMode===i.minMode){var c=j.$modelValue?new Date(j.$modelValue):new Date(0,0,0,0,0,0,0);c.setFullYear(b.getFullYear(),b.getMonth(),b.getDate()),j.$setViewValue(c),j.$render()}else i.activeDate=b,a.datepickerMode=i.modes[i.modes.indexOf(a.datepickerMode)-1]},a.move=function(a){var b=i.activeDate.getFullYear()+a*(i.step.years||0),c=i.activeDate.getMonth()+a*(i.step.months||0);i.activeDate.setFullYear(b,c,1),i.refreshView()},a.toggleMode=function(b){b=b||1,a.datepickerMode===i.maxMode&&1===b||a.datepickerMode===i.minMode&&-1===b||(a.datepickerMode=i.modes[i.modes.indexOf(a.datepickerMode)+b])},a.keys={13:"enter",32:"space",33:"pageup",34:"pagedown",35:"end",36:"home",37:"left",38:"up",39:"right",40:"down"};var k=function(){e(function(){i.element[0].focus()},0,!1)};a.$on("datepicker.focus",k),a.keydown=function(b){var c=a.keys[b.which];if(c&&!b.shiftKey&&!b.altKey)if(b.preventDefault(),b.stopPropagation(),"enter"===c||"space"===c){if(i.isDisabled(i.activeDate))return;a.select(i.activeDate),k()}else!b.ctrlKey||"up"!==c&&"down"!==c?(i.handleKeyDown(c,b),i.refreshView()):(a.toggleMode("up"===c?1:-1),k())}}]).directive("datepicker",function(){return{restrict:"EA",replace:!0,templateUrl:"template/datepicker/datepicker.html",scope:{datepickerMode:"=?",dateDisabled:"&"},require:["datepicker","?^ngModel"],controller:"DatepickerController",link:function(a,b,c,d){var e=d[0],f=d[1];f&&e.init(f)}}}).directive("daypicker",["dateFilter",function(a){return{restrict:"EA",replace:!0,templateUrl:"template/datepicker/day.html",require:"^datepicker",link:function(b,c,d,e){function f(a,b){return 1!==b||a%4!==0||a%100===0&&a%400!==0?i[b]:29}function g(a,b){var c=new Array(b),d=new Date(a),e=0;for(d.setHours(12);b>e;)c[e++]=new Date(d),d.setDate(d.getDate()+1);return c}function h(a){var b=new Date(a);b.setDate(b.getDate()+4-(b.getDay()||7));var c=b.getTime();return b.setMonth(0),b.setDate(1),Math.floor(Math.round((c-b)/864e5)/7)+1}b.showWeeks=e.showWeeks,e.step={months:1},e.element=c;var i=[31,28,31,30,31,30,31,31,30,31,30,31];e._refreshView=function(){var c=e.activeDate.getFullYear(),d=e.activeDate.getMonth(),f=new Date(c,d,1),i=e.startingDay-f.getDay(),j=i>0?7-i:-i,k=new Date(f);j>0&&k.setDate(-j+1);for(var l=g(k,42),m=0;42>m;m++)l[m]=angular.extend(e.createDateObject(l[m],e.formatDay),{secondary:l[m].getMonth()!==d,uid:b.uniqueId+"-"+m});b.labels=new Array(7);for(var n=0;7>n;n++)b.labels[n]={abbr:a(l[n].date,e.formatDayHeader),full:a(l[n].date,"EEEE")};if(b.title=a(e.activeDate,e.formatDayTitle),b.rows=e.split(l,7),b.showWeeks){b.weekNumbers=[];for(var o=h(b.rows[0][0].date),p=b.rows.length;b.weekNumbers.push(o++)f;f++)c[f]=angular.extend(e.createDateObject(new Date(d,f,1),e.formatMonth),{uid:b.uniqueId+"-"+f});b.title=a(e.activeDate,e.formatMonthTitle),b.rows=e.split(c,3)},e.compare=function(a,b){return new Date(a.getFullYear(),a.getMonth())-new Date(b.getFullYear(),b.getMonth())},e.handleKeyDown=function(a){var b=e.activeDate.getMonth();if("left"===a)b-=1;else if("up"===a)b-=3;else if("right"===a)b+=1;else if("down"===a)b+=3;else if("pageup"===a||"pagedown"===a){var c=e.activeDate.getFullYear()+("pageup"===a?-1:1);e.activeDate.setFullYear(c)}else"home"===a?b=0:"end"===a&&(b=11);e.activeDate.setMonth(b)},e.refreshView()}}}]).directive("yearpicker",["dateFilter",function(){return{restrict:"EA",replace:!0,templateUrl:"template/datepicker/year.html",require:"^datepicker",link:function(a,b,c,d){function e(a){return parseInt((a-1)/f,10)*f+1}var f=d.yearRange;d.step={years:f},d.element=b,d._refreshView=function(){for(var b=new Array(f),c=0,g=e(d.activeDate.getFullYear());f>c;c++)b[c]=angular.extend(d.createDateObject(new Date(g+c,0,1),d.formatYear),{uid:a.uniqueId+"-"+c});a.title=[b[0].label,b[f-1].label].join(" - "),a.rows=d.split(b,5)},d.compare=function(a,b){return a.getFullYear()-b.getFullYear()},d.handleKeyDown=function(a){var b=d.activeDate.getFullYear();"left"===a?b-=1:"up"===a?b-=5:"right"===a?b+=1:"down"===a?b+=5:"pageup"===a||"pagedown"===a?b+=("pageup"===a?-1:1)*d.step.years:"home"===a?b=e(d.activeDate.getFullYear()):"end"===a&&(b=e(d.activeDate.getFullYear())+f-1),d.activeDate.setFullYear(b)},d.refreshView()}}}]).constant("datepickerPopupConfig",{datepickerPopup:"yyyy-MM-dd",currentText:"Today",clearText:"Clear",closeText:"Done",closeOnDateSelection:!0,appendToBody:!1,showButtonBar:!0}).directive("datepickerPopup",["$compile","$parse","$document","$position","dateFilter","dateParser","datepickerPopupConfig",function(a,b,c,d,e,f,g){return{restrict:"EA",require:"ngModel",scope:{isOpen:"=?",currentText:"@",clearText:"@",closeText:"@",dateDisabled:"&"},link:function(h,i,j,k){function l(a){return a.replace(/([A-Z])/g,function(a){return"-"+a.toLowerCase()})}function m(a){if(a){if(angular.isDate(a)&&!isNaN(a))return k.$setValidity("date",!0),a;if(angular.isString(a)){var b=f.parse(a,n)||new Date(a);return isNaN(b)?void k.$setValidity("date",!1):(k.$setValidity("date",!0),b)}return void k.$setValidity("date",!1)}return k.$setValidity("date",!0),null}var n,o=angular.isDefined(j.closeOnDateSelection)?h.$parent.$eval(j.closeOnDateSelection):g.closeOnDateSelection,p=angular.isDefined(j.datepickerAppendToBody)?h.$parent.$eval(j.datepickerAppendToBody):g.appendToBody;h.showButtonBar=angular.isDefined(j.showButtonBar)?h.$parent.$eval(j.showButtonBar):g.showButtonBar,h.getText=function(a){return h[a+"Text"]||g[a+"Text"]},j.$observe("datepickerPopup",function(a){n=a||g.datepickerPopup,k.$render()});var q=angular.element("
");q.attr({"ng-model":"date","ng-change":"dateSelection()"});var r=angular.element(q.children()[0]);j.datepickerOptions&&angular.forEach(h.$parent.$eval(j.datepickerOptions),function(a,b){r.attr(l(b),a)}),h.watchData={},angular.forEach(["minDate","maxDate","datepickerMode"],function(a){if(j[a]){var c=b(j[a]);if(h.$parent.$watch(c,function(b){h.watchData[a]=b}),r.attr(l(a),"watchData."+a),"datepickerMode"===a){var d=c.assign;h.$watch("watchData."+a,function(a,b){a!==b&&d(h.$parent,a)})}}}),j.dateDisabled&&r.attr("date-disabled","dateDisabled({ date: date, mode: mode })"),k.$parsers.unshift(m),h.dateSelection=function(a){angular.isDefined(a)&&(h.date=a),k.$setViewValue(h.date),k.$render(),o&&(h.isOpen=!1,i[0].focus())},i.bind("input change keyup",function(){h.$apply(function(){h.date=k.$modelValue})}),k.$render=function(){var a=k.$viewValue?e(k.$viewValue,n):"";i.val(a),h.date=m(k.$modelValue)};var s=function(a){h.isOpen&&a.target!==i[0]&&h.$apply(function(){h.isOpen=!1})},t=function(a){h.keydown(a)};i.bind("keydown",t),h.keydown=function(a){27===a.which?(a.preventDefault(),a.stopPropagation(),h.close()):40!==a.which||h.isOpen||(h.isOpen=!0)},h.$watch("isOpen",function(a){a?(h.$broadcast("datepicker.focus"),h.position=p?d.offset(i):d.position(i),h.position.top=h.position.top+i.prop("offsetHeight"),c.bind("click",s)):c.unbind("click",s)}),h.select=function(a){if("today"===a){var b=new Date;angular.isDate(k.$modelValue)?(a=new Date(k.$modelValue),a.setFullYear(b.getFullYear(),b.getMonth(),b.getDate())):a=new Date(b.setHours(0,0,0,0))}h.dateSelection(a)},h.close=function(){h.isOpen=!1,i[0].focus()};var u=a(q)(h);q.remove(),p?c.find("body").append(u):i.after(u),h.$on("$destroy",function(){u.remove(),i.unbind("keydown",t),c.unbind("click",s)})}}}]).directive("datepickerPopupWrap",function(){return{restrict:"EA",replace:!0,transclude:!0,templateUrl:"template/datepicker/popup.html",link:function(a,b){b.bind("click",function(a){a.preventDefault(),a.stopPropagation()})}}}),angular.module("ui.bootstrap.dropdown",[]).constant("dropdownConfig",{openClass:"open"}).service("dropdownService",["$document",function(a){var b=null;this.open=function(e){b||(a.bind("click",c),a.bind("keydown",d)),b&&b!==e&&(b.isOpen=!1),b=e},this.close=function(e){b===e&&(b=null,a.unbind("click",c),a.unbind("keydown",d))};var c=function(a){if(b){var c=b.getToggleElement();a&&c&&c[0].contains(a.target)||b.$apply(function(){b.isOpen=!1})}},d=function(a){27===a.which&&(b.focusToggleElement(),c())}}]).controller("DropdownController",["$scope","$attrs","$parse","dropdownConfig","dropdownService","$animate",function(a,b,c,d,e,f){var g,h=this,i=a.$new(),j=d.openClass,k=angular.noop,l=b.onToggle?c(b.onToggle):angular.noop;this.init=function(d){h.$element=d,b.isOpen&&(g=c(b.isOpen),k=g.assign,a.$watch(g,function(a){i.isOpen=!!a}))},this.toggle=function(a){return i.isOpen=arguments.length?!!a:!i.isOpen},this.isOpen=function(){return i.isOpen},i.getToggleElement=function(){return h.toggleElement},i.focusToggleElement=function(){h.toggleElement&&h.toggleElement[0].focus()},i.$watch("isOpen",function(b,c){f[b?"addClass":"removeClass"](h.$element,j),b?(i.focusToggleElement(),e.open(i)):e.close(i),k(a,b),angular.isDefined(b)&&b!==c&&l(a,{open:!!b})}),a.$on("$locationChangeSuccess",function(){i.isOpen=!1}),a.$on("$destroy",function(){i.$destroy()})}]).directive("dropdown",function(){return{controller:"DropdownController",link:function(a,b,c,d){d.init(b)}}}).directive("dropdownToggle",function(){return{require:"?^dropdown",link:function(a,b,c,d){if(d){d.toggleElement=b;var e=function(e){e.preventDefault(),b.hasClass("disabled")||c.disabled||a.$apply(function(){d.toggle()})};b.bind("click",e),b.attr({"aria-haspopup":!0,"aria-expanded":!1}),a.$watch(d.isOpen,function(a){b.attr("aria-expanded",!!a)}),a.$on("$destroy",function(){b.unbind("click",e)})}}}}),angular.module("ui.bootstrap.modal",["ui.bootstrap.transition"]).factory("$$stackedMap",function(){return{createNew:function(){var a=[];return{add:function(b,c){a.push({key:b,value:c})},get:function(b){for(var c=0;c0),i()})}function i(){if(k&&-1==g()){var a=l;j(k,l,150,function(){a.$destroy(),a=null}),k=void 0,l=void 0}}function j(c,d,e,f){function g(){g.done||(g.done=!0,c.remove(),f&&f())}d.animate=!1;var h=a.transitionEndEventName;if(h){var i=b(g,e);c.bind(h,function(){b.cancel(i),g(),d.$apply()})}else b(g)}var k,l,m="modal-open",n=f.createNew(),o={};return e.$watch(g,function(a){l&&(l.index=a)}),c.bind("keydown",function(a){var b;27===a.which&&(b=n.top(),b&&b.value.keyboard&&(a.preventDefault(),e.$apply(function(){o.dismiss(b.key,"escape key press")})))}),o.open=function(a,b){n.add(a,{deferred:b.deferred,modalScope:b.scope,backdrop:b.backdrop,keyboard:b.keyboard});var f=c.find("body").eq(0),h=g();if(h>=0&&!k){l=e.$new(!0),l.index=h;var i=angular.element("
");i.attr("backdrop-class",b.backdropClass),k=d(i)(l),f.append(k)}var j=angular.element("
");j.attr({"template-url":b.windowTemplateUrl,"window-class":b.windowClass,size:b.size,index:n.length()-1,animate:"animate"}).html(b.content);var o=d(j)(b.scope);n.top().value.modalDomEl=o,f.append(o),f.addClass(m)},o.close=function(a,b){var c=n.get(a);c&&(c.value.deferred.resolve(b),h(a))},o.dismiss=function(a,b){var c=n.get(a);c&&(c.value.deferred.reject(b),h(a))},o.dismissAll=function(a){for(var b=this.getTop();b;)this.dismiss(b.key,a),b=this.getTop()},o.getTop=function(){return n.top()},o}]).provider("$modal",function(){var a={options:{backdrop:!0,keyboard:!0},$get:["$injector","$rootScope","$q","$http","$templateCache","$controller","$modalStack",function(b,c,d,e,f,g,h){function i(a){return a.template?d.when(a.template):e.get(angular.isFunction(a.templateUrl)?a.templateUrl():a.templateUrl,{cache:f}).then(function(a){return a.data})}function j(a){var c=[];return angular.forEach(a,function(a){(angular.isFunction(a)||angular.isArray(a))&&c.push(d.when(b.invoke(a)))}),c}var k={};return k.open=function(b){var e=d.defer(),f=d.defer(),k={result:e.promise,opened:f.promise,close:function(a){h.close(k,a)},dismiss:function(a){h.dismiss(k,a)}};if(b=angular.extend({},a.options,b),b.resolve=b.resolve||{},!b.template&&!b.templateUrl)throw new Error("One of template or templateUrl options is required.");var l=d.all([i(b)].concat(j(b.resolve)));return l.then(function(a){var d=(b.scope||c).$new();d.$close=k.close,d.$dismiss=k.dismiss;var f,i={},j=1;b.controller&&(i.$scope=d,i.$modalInstance=k,angular.forEach(b.resolve,function(b,c){i[c]=a[j++]}),f=g(b.controller,i),b.controllerAs&&(d[b.controllerAs]=f)),h.open(k,{scope:d,deferred:e,content:a[0],backdrop:b.backdrop,keyboard:b.keyboard,backdropClass:b.backdropClass,windowClass:b.windowClass,windowTemplateUrl:b.windowTemplateUrl,size:b.size})},function(a){e.reject(a)}),l.then(function(){f.resolve(!0)},function(){f.reject(!1)}),k},k}]};return a}),angular.module("ui.bootstrap.pagination",[]).controller("PaginationController",["$scope","$attrs","$parse",function(a,b,c){var d=this,e={$setViewValue:angular.noop},f=b.numPages?c(b.numPages).assign:angular.noop;this.init=function(f,g){e=f,this.config=g,e.$render=function(){d.render()},b.itemsPerPage?a.$parent.$watch(c(b.itemsPerPage),function(b){d.itemsPerPage=parseInt(b,10),a.totalPages=d.calculateTotalPages()}):this.itemsPerPage=g.itemsPerPage},this.calculateTotalPages=function(){var b=this.itemsPerPage<1?1:Math.ceil(a.totalItems/this.itemsPerPage);return Math.max(b||0,1)},this.render=function(){a.page=parseInt(e.$viewValue,10)||1},a.selectPage=function(b){a.page!==b&&b>0&&b<=a.totalPages&&(e.$setViewValue(b),e.$render())},a.getText=function(b){return a[b+"Text"]||d.config[b+"Text"]},a.noPrevious=function(){return 1===a.page},a.noNext=function(){return a.page===a.totalPages},a.$watch("totalItems",function(){a.totalPages=d.calculateTotalPages()}),a.$watch("totalPages",function(b){f(a.$parent,b),a.page>b?a.selectPage(b):e.$render()})}]).constant("paginationConfig",{itemsPerPage:10,boundaryLinks:!1,directionLinks:!0,firstText:"First",previousText:"Previous",nextText:"Next",lastText:"Last",rotate:!0}).directive("pagination",["$parse","paginationConfig",function(a,b){return{restrict:"EA",scope:{totalItems:"=",firstText:"@",previousText:"@",nextText:"@",lastText:"@"},require:["pagination","?ngModel"],controller:"PaginationController",templateUrl:"template/pagination/pagination.html",replace:!0,link:function(c,d,e,f){function g(a,b,c){return{number:a,text:b,active:c}}function h(a,b){var c=[],d=1,e=b,f=angular.isDefined(k)&&b>k;f&&(l?(d=Math.max(a-Math.floor(k/2),1),e=d+k-1,e>b&&(e=b,d=e-k+1)):(d=(Math.ceil(a/k)-1)*k+1,e=Math.min(d+k-1,b)));for(var h=d;e>=h;h++){var i=g(h,h,h===a);c.push(i)}if(f&&!l){if(d>1){var j=g(d-1,"...",!1);c.unshift(j)}if(b>e){var m=g(e+1,"...",!1);c.push(m)}}return c}var i=f[0],j=f[1];if(j){var k=angular.isDefined(e.maxSize)?c.$parent.$eval(e.maxSize):b.maxSize,l=angular.isDefined(e.rotate)?c.$parent.$eval(e.rotate):b.rotate;c.boundaryLinks=angular.isDefined(e.boundaryLinks)?c.$parent.$eval(e.boundaryLinks):b.boundaryLinks,c.directionLinks=angular.isDefined(e.directionLinks)?c.$parent.$eval(e.directionLinks):b.directionLinks,i.init(j,b),e.maxSize&&c.$parent.$watch(a(e.maxSize),function(a){k=parseInt(a,10),i.render() +});var m=i.render;i.render=function(){m(),c.page>0&&c.page<=c.totalPages&&(c.pages=h(c.page,c.totalPages))}}}}}]).constant("pagerConfig",{itemsPerPage:10,previousText:"« Previous",nextText:"Next »",align:!0}).directive("pager",["pagerConfig",function(a){return{restrict:"EA",scope:{totalItems:"=",previousText:"@",nextText:"@"},require:["pager","?ngModel"],controller:"PaginationController",templateUrl:"template/pagination/pager.html",replace:!0,link:function(b,c,d,e){var f=e[0],g=e[1];g&&(b.align=angular.isDefined(d.align)?b.$parent.$eval(d.align):a.align,f.init(g,a))}}}]),angular.module("ui.bootstrap.tooltip",["ui.bootstrap.position","ui.bootstrap.bindHtml"]).provider("$tooltip",function(){function a(a){var b=/[A-Z]/g,c="-";return a.replace(b,function(a,b){return(b?c:"")+a.toLowerCase()})}var b={placement:"top",animation:!0,popupDelay:0},c={mouseenter:"mouseleave",click:"click",focus:"blur"},d={};this.options=function(a){angular.extend(d,a)},this.setTriggers=function(a){angular.extend(c,a)},this.$get=["$window","$compile","$timeout","$document","$position","$interpolate",function(e,f,g,h,i,j){return function(e,k,l){function m(a){var b=a||n.trigger||l,d=c[b]||b;return{show:b,hide:d}}var n=angular.extend({},b,d),o=a(e),p=j.startSymbol(),q=j.endSymbol(),r="
';return{restrict:"EA",compile:function(){var a=f(r);return function(b,c,d){function f(){D.isOpen?l():j()}function j(){(!C||b.$eval(d[k+"Enable"]))&&(s(),D.popupDelay?z||(z=g(o,D.popupDelay,!1),z.then(function(a){a()})):o()())}function l(){b.$apply(function(){p()})}function o(){return z=null,y&&(g.cancel(y),y=null),D.content?(q(),w.css({top:0,left:0,display:"block"}),A?h.find("body").append(w):c.after(w),E(),D.isOpen=!0,D.$digest(),E):angular.noop}function p(){D.isOpen=!1,g.cancel(z),z=null,D.animation?y||(y=g(r,500)):r()}function q(){w&&r(),x=D.$new(),w=a(x,angular.noop)}function r(){y=null,w&&(w.remove(),w=null),x&&(x.$destroy(),x=null)}function s(){t(),u()}function t(){var a=d[k+"Placement"];D.placement=angular.isDefined(a)?a:n.placement}function u(){var a=d[k+"PopupDelay"],b=parseInt(a,10);D.popupDelay=isNaN(b)?n.popupDelay:b}function v(){var a=d[k+"Trigger"];F(),B=m(a),B.show===B.hide?c.bind(B.show,f):(c.bind(B.show,j),c.bind(B.hide,l))}var w,x,y,z,A=angular.isDefined(n.appendToBody)?n.appendToBody:!1,B=m(void 0),C=angular.isDefined(d[k+"Enable"]),D=b.$new(!0),E=function(){var a=i.positionElements(c,w,D.placement,A);a.top+="px",a.left+="px",w.css(a)};D.isOpen=!1,d.$observe(e,function(a){D.content=a,!a&&D.isOpen&&p()}),d.$observe(k+"Title",function(a){D.title=a});var F=function(){c.unbind(B.show,j),c.unbind(B.hide,l)};v();var G=b.$eval(d[k+"Animation"]);D.animation=angular.isDefined(G)?!!G:n.animation;var H=b.$eval(d[k+"AppendToBody"]);A=angular.isDefined(H)?H:A,A&&b.$on("$locationChangeSuccess",function(){D.isOpen&&p()}),b.$on("$destroy",function(){g.cancel(y),g.cancel(z),F(),r(),D=null})}}}}}]}).directive("tooltipPopup",function(){return{restrict:"EA",replace:!0,scope:{content:"@",placement:"@",animation:"&",isOpen:"&"},templateUrl:"template/tooltip/tooltip-popup.html"}}).directive("tooltip",["$tooltip",function(a){return a("tooltip","tooltip","mouseenter")}]).directive("tooltipHtmlUnsafePopup",function(){return{restrict:"EA",replace:!0,scope:{content:"@",placement:"@",animation:"&",isOpen:"&"},templateUrl:"template/tooltip/tooltip-html-unsafe-popup.html"}}).directive("tooltipHtmlUnsafe",["$tooltip",function(a){return a("tooltipHtmlUnsafe","tooltip","mouseenter")}]),angular.module("ui.bootstrap.popover",["ui.bootstrap.tooltip"]).directive("popoverPopup",function(){return{restrict:"EA",replace:!0,scope:{title:"@",content:"@",placement:"@",animation:"&",isOpen:"&"},templateUrl:"template/popover/popover.html"}}).directive("popover",["$tooltip",function(a){return a("popover","popover","click")}]),angular.module("ui.bootstrap.progressbar",[]).constant("progressConfig",{animate:!0,max:100}).controller("ProgressController",["$scope","$attrs","progressConfig",function(a,b,c){var d=this,e=angular.isDefined(b.animate)?a.$parent.$eval(b.animate):c.animate;this.bars=[],a.max=angular.isDefined(b.max)?a.$parent.$eval(b.max):c.max,this.addBar=function(b,c){e||c.css({transition:"none"}),this.bars.push(b),b.$watch("value",function(c){b.percent=+(100*c/a.max).toFixed(2)}),b.$on("$destroy",function(){c=null,d.removeBar(b)})},this.removeBar=function(a){this.bars.splice(this.bars.indexOf(a),1)}}]).directive("progress",function(){return{restrict:"EA",replace:!0,transclude:!0,controller:"ProgressController",require:"progress",scope:{},templateUrl:"template/progressbar/progress.html"}}).directive("bar",function(){return{restrict:"EA",replace:!0,transclude:!0,require:"^progress",scope:{value:"=",type:"@"},templateUrl:"template/progressbar/bar.html",link:function(a,b,c,d){d.addBar(a,b)}}}).directive("progressbar",function(){return{restrict:"EA",replace:!0,transclude:!0,controller:"ProgressController",scope:{value:"=",type:"@"},templateUrl:"template/progressbar/progressbar.html",link:function(a,b,c,d){d.addBar(a,angular.element(b.children()[0]))}}}),angular.module("ui.bootstrap.rating",[]).constant("ratingConfig",{max:5,stateOn:null,stateOff:null}).controller("RatingController",["$scope","$attrs","ratingConfig",function(a,b,c){var d={$setViewValue:angular.noop};this.init=function(e){d=e,d.$render=this.render,this.stateOn=angular.isDefined(b.stateOn)?a.$parent.$eval(b.stateOn):c.stateOn,this.stateOff=angular.isDefined(b.stateOff)?a.$parent.$eval(b.stateOff):c.stateOff;var f=angular.isDefined(b.ratingStates)?a.$parent.$eval(b.ratingStates):new Array(angular.isDefined(b.max)?a.$parent.$eval(b.max):c.max);a.range=this.buildTemplateObjects(f)},this.buildTemplateObjects=function(a){for(var b=0,c=a.length;c>b;b++)a[b]=angular.extend({index:b},{stateOn:this.stateOn,stateOff:this.stateOff},a[b]);return a},a.rate=function(b){!a.readonly&&b>=0&&b<=a.range.length&&(d.$setViewValue(b),d.$render())},a.enter=function(b){a.readonly||(a.value=b),a.onHover({value:b})},a.reset=function(){a.value=d.$viewValue,a.onLeave()},a.onKeydown=function(b){/(37|38|39|40)/.test(b.which)&&(b.preventDefault(),b.stopPropagation(),a.rate(a.value+(38===b.which||39===b.which?1:-1)))},this.render=function(){a.value=d.$viewValue}}]).directive("rating",function(){return{restrict:"EA",require:["rating","ngModel"],scope:{readonly:"=?",onHover:"&",onLeave:"&"},controller:"RatingController",templateUrl:"template/rating/rating.html",replace:!0,link:function(a,b,c,d){var e=d[0],f=d[1];f&&e.init(f)}}}),angular.module("ui.bootstrap.tabs",[]).controller("TabsetController",["$scope",function(a){var b=this,c=b.tabs=a.tabs=[];b.select=function(a){angular.forEach(c,function(b){b.active&&b!==a&&(b.active=!1,b.onDeselect())}),a.active=!0,a.onSelect()},b.addTab=function(a){c.push(a),1===c.length?a.active=!0:a.active&&b.select(a)},b.removeTab=function(a){var e=c.indexOf(a);if(a.active&&c.length>1&&!d){var f=e==c.length-1?e-1:e+1;b.select(c[f])}c.splice(e,1)};var d;a.$on("$destroy",function(){d=!0})}]).directive("tabset",function(){return{restrict:"EA",transclude:!0,replace:!0,scope:{type:"@"},controller:"TabsetController",templateUrl:"template/tabs/tabset.html",link:function(a,b,c){a.vertical=angular.isDefined(c.vertical)?a.$parent.$eval(c.vertical):!1,a.justified=angular.isDefined(c.justified)?a.$parent.$eval(c.justified):!1}}}).directive("tab",["$parse",function(a){return{require:"^tabset",restrict:"EA",replace:!0,templateUrl:"template/tabs/tab.html",transclude:!0,scope:{active:"=?",heading:"@",onSelect:"&select",onDeselect:"&deselect"},controller:function(){},compile:function(b,c,d){return function(b,c,e,f){b.$watch("active",function(a){a&&f.select(b)}),b.disabled=!1,e.disabled&&b.$parent.$watch(a(e.disabled),function(a){b.disabled=!!a}),b.select=function(){b.disabled||(b.active=!0)},f.addTab(b),b.$on("$destroy",function(){f.removeTab(b)}),b.$transcludeFn=d}}}}]).directive("tabHeadingTransclude",[function(){return{restrict:"A",require:"^tab",link:function(a,b){a.$watch("headingElement",function(a){a&&(b.html(""),b.append(a))})}}}]).directive("tabContentTransclude",function(){function a(a){return a.tagName&&(a.hasAttribute("tab-heading")||a.hasAttribute("data-tab-heading")||"tab-heading"===a.tagName.toLowerCase()||"data-tab-heading"===a.tagName.toLowerCase())}return{restrict:"A",require:"^tabset",link:function(b,c,d){var e=b.$eval(d.tabContentTransclude);e.$transcludeFn(e.$parent,function(b){angular.forEach(b,function(b){a(b)?e.headingElement=b:c.append(b)})})}}}),angular.module("ui.bootstrap.timepicker",[]).constant("timepickerConfig",{hourStep:1,minuteStep:1,showMeridian:!0,meridians:null,readonlyInput:!1,mousewheel:!0}).controller("TimepickerController",["$scope","$attrs","$parse","$log","$locale","timepickerConfig",function(a,b,c,d,e,f){function g(){var b=parseInt(a.hours,10),c=a.showMeridian?b>0&&13>b:b>=0&&24>b;return c?(a.showMeridian&&(12===b&&(b=0),a.meridian===p[1]&&(b+=12)),b):void 0}function h(){var b=parseInt(a.minutes,10);return b>=0&&60>b?b:void 0}function i(a){return angular.isDefined(a)&&a.toString().length<2?"0"+a:a}function j(a){k(),o.$setViewValue(new Date(n)),l(a)}function k(){o.$setValidity("time",!0),a.invalidHours=!1,a.invalidMinutes=!1}function l(b){var c=n.getHours(),d=n.getMinutes();a.showMeridian&&(c=0===c||12===c?12:c%12),a.hours="h"===b?c:i(c),a.minutes="m"===b?d:i(d),a.meridian=n.getHours()<12?p[0]:p[1]}function m(a){var b=new Date(n.getTime()+6e4*a);n.setHours(b.getHours(),b.getMinutes()),j()}var n=new Date,o={$setViewValue:angular.noop},p=angular.isDefined(b.meridians)?a.$parent.$eval(b.meridians):f.meridians||e.DATETIME_FORMATS.AMPMS;this.init=function(c,d){o=c,o.$render=this.render;var e=d.eq(0),g=d.eq(1),h=angular.isDefined(b.mousewheel)?a.$parent.$eval(b.mousewheel):f.mousewheel;h&&this.setupMousewheelEvents(e,g),a.readonlyInput=angular.isDefined(b.readonlyInput)?a.$parent.$eval(b.readonlyInput):f.readonlyInput,this.setupInputEvents(e,g)};var q=f.hourStep;b.hourStep&&a.$parent.$watch(c(b.hourStep),function(a){q=parseInt(a,10)});var r=f.minuteStep;b.minuteStep&&a.$parent.$watch(c(b.minuteStep),function(a){r=parseInt(a,10)}),a.showMeridian=f.showMeridian,b.showMeridian&&a.$parent.$watch(c(b.showMeridian),function(b){if(a.showMeridian=!!b,o.$error.time){var c=g(),d=h();angular.isDefined(c)&&angular.isDefined(d)&&(n.setHours(c),j())}else l()}),this.setupMousewheelEvents=function(b,c){var d=function(a){a.originalEvent&&(a=a.originalEvent);var b=a.wheelDelta?a.wheelDelta:-a.deltaY;return a.detail||b>0};b.bind("mousewheel wheel",function(b){a.$apply(d(b)?a.incrementHours():a.decrementHours()),b.preventDefault()}),c.bind("mousewheel wheel",function(b){a.$apply(d(b)?a.incrementMinutes():a.decrementMinutes()),b.preventDefault()})},this.setupInputEvents=function(b,c){if(a.readonlyInput)return a.updateHours=angular.noop,void(a.updateMinutes=angular.noop);var d=function(b,c){o.$setViewValue(null),o.$setValidity("time",!1),angular.isDefined(b)&&(a.invalidHours=b),angular.isDefined(c)&&(a.invalidMinutes=c)};a.updateHours=function(){var a=g();angular.isDefined(a)?(n.setHours(a),j("h")):d(!0)},b.bind("blur",function(){!a.invalidHours&&a.hours<10&&a.$apply(function(){a.hours=i(a.hours)})}),a.updateMinutes=function(){var a=h();angular.isDefined(a)?(n.setMinutes(a),j("m")):d(void 0,!0)},c.bind("blur",function(){!a.invalidMinutes&&a.minutes<10&&a.$apply(function(){a.minutes=i(a.minutes)})})},this.render=function(){var a=o.$modelValue?new Date(o.$modelValue):null;isNaN(a)?(o.$setValidity("time",!1),d.error('Timepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.')):(a&&(n=a),k(),l())},a.incrementHours=function(){m(60*q)},a.decrementHours=function(){m(60*-q)},a.incrementMinutes=function(){m(r)},a.decrementMinutes=function(){m(-r)},a.toggleMeridian=function(){m(720*(n.getHours()<12?1:-1))}}]).directive("timepicker",function(){return{restrict:"EA",require:["timepicker","?^ngModel"],controller:"TimepickerController",replace:!0,scope:{},templateUrl:"template/timepicker/timepicker.html",link:function(a,b,c,d){var e=d[0],f=d[1];f&&e.init(f,b.find("input"))}}}),angular.module("ui.bootstrap.typeahead",["ui.bootstrap.position","ui.bootstrap.bindHtml"]).factory("typeaheadParser",["$parse",function(a){var b=/^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w\d]*))\s+in\s+([\s\S]+?)$/;return{parse:function(c){var d=c.match(b);if(!d)throw new Error('Expected typeahead specification in form of "_modelValue_ (as _label_)? for _item_ in _collection_" but got "'+c+'".');return{itemName:d[3],source:a(d[4]),viewMapper:a(d[2]||d[1]),modelMapper:a(d[1])}}}}]).directive("typeahead",["$compile","$parse","$q","$timeout","$document","$position","typeaheadParser",function(a,b,c,d,e,f,g){var h=[9,13,27,38,40];return{require:"ngModel",link:function(i,j,k,l){var m,n=i.$eval(k.typeaheadMinLength)||1,o=i.$eval(k.typeaheadWaitMs)||0,p=i.$eval(k.typeaheadEditable)!==!1,q=b(k.typeaheadLoading).assign||angular.noop,r=b(k.typeaheadOnSelect),s=k.typeaheadInputFormatter?b(k.typeaheadInputFormatter):void 0,t=k.typeaheadAppendToBody?i.$eval(k.typeaheadAppendToBody):!1,u=i.$eval(k.typeaheadFocusFirst)!==!1,v=b(k.ngModel).assign,w=g.parse(k.typeahead),x=i.$new();i.$on("$destroy",function(){x.$destroy()});var y="typeahead-"+x.$id+"-"+Math.floor(1e4*Math.random());j.attr({"aria-autocomplete":"list","aria-expanded":!1,"aria-owns":y});var z=angular.element("
");z.attr({id:y,matches:"matches",active:"activeIdx",select:"select(activeIdx)",query:"query",position:"position"}),angular.isDefined(k.typeaheadTemplateUrl)&&z.attr("template-url",k.typeaheadTemplateUrl);var A=function(){x.matches=[],x.activeIdx=-1,j.attr("aria-expanded",!1)},B=function(a){return y+"-option-"+a};x.$watch("activeIdx",function(a){0>a?j.removeAttr("aria-activedescendant"):j.attr("aria-activedescendant",B(a))});var C=function(a){var b={$viewValue:a};q(i,!0),c.when(w.source(i,b)).then(function(c){var d=a===l.$viewValue;if(d&&m)if(c.length>0){x.activeIdx=u?0:-1,x.matches.length=0;for(var e=0;e=n?o>0?(F(),E(a)):C(a):(q(i,!1),F(),A()),p?a:a?void l.$setValidity("editable",!1):(l.$setValidity("editable",!0),a)}),l.$formatters.push(function(a){var b,c,d={};return s?(d.$model=a,s(i,d)):(d[w.itemName]=a,b=w.viewMapper(i,d),d[w.itemName]=void 0,c=w.viewMapper(i,d),b!==c?b:a)}),x.select=function(a){var b,c,e={};e[w.itemName]=c=x.matches[a].model,b=w.modelMapper(i,e),v(i,b),l.$setValidity("editable",!0),r(i,{$item:c,$model:b,$label:w.viewMapper(i,e)}),A(),d(function(){j[0].focus()},0,!1)},j.bind("keydown",function(a){0!==x.matches.length&&-1!==h.indexOf(a.which)&&(-1!=x.activeIdx||13!==a.which&&9!==a.which)&&(a.preventDefault(),40===a.which?(x.activeIdx=(x.activeIdx+1)%x.matches.length,x.$digest()):38===a.which?(x.activeIdx=(x.activeIdx>0?x.activeIdx:x.matches.length)-1,x.$digest()):13===a.which||9===a.which?x.$apply(function(){x.select(x.activeIdx)}):27===a.which&&(a.stopPropagation(),A(),x.$digest()))}),j.bind("blur",function(){m=!1});var G=function(a){j[0]!==a.target&&(A(),x.$digest())};e.bind("click",G),i.$on("$destroy",function(){e.unbind("click",G),t&&H.remove()});var H=a(z)(x);t?e.find("body").append(H):j.after(H)}}}]).directive("typeaheadPopup",function(){return{restrict:"EA",scope:{matches:"=",query:"=",active:"=",position:"=",select:"&"},replace:!0,templateUrl:"template/typeahead/typeahead-popup.html",link:function(a,b,c){a.templateUrl=c.templateUrl,a.isOpen=function(){return a.matches.length>0},a.isActive=function(b){return a.active==b},a.selectActive=function(b){a.active=b},a.selectMatch=function(b){a.select({activeIdx:b})}}}}).directive("typeaheadMatch",["$http","$templateCache","$compile","$parse",function(a,b,c,d){return{restrict:"EA",scope:{index:"=",match:"=",query:"="},link:function(e,f,g){var h=d(g.templateUrl)(e.$parent)||"template/typeahead/typeahead-match.html";a.get(h,{cache:b}).success(function(a){f.replaceWith(c(a.trim())(e))})}}}]).filter("typeaheadHighlight",function(){function a(a){return a.replace(/([.?*+^$[\]\\(){}|-])/g,"\\$1")}return function(b,c){return c?(""+b).replace(new RegExp(a(c),"gi"),"$&"):b}}),angular.module("template/accordion/accordion-group.html",[]).run(["$templateCache",function(a){a.put("template/accordion/accordion-group.html",'
\n \n
\n
\n
\n
\n')}]),angular.module("template/accordion/accordion.html",[]).run(["$templateCache",function(a){a.put("template/accordion/accordion.html",'
')}]),angular.module("template/alert/alert.html",[]).run(["$templateCache",function(a){a.put("template/alert/alert.html",'\n')}]),angular.module("template/carousel/carousel.html",[]).run(["$templateCache",function(a){a.put("template/carousel/carousel.html",'\n')}]),angular.module("template/carousel/slide.html",[]).run(["$templateCache",function(a){a.put("template/carousel/slide.html","
\n")}]),angular.module("template/datepicker/datepicker.html",[]).run(["$templateCache",function(a){a.put("template/datepicker/datepicker.html",'
\n \n \n \n
')}]),angular.module("template/datepicker/day.html",[]).run(["$templateCache",function(a){a.put("template/datepicker/day.html",'\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
{{label.abbr}}
{{ weekNumbers[$index] }}\n \n
\n')}]),angular.module("template/datepicker/month.html",[]).run(["$templateCache",function(a){a.put("template/datepicker/month.html",'\n \n \n \n \n \n \n \n \n \n \n \n \n
\n \n
\n')}]),angular.module("template/datepicker/popup.html",[]).run(["$templateCache",function(a){a.put("template/datepicker/popup.html",'\n')}]),angular.module("template/datepicker/year.html",[]).run(["$templateCache",function(a){a.put("template/datepicker/year.html",'\n \n \n \n \n \n \n \n \n \n \n \n \n
\n \n
\n')}]),angular.module("template/modal/backdrop.html",[]).run(["$templateCache",function(a){a.put("template/modal/backdrop.html",'\n')}]),angular.module("template/modal/window.html",[]).run(["$templateCache",function(a){a.put("template/modal/window.html",'')}]),angular.module("template/pagination/pager.html",[]).run(["$templateCache",function(a){a.put("template/pagination/pager.html",'')}]),angular.module("template/pagination/pagination.html",[]).run(["$templateCache",function(a){a.put("template/pagination/pagination.html",'')}]),angular.module("template/tooltip/tooltip-html-unsafe-popup.html",[]).run(["$templateCache",function(a){a.put("template/tooltip/tooltip-html-unsafe-popup.html",'
\n
\n
\n
\n')}]),angular.module("template/tooltip/tooltip-popup.html",[]).run(["$templateCache",function(a){a.put("template/tooltip/tooltip-popup.html",'
\n
\n
\n
\n')}]),angular.module("template/popover/popover.html",[]).run(["$templateCache",function(a){a.put("template/popover/popover.html",'
\n
\n\n
\n

\n
\n
\n
\n')}]),angular.module("template/progressbar/bar.html",[]).run(["$templateCache",function(a){a.put("template/progressbar/bar.html",'
')}]),angular.module("template/progressbar/progress.html",[]).run(["$templateCache",function(a){a.put("template/progressbar/progress.html",'
')}]),angular.module("template/progressbar/progressbar.html",[]).run(["$templateCache",function(a){a.put("template/progressbar/progressbar.html",'
\n
\n
')}]),angular.module("template/rating/rating.html",[]).run(["$templateCache",function(a){a.put("template/rating/rating.html",'\n \n ({{ $index < value ? \'*\' : \' \' }})\n \n')}]),angular.module("template/tabs/tab.html",[]).run(["$templateCache",function(a){a.put("template/tabs/tab.html",'
  • \n {{heading}}\n
  • \n')}]),angular.module("template/tabs/tabset.html",[]).run(["$templateCache",function(a){a.put("template/tabs/tabset.html",'
    \n \n
    \n
    \n
    \n
    \n
    \n')}]),angular.module("template/timepicker/timepicker.html",[]).run(["$templateCache",function(a){a.put("template/timepicker/timepicker.html",'\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
     
    \n \n :\n \n
     
    \n')}]),angular.module("template/typeahead/typeahead-match.html",[]).run(["$templateCache",function(a){a.put("template/typeahead/typeahead-match.html",'') +}]),angular.module("template/typeahead/typeahead-popup.html",[]).run(["$templateCache",function(a){a.put("template/typeahead/typeahead-popup.html",'\n')}]); \ No newline at end of file diff --git a/html/angularjs/ui-utils-0.2.1.zip b/html/angularjs/ui-utils-0.2.1.zip new file mode 100644 index 0000000..7dffc5b Binary files /dev/null and b/html/angularjs/ui-utils-0.2.1.zip differ diff --git a/html/bootstrap-3.3.0-dist.zip b/html/bootstrap-3.3.0-dist.zip new file mode 100644 index 0000000..01a5051 Binary files /dev/null and b/html/bootstrap-3.3.0-dist.zip differ diff --git a/html/contexthelp/A1.html b/html/contexthelp/A1.html index e40ba28..465430b 100644 --- a/html/contexthelp/A1.html +++ b/html/contexthelp/A1.html @@ -26,7 +26,7 @@ Context-sensitive help is not yet available.

    -For more information, please visit the main Nagios website at http://www.nagios.org. +For more information, please visit the main Nagios website at https://www.nagios.org.

    diff --git a/html/contexthelp/A2.html b/html/contexthelp/A2.html index e40ba28..465430b 100644 --- a/html/contexthelp/A2.html +++ b/html/contexthelp/A2.html @@ -26,7 +26,7 @@ Context-sensitive help is not yet available.

    -For more information, please visit the main Nagios website at http://www.nagios.org. +For more information, please visit the main Nagios website at https://www.nagios.org.

    diff --git a/html/contexthelp/A3.html b/html/contexthelp/A3.html index e40ba28..465430b 100644 --- a/html/contexthelp/A3.html +++ b/html/contexthelp/A3.html @@ -26,7 +26,7 @@ Context-sensitive help is not yet available.

    -For more information, please visit the main Nagios website at http://www.nagios.org. +For more information, please visit the main Nagios website at https://www.nagios.org.

    diff --git a/html/contexthelp/A4.html b/html/contexthelp/A4.html index e40ba28..465430b 100644 --- a/html/contexthelp/A4.html +++ b/html/contexthelp/A4.html @@ -26,7 +26,7 @@ Context-sensitive help is not yet available.

    -For more information, please visit the main Nagios website at http://www.nagios.org. +For more information, please visit the main Nagios website at https://www.nagios.org.

    diff --git a/html/contexthelp/A5.html b/html/contexthelp/A5.html index e40ba28..465430b 100644 --- a/html/contexthelp/A5.html +++ b/html/contexthelp/A5.html @@ -26,7 +26,7 @@ Context-sensitive help is not yet available.

    -For more information, please visit the main Nagios website at http://www.nagios.org. +For more information, please visit the main Nagios website at https://www.nagios.org.

    diff --git a/html/contexthelp/A6.html b/html/contexthelp/A6.html index e40ba28..465430b 100644 --- a/html/contexthelp/A6.html +++ b/html/contexthelp/A6.html @@ -26,7 +26,7 @@ Context-sensitive help is not yet available.

    -For more information, please visit the main Nagios website at http://www.nagios.org. +For more information, please visit the main Nagios website at https://www.nagios.org.

    diff --git a/html/contexthelp/A7.html b/html/contexthelp/A7.html index e40ba28..465430b 100644 --- a/html/contexthelp/A7.html +++ b/html/contexthelp/A7.html @@ -26,7 +26,7 @@ Context-sensitive help is not yet available.

    -For more information, please visit the main Nagios website at http://www.nagios.org. +For more information, please visit the main Nagios website at https://www.nagios.org.

    diff --git a/html/contexthelp/B1.html b/html/contexthelp/B1.html index e40ba28..465430b 100644 --- a/html/contexthelp/B1.html +++ b/html/contexthelp/B1.html @@ -26,7 +26,7 @@ Context-sensitive help is not yet available.

    -For more information, please visit the main Nagios website at http://www.nagios.org. +For more information, please visit the main Nagios website at https://www.nagios.org.

    diff --git a/html/contexthelp/C1.html b/html/contexthelp/C1.html index e40ba28..465430b 100644 --- a/html/contexthelp/C1.html +++ b/html/contexthelp/C1.html @@ -26,7 +26,7 @@ Context-sensitive help is not yet available.

    -For more information, please visit the main Nagios website at http://www.nagios.org. +For more information, please visit the main Nagios website at https://www.nagios.org.

    diff --git a/html/contexthelp/D1.html b/html/contexthelp/D1.html index e40ba28..465430b 100644 --- a/html/contexthelp/D1.html +++ b/html/contexthelp/D1.html @@ -26,7 +26,7 @@ Context-sensitive help is not yet available.

    -For more information, please visit the main Nagios website at http://www.nagios.org. +For more information, please visit the main Nagios website at https://www.nagios.org.

    diff --git a/html/contexthelp/E1.html b/html/contexthelp/E1.html index e40ba28..465430b 100644 --- a/html/contexthelp/E1.html +++ b/html/contexthelp/E1.html @@ -26,7 +26,7 @@ Context-sensitive help is not yet available.

    -For more information, please visit the main Nagios website at http://www.nagios.org. +For more information, please visit the main Nagios website at https://www.nagios.org.

    diff --git a/html/contexthelp/F1.html b/html/contexthelp/F1.html index e40ba28..465430b 100644 --- a/html/contexthelp/F1.html +++ b/html/contexthelp/F1.html @@ -26,7 +26,7 @@ Context-sensitive help is not yet available.

    -For more information, please visit the main Nagios website at http://www.nagios.org. +For more information, please visit the main Nagios website at https://www.nagios.org.

    diff --git a/html/contexthelp/G1.html b/html/contexthelp/G1.html index e40ba28..465430b 100644 --- a/html/contexthelp/G1.html +++ b/html/contexthelp/G1.html @@ -26,7 +26,7 @@ Context-sensitive help is not yet available.

    -For more information, please visit the main Nagios website at http://www.nagios.org. +For more information, please visit the main Nagios website at https://www.nagios.org.

    diff --git a/html/contexthelp/G2.html b/html/contexthelp/G2.html index e40ba28..465430b 100644 --- a/html/contexthelp/G2.html +++ b/html/contexthelp/G2.html @@ -26,7 +26,7 @@ Context-sensitive help is not yet available.

    -For more information, please visit the main Nagios website at http://www.nagios.org. +For more information, please visit the main Nagios website at https://www.nagios.org.

    diff --git a/html/contexthelp/G3.html b/html/contexthelp/G3.html index e40ba28..465430b 100644 --- a/html/contexthelp/G3.html +++ b/html/contexthelp/G3.html @@ -26,7 +26,7 @@ Context-sensitive help is not yet available.

    -For more information, please visit the main Nagios website at http://www.nagios.org. +For more information, please visit the main Nagios website at https://www.nagios.org.

    diff --git a/html/contexthelp/G4.html b/html/contexthelp/G4.html index e40ba28..465430b 100644 --- a/html/contexthelp/G4.html +++ b/html/contexthelp/G4.html @@ -26,7 +26,7 @@ Context-sensitive help is not yet available.

    -For more information, please visit the main Nagios website at http://www.nagios.org. +For more information, please visit the main Nagios website at https://www.nagios.org.

    diff --git a/html/contexthelp/G5.html b/html/contexthelp/G5.html index e40ba28..465430b 100644 --- a/html/contexthelp/G5.html +++ b/html/contexthelp/G5.html @@ -26,7 +26,7 @@ Context-sensitive help is not yet available.

    -For more information, please visit the main Nagios website at http://www.nagios.org. +For more information, please visit the main Nagios website at https://www.nagios.org.

    diff --git a/html/contexthelp/G6.html b/html/contexthelp/G6.html index e40ba28..465430b 100644 --- a/html/contexthelp/G6.html +++ b/html/contexthelp/G6.html @@ -26,7 +26,7 @@ Context-sensitive help is not yet available.

    -For more information, please visit the main Nagios website at http://www.nagios.org. +For more information, please visit the main Nagios website at https://www.nagios.org.

    diff --git a/html/contexthelp/H1.html b/html/contexthelp/H1.html index e40ba28..465430b 100644 --- a/html/contexthelp/H1.html +++ b/html/contexthelp/H1.html @@ -26,7 +26,7 @@ Context-sensitive help is not yet available.

    -For more information, please visit the main Nagios website at http://www.nagios.org. +For more information, please visit the main Nagios website at https://www.nagios.org.

    diff --git a/html/contexthelp/H2.html b/html/contexthelp/H2.html index e40ba28..465430b 100644 --- a/html/contexthelp/H2.html +++ b/html/contexthelp/H2.html @@ -26,7 +26,7 @@ Context-sensitive help is not yet available.

    -For more information, please visit the main Nagios website at http://www.nagios.org. +For more information, please visit the main Nagios website at https://www.nagios.org.

    diff --git a/html/contexthelp/H3.html b/html/contexthelp/H3.html index e40ba28..465430b 100644 --- a/html/contexthelp/H3.html +++ b/html/contexthelp/H3.html @@ -26,7 +26,7 @@ Context-sensitive help is not yet available.

    -For more information, please visit the main Nagios website at http://www.nagios.org. +For more information, please visit the main Nagios website at https://www.nagios.org.

    diff --git a/html/contexthelp/H4.html b/html/contexthelp/H4.html index e40ba28..465430b 100644 --- a/html/contexthelp/H4.html +++ b/html/contexthelp/H4.html @@ -26,7 +26,7 @@ Context-sensitive help is not yet available.

    -For more information, please visit the main Nagios website at http://www.nagios.org. +For more information, please visit the main Nagios website at https://www.nagios.org.

    diff --git a/html/contexthelp/H5.html b/html/contexthelp/H5.html index e40ba28..465430b 100644 --- a/html/contexthelp/H5.html +++ b/html/contexthelp/H5.html @@ -26,7 +26,7 @@ Context-sensitive help is not yet available.

    -For more information, please visit the main Nagios website at http://www.nagios.org. +For more information, please visit the main Nagios website at https://www.nagios.org.

    diff --git a/html/contexthelp/H6.html b/html/contexthelp/H6.html index e40ba28..465430b 100644 --- a/html/contexthelp/H6.html +++ b/html/contexthelp/H6.html @@ -26,7 +26,7 @@ Context-sensitive help is not yet available.

    -For more information, please visit the main Nagios website at http://www.nagios.org. +For more information, please visit the main Nagios website at https://www.nagios.org.

    diff --git a/html/contexthelp/H7.html b/html/contexthelp/H7.html index e40ba28..465430b 100644 --- a/html/contexthelp/H7.html +++ b/html/contexthelp/H7.html @@ -26,7 +26,7 @@ Context-sensitive help is not yet available.

    -For more information, please visit the main Nagios website at http://www.nagios.org. +For more information, please visit the main Nagios website at https://www.nagios.org.

    diff --git a/html/contexthelp/H8.html b/html/contexthelp/H8.html index e40ba28..465430b 100644 --- a/html/contexthelp/H8.html +++ b/html/contexthelp/H8.html @@ -26,7 +26,7 @@ Context-sensitive help is not yet available.

    -For more information, please visit the main Nagios website at http://www.nagios.org. +For more information, please visit the main Nagios website at https://www.nagios.org.

    diff --git a/html/contexthelp/I1.html b/html/contexthelp/I1.html index e40ba28..465430b 100644 --- a/html/contexthelp/I1.html +++ b/html/contexthelp/I1.html @@ -26,7 +26,7 @@ Context-sensitive help is not yet available.

    -For more information, please visit the main Nagios website at http://www.nagios.org. +For more information, please visit the main Nagios website at https://www.nagios.org.

    diff --git a/html/contexthelp/I2.html b/html/contexthelp/I2.html index e40ba28..465430b 100644 --- a/html/contexthelp/I2.html +++ b/html/contexthelp/I2.html @@ -26,7 +26,7 @@ Context-sensitive help is not yet available.

    -For more information, please visit the main Nagios website at http://www.nagios.org. +For more information, please visit the main Nagios website at https://www.nagios.org.

    diff --git a/html/contexthelp/I3.html b/html/contexthelp/I3.html index e40ba28..465430b 100644 --- a/html/contexthelp/I3.html +++ b/html/contexthelp/I3.html @@ -26,7 +26,7 @@ Context-sensitive help is not yet available.

    -For more information, please visit the main Nagios website at http://www.nagios.org. +For more information, please visit the main Nagios website at https://www.nagios.org.

    diff --git a/html/contexthelp/I4.html b/html/contexthelp/I4.html index e40ba28..465430b 100644 --- a/html/contexthelp/I4.html +++ b/html/contexthelp/I4.html @@ -26,7 +26,7 @@ Context-sensitive help is not yet available.

    -For more information, please visit the main Nagios website at http://www.nagios.org. +For more information, please visit the main Nagios website at https://www.nagios.org.

    diff --git a/html/contexthelp/I5.html b/html/contexthelp/I5.html index e40ba28..465430b 100644 --- a/html/contexthelp/I5.html +++ b/html/contexthelp/I5.html @@ -26,7 +26,7 @@ Context-sensitive help is not yet available.

    -For more information, please visit the main Nagios website at http://www.nagios.org. +For more information, please visit the main Nagios website at https://www.nagios.org.

    diff --git a/html/contexthelp/I6.html b/html/contexthelp/I6.html index e40ba28..465430b 100644 --- a/html/contexthelp/I6.html +++ b/html/contexthelp/I6.html @@ -26,7 +26,7 @@ Context-sensitive help is not yet available.

    -For more information, please visit the main Nagios website at http://www.nagios.org. +For more information, please visit the main Nagios website at https://www.nagios.org.

    diff --git a/html/contexthelp/I7.html b/html/contexthelp/I7.html index e40ba28..465430b 100644 --- a/html/contexthelp/I7.html +++ b/html/contexthelp/I7.html @@ -26,7 +26,7 @@ Context-sensitive help is not yet available.

    -For more information, please visit the main Nagios website at http://www.nagios.org. +For more information, please visit the main Nagios website at https://www.nagios.org.

    diff --git a/html/contexthelp/I8.html b/html/contexthelp/I8.html index e40ba28..465430b 100644 --- a/html/contexthelp/I8.html +++ b/html/contexthelp/I8.html @@ -26,7 +26,7 @@ Context-sensitive help is not yet available.

    -For more information, please visit the main Nagios website at http://www.nagios.org. +For more information, please visit the main Nagios website at https://www.nagios.org.

    diff --git a/html/contexthelp/I9.html b/html/contexthelp/I9.html index e40ba28..465430b 100644 --- a/html/contexthelp/I9.html +++ b/html/contexthelp/I9.html @@ -26,7 +26,7 @@ Context-sensitive help is not yet available.

    -For more information, please visit the main Nagios website at http://www.nagios.org. +For more information, please visit the main Nagios website at https://www.nagios.org.

    diff --git a/html/contexthelp/J1.html b/html/contexthelp/J1.html index e40ba28..465430b 100644 --- a/html/contexthelp/J1.html +++ b/html/contexthelp/J1.html @@ -26,7 +26,7 @@ Context-sensitive help is not yet available.

    -For more information, please visit the main Nagios website at http://www.nagios.org. +For more information, please visit the main Nagios website at https://www.nagios.org.

    diff --git a/html/contexthelp/K1.html b/html/contexthelp/K1.html index e40ba28..465430b 100644 --- a/html/contexthelp/K1.html +++ b/html/contexthelp/K1.html @@ -26,7 +26,7 @@ Context-sensitive help is not yet available.

    -For more information, please visit the main Nagios website at http://www.nagios.org. +For more information, please visit the main Nagios website at https://www.nagios.org.

    diff --git a/html/contexthelp/L1.html b/html/contexthelp/L1.html index e40ba28..465430b 100644 --- a/html/contexthelp/L1.html +++ b/html/contexthelp/L1.html @@ -26,7 +26,7 @@ Context-sensitive help is not yet available.

    -For more information, please visit the main Nagios website at http://www.nagios.org. +For more information, please visit the main Nagios website at https://www.nagios.org.

    diff --git a/html/contexthelp/L10.html b/html/contexthelp/L10.html index e40ba28..465430b 100644 --- a/html/contexthelp/L10.html +++ b/html/contexthelp/L10.html @@ -26,7 +26,7 @@ Context-sensitive help is not yet available.

    -For more information, please visit the main Nagios website at http://www.nagios.org. +For more information, please visit the main Nagios website at https://www.nagios.org.

    diff --git a/html/contexthelp/L11.html b/html/contexthelp/L11.html index e40ba28..465430b 100644 --- a/html/contexthelp/L11.html +++ b/html/contexthelp/L11.html @@ -26,7 +26,7 @@ Context-sensitive help is not yet available.

    -For more information, please visit the main Nagios website at http://www.nagios.org. +For more information, please visit the main Nagios website at https://www.nagios.org.

    diff --git a/html/contexthelp/L12.html b/html/contexthelp/L12.html index e40ba28..465430b 100644 --- a/html/contexthelp/L12.html +++ b/html/contexthelp/L12.html @@ -26,7 +26,7 @@ Context-sensitive help is not yet available.

    -For more information, please visit the main Nagios website at http://www.nagios.org. +For more information, please visit the main Nagios website at https://www.nagios.org.

    diff --git a/html/contexthelp/L13.html b/html/contexthelp/L13.html index e40ba28..465430b 100644 --- a/html/contexthelp/L13.html +++ b/html/contexthelp/L13.html @@ -26,7 +26,7 @@ Context-sensitive help is not yet available.

    -For more information, please visit the main Nagios website at http://www.nagios.org. +For more information, please visit the main Nagios website at https://www.nagios.org.

    diff --git a/html/contexthelp/L2.html b/html/contexthelp/L2.html index e40ba28..465430b 100644 --- a/html/contexthelp/L2.html +++ b/html/contexthelp/L2.html @@ -26,7 +26,7 @@ Context-sensitive help is not yet available.

    -For more information, please visit the main Nagios website at http://www.nagios.org. +For more information, please visit the main Nagios website at https://www.nagios.org.

    diff --git a/html/contexthelp/L3.html b/html/contexthelp/L3.html index e40ba28..465430b 100644 --- a/html/contexthelp/L3.html +++ b/html/contexthelp/L3.html @@ -26,7 +26,7 @@ Context-sensitive help is not yet available.

    -For more information, please visit the main Nagios website at http://www.nagios.org. +For more information, please visit the main Nagios website at https://www.nagios.org.

    diff --git a/html/contexthelp/L4.html b/html/contexthelp/L4.html index e40ba28..465430b 100644 --- a/html/contexthelp/L4.html +++ b/html/contexthelp/L4.html @@ -26,7 +26,7 @@ Context-sensitive help is not yet available.

    -For more information, please visit the main Nagios website at http://www.nagios.org. +For more information, please visit the main Nagios website at https://www.nagios.org.

    diff --git a/html/contexthelp/L5.html b/html/contexthelp/L5.html index e40ba28..465430b 100644 --- a/html/contexthelp/L5.html +++ b/html/contexthelp/L5.html @@ -26,7 +26,7 @@ Context-sensitive help is not yet available.

    -For more information, please visit the main Nagios website at http://www.nagios.org. +For more information, please visit the main Nagios website at https://www.nagios.org.

    diff --git a/html/contexthelp/L6.html b/html/contexthelp/L6.html index e40ba28..465430b 100644 --- a/html/contexthelp/L6.html +++ b/html/contexthelp/L6.html @@ -26,7 +26,7 @@ Context-sensitive help is not yet available.

    -For more information, please visit the main Nagios website at http://www.nagios.org. +For more information, please visit the main Nagios website at https://www.nagios.org.

    diff --git a/html/contexthelp/L7.html b/html/contexthelp/L7.html index e40ba28..465430b 100644 --- a/html/contexthelp/L7.html +++ b/html/contexthelp/L7.html @@ -26,7 +26,7 @@ Context-sensitive help is not yet available.

    -For more information, please visit the main Nagios website at http://www.nagios.org. +For more information, please visit the main Nagios website at https://www.nagios.org.

    diff --git a/html/contexthelp/L8.html b/html/contexthelp/L8.html index e40ba28..465430b 100644 --- a/html/contexthelp/L8.html +++ b/html/contexthelp/L8.html @@ -26,7 +26,7 @@ Context-sensitive help is not yet available.

    -For more information, please visit the main Nagios website at http://www.nagios.org. +For more information, please visit the main Nagios website at https://www.nagios.org.

    diff --git a/html/contexthelp/L9.html b/html/contexthelp/L9.html index e40ba28..465430b 100644 --- a/html/contexthelp/L9.html +++ b/html/contexthelp/L9.html @@ -26,7 +26,7 @@ Context-sensitive help is not yet available.

    -For more information, please visit the main Nagios website at http://www.nagios.org. +For more information, please visit the main Nagios website at https://www.nagios.org.

    diff --git a/html/contexthelp/M1.html b/html/contexthelp/M1.html index e40ba28..465430b 100644 --- a/html/contexthelp/M1.html +++ b/html/contexthelp/M1.html @@ -26,7 +26,7 @@ Context-sensitive help is not yet available.

    -For more information, please visit the main Nagios website at http://www.nagios.org. +For more information, please visit the main Nagios website at https://www.nagios.org.

    diff --git a/html/contexthelp/M2.html b/html/contexthelp/M2.html index e40ba28..465430b 100644 --- a/html/contexthelp/M2.html +++ b/html/contexthelp/M2.html @@ -26,7 +26,7 @@ Context-sensitive help is not yet available.

    -For more information, please visit the main Nagios website at http://www.nagios.org. +For more information, please visit the main Nagios website at https://www.nagios.org.

    diff --git a/html/contexthelp/M3.html b/html/contexthelp/M3.html index e40ba28..465430b 100644 --- a/html/contexthelp/M3.html +++ b/html/contexthelp/M3.html @@ -26,7 +26,7 @@ Context-sensitive help is not yet available.

    -For more information, please visit the main Nagios website at http://www.nagios.org. +For more information, please visit the main Nagios website at https://www.nagios.org.

    diff --git a/html/contexthelp/M4.html b/html/contexthelp/M4.html index e40ba28..465430b 100644 --- a/html/contexthelp/M4.html +++ b/html/contexthelp/M4.html @@ -26,7 +26,7 @@ Context-sensitive help is not yet available.

    -For more information, please visit the main Nagios website at http://www.nagios.org. +For more information, please visit the main Nagios website at https://www.nagios.org.

    diff --git a/html/contexthelp/M5.html b/html/contexthelp/M5.html index e40ba28..465430b 100644 --- a/html/contexthelp/M5.html +++ b/html/contexthelp/M5.html @@ -26,7 +26,7 @@ Context-sensitive help is not yet available.

    -For more information, please visit the main Nagios website at http://www.nagios.org. +For more information, please visit the main Nagios website at https://www.nagios.org.

    diff --git a/html/contexthelp/M6.html b/html/contexthelp/M6.html index e40ba28..465430b 100644 --- a/html/contexthelp/M6.html +++ b/html/contexthelp/M6.html @@ -26,7 +26,7 @@ Context-sensitive help is not yet available.

    -For more information, please visit the main Nagios website at http://www.nagios.org. +For more information, please visit the main Nagios website at https://www.nagios.org.

    diff --git a/html/contexthelp/N1.html b/html/contexthelp/N1.html index e40ba28..465430b 100644 --- a/html/contexthelp/N1.html +++ b/html/contexthelp/N1.html @@ -26,7 +26,7 @@ Context-sensitive help is not yet available.

    -For more information, please visit the main Nagios website at http://www.nagios.org. +For more information, please visit the main Nagios website at https://www.nagios.org.

    diff --git a/html/contexthelp/N2.html b/html/contexthelp/N2.html index e40ba28..465430b 100644 --- a/html/contexthelp/N2.html +++ b/html/contexthelp/N2.html @@ -26,7 +26,7 @@ Context-sensitive help is not yet available.

    -For more information, please visit the main Nagios website at http://www.nagios.org. +For more information, please visit the main Nagios website at https://www.nagios.org.

    diff --git a/html/contexthelp/N3.html b/html/contexthelp/N3.html index e40ba28..465430b 100644 --- a/html/contexthelp/N3.html +++ b/html/contexthelp/N3.html @@ -26,7 +26,7 @@ Context-sensitive help is not yet available.

    -For more information, please visit the main Nagios website at http://www.nagios.org. +For more information, please visit the main Nagios website at https://www.nagios.org.

    diff --git a/html/contexthelp/N4.html b/html/contexthelp/N4.html index e40ba28..465430b 100644 --- a/html/contexthelp/N4.html +++ b/html/contexthelp/N4.html @@ -26,7 +26,7 @@ Context-sensitive help is not yet available.

    -For more information, please visit the main Nagios website at http://www.nagios.org. +For more information, please visit the main Nagios website at https://www.nagios.org.

    diff --git a/html/contexthelp/N5.html b/html/contexthelp/N5.html index e40ba28..465430b 100644 --- a/html/contexthelp/N5.html +++ b/html/contexthelp/N5.html @@ -26,7 +26,7 @@ Context-sensitive help is not yet available.

    -For more information, please visit the main Nagios website at http://www.nagios.org. +For more information, please visit the main Nagios website at https://www.nagios.org.

    diff --git a/html/contexthelp/N6.html b/html/contexthelp/N6.html index e40ba28..465430b 100644 --- a/html/contexthelp/N6.html +++ b/html/contexthelp/N6.html @@ -26,7 +26,7 @@ Context-sensitive help is not yet available.

    -For more information, please visit the main Nagios website at http://www.nagios.org. +For more information, please visit the main Nagios website at https://www.nagios.org.

    diff --git a/html/contexthelp/N7.html b/html/contexthelp/N7.html index e40ba28..465430b 100644 --- a/html/contexthelp/N7.html +++ b/html/contexthelp/N7.html @@ -26,7 +26,7 @@ Context-sensitive help is not yet available.

    -For more information, please visit the main Nagios website at http://www.nagios.org. +For more information, please visit the main Nagios website at https://www.nagios.org.

    diff --git a/html/d3-3.5.3.zip b/html/d3-3.5.3.zip new file mode 100644 index 0000000..1e43787 Binary files /dev/null and b/html/d3-3.5.3.zip differ diff --git a/html/docs/index.html b/html/docs/index.html index 4d12a47..8817359 100644 --- a/html/docs/index.html +++ b/html/docs/index.html @@ -74,7 +74,7 @@ The Nagios Core Documentation Has Moved!

    -Documentation for Nagios Core can now be found online at http://go.nagios.com/nagioscore/docs/ +Documentation for Nagios Core can now be found online at https://go.nagios.com/nagioscore/docs/

    @@ -86,7 +86,7 @@ Documentation for Nagios Core can now be found online at -Nagios, Nagios Core, NRPE, NSCA, and the Nagios logo are trademarks, servicemarks, registered servicemarks or registered trademarks of Nagios Enterprises. All other trademarks, servicemarks, registered trademarks, and registered servicemarks mentioned herein may be the property of their respective owner(s). The information contained herein is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +Nagios, Nagios Core, NRPE, NSCA, and the Nagios logo are trademarks, servicemarks, registered servicemarks or registered trademarks of Nagios Enterprises. All other trademarks, servicemarks, registered trademarks, and registered servicemarks mentioned herein may be the property of their respective owner(s). The information contained herein is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.

    diff --git a/html/graph-header.html b/html/graph-header.html new file mode 100644 index 0000000..5f207a9 --- /dev/null +++ b/html/graph-header.html @@ -0,0 +1,26 @@ +
    +
    + Host {{params.host}} +
    +
    + Service {{params.service}} on {{params.host}} +
    +
    + Histogram +
    +
    +
    +Host Event Histogram +Service Event Histogram +
    +
    + {{params.t1 * 1000 | date:'MM-dd-yy HH:mm:ss'}} to + {{params.t2 * 1000 | date:'MM-dd-yy HH:mm:ss'}} +
    +
    + Duration: {{(params.t2 - params.t1) * 1000 | duration}} +
    diff --git a/html/histogram-form.html b/html/histogram-form.html new file mode 100644 index 0000000..8e07459 --- /dev/null +++ b/html/histogram-form.html @@ -0,0 +1,131 @@ + + + + + diff --git a/html/histogram-graph.html b/html/histogram-graph.html new file mode 100644 index 0000000..3da0dc0 --- /dev/null +++ b/html/histogram-graph.html @@ -0,0 +1,156 @@ +
    +
    +
    + + + + State History for Host '{{host}}' + + + State History for Service '{{service}}' + on Host '{{host}}' + + + {{startTime | date:'EEE MMM dd HH:mm:ss yyyy'}} to + {{endTime | date:'EEE MMM dd HH:mm:ss yyyy'}} + + + + + + + + + + + + {{statisticsBreakdownLabel(breakdown)}} + + + + + + Number of Events + + + + + EVENT TYPE + MIN + MAX + SUM + AVG + + Recovery (Up): + + {{summary[breakdown].minima.up}} + + + {{summary[breakdown].maxima.up}} + + + {{summary[breakdown].totals.up}} + + + {{summary[breakdown].totals.up / getBreakdownPeriods() | number:2}} + + Down: + + {{summary[breakdown].minima.down}} + + + {{summary[breakdown].maxima.down}} + + + {{summary[breakdown].totals.down}} + + + {{summary[breakdown].totals.down / getBreakdownPeriods() | number:2}} + + + Unreachable: + + + {{summary[breakdown].minima.unreachable}} + + + {{summary[breakdown].maxima.unreachable}} + + + {{summary[breakdown].totals.unreachable}} + + + {{summary[breakdown].totals.unreachable / getBreakdownPeriods() | number:2}} + + + + EVENT TYPE + MIN + MAX + SUM + AVG + + Recovery (Ok): + + {{summary[breakdown].minima.ok}} + + + {{summary[breakdown].maxima.ok}} + + + {{summary[breakdown].totals.ok}} + + + {{summary[breakdown].totals.ok / getBreakdownPeriods() | number:2}} + + Warning: + + {{summary[breakdown].minima.warning}} + + + {{summary[breakdown].maxima.warning}} + + + {{summary[breakdown].totals.warning}} + + + {{summary[breakdown].totals.warning / getBreakdownPeriods() | number:2}} + + Unknown: + + {{summary[breakdown].minima.unknown}} + + + {{summary[breakdown].maxima.unknown}} + + + {{summary[breakdown].totals.unknown}} + + + {{summary[breakdown].totals.unknown / getBreakdownPeriods() | number:2}} + + Critical: + + {{summary[breakdown].minima.critical}} + + + {{summary[breakdown].maxima.critical}} + + + {{summary[breakdown].totals.critical}} + + + {{summary[breakdown].totals.critical / getBreakdownPeriods() | number:2}} + + + +
    +
    diff --git a/html/histogram-links.html b/html/histogram-links.html new file mode 100644 index 0000000..dbb905e --- /dev/null +++ b/html/histogram-links.html @@ -0,0 +1,47 @@ + + + + + + + + + diff --git a/html/histogram.html b/html/histogram.html new file mode 100644 index 0000000..2ebb3bd --- /dev/null +++ b/html/histogram.html @@ -0,0 +1,77 @@ + + + + + Nagios Histogram + + + + + + + + + + + + + + + + + + + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + + +
    +
    +
    + + + diff --git a/html/images/menu.png b/html/images/menu.png new file mode 100644 index 0000000..381c939 Binary files /dev/null and b/html/images/menu.png differ diff --git a/html/includes/rss/AUTHORS b/html/includes/rss/AUTHORS deleted file mode 100644 index 7d7f3f5..0000000 --- a/html/includes/rss/AUTHORS +++ /dev/null @@ -1 +0,0 @@ -kellan diff --git a/html/includes/rss/CHANGES b/html/includes/rss/CHANGES deleted file mode 100644 index 3346f2b..0000000 --- a/html/includes/rss/CHANGES +++ /dev/null @@ -1,41 +0,0 @@ -Version 0.72 ------------ - - fix security exploit: http://www.sec-consult.com/216.html - -Version 0.7 ------------ - - support for input and output charset encoding - based on the work in FoF, uses iconv or mbstring if available - - - -Version 0.6 ------------ - - basic support for Atom syndication format - including support for Atom content constructs - - fixed support for private feeds (HTTP Auth and SSL) - (thanks to silverorange.com for providing test feeds) - - support for some broken webservers - -Version 0.52 ------------ - - support GZIP content negoiation - - PHP 4.3.2 support - -Version 0.4 ------------ - - improved error handling, better access for script authors - - included example scripts of working with MagpieRSS - - new Smarty plugin for RSS date parsing - -Version 0.3 ------------ - - added support for conditional gets (Last-Modified, ETag) - - now use Snoopy to handle fetching RSS files - -Version 0.2 ------------ - - MAJOR CLEAN UP - - removed kludgy $options array in favour of constants - - phased out returning arrays - - added better error handling - - re-worked comments diff --git a/html/includes/rss/ChangeLog b/html/includes/rss/ChangeLog deleted file mode 100644 index 62fa4f5..0000000 --- a/html/includes/rss/ChangeLog +++ /dev/null @@ -1,405 +0,0 @@ -2005-10-28 14:11 kellan - - * extlib/Snoopy.class.inc: a better solution - -2005-10-28 11:51 kellan - - * extlib/Snoopy.class.inc: fix arbtriary code execution - vulnerability when using curl+ssl - - http://www.sec-consult.com/216.html - -2005-03-08 10:46 kellan - - * rss_parse.inc: fix bug w/ atom and date normalization - -2005-02-09 14:59 kellan - - * rss_fetch.inc: fix stale cache bug - -2005-01-28 02:27 kellan - - * rss_parse.inc: support php w/o array_change_case - -2005-01-23 20:02 kellan - - * rss_fetch.inc: fix cache bug introduced by charset encoding - -2005-01-12 09:14 kellan - - * rss_cache.inc, rss_fetch.inc: more sanity checks for when things - go wrong - -2004-12-12 13:44 kellan - - * INSTALL, rss_cache.inc, rss_utils.inc: detab - -2004-11-23 20:15 kellan - - * rss_parse.inc: fix calling iconv instead of mb_convert_encoding - -2004-11-22 02:11 kellan - - * CHANGES, ChangeLog, rss_parse.inc, scripts/magpie_debug.php: last - bit of tidying - -2004-11-22 01:45 kellan - - * rss_fetch.inc: detab, bump version - -2004-11-22 01:43 kellan - - * rss_parse.inc: was filtering too much - -2004-11-22 00:03 kellan - - * rss_fetch.inc, rss_parse.inc: cache on $url . $output_encoding - otherwise we can get munged output - -2004-11-21 23:52 kellan - - * rss_parse.inc: add WARNING - -2004-11-21 23:45 kellan - - * rss_parse.inc: don't set ERROR on notice or warning (rss_fetch - dies on parse errors) - -2004-11-21 23:44 kellan - - * rss_fetch.inc: add encoding defines (fix timeout error reporting) - -2004-11-21 20:21 kellan - - * rss_parse.inc: incorporate steve's patch - -2004-11-21 19:26 kellan - - * rss_parse.inc: remove old debugging functions, totally - arbitrarily. might break stuff. can't really explain why i'm - doing this. - -2004-10-28 15:52 kellan - - * rss_parse.inc: fixed '=' instead of '==' - -2004-10-26 00:48 kellan - - * rss_parse.inc: chance epoch to timestamp to conform w/ php naming - conventions - -2004-06-15 12:00 kellan - - * rss_parse.inc: [no log message] - -2004-04-26 14:16 kellan - - * rss_fetch.inc: bump version - -2004-04-26 12:36 kellan - - * rss_parse.inc: fix field doubling - -2004-04-24 17:47 kellan - - * CHANGES, ChangeLog: updated - -2004-04-24 17:35 kellan - - * rss_fetch.inc: bumped version - -2004-04-24 16:52 kellan - - * rss_parse.inc: support arbitrary atom content constructs - - some refactoring - -2004-04-24 16:15 kellan - - * rss_parse.inc: support summary content contstruct. add normalize - function - -2004-03-27 16:29 kellan - - * extlib/Snoopy.class.inc: accept self-signed certs - -2004-03-27 12:53 kellan - - * extlib/Snoopy.class.inc: fixed SSL support * set status * set - error on bad curl - - (also ripped out big chunks of dead weight (submit_form) which - were getting in my way - -2004-01-25 02:25 kellan - - * rss_parse.inc: make RSS 1.0's rdf:about available - -2004-01-25 02:07 kellan - - * rss_parse.inc: clean up text, and line formats. add support item - rdf:about - -2004-01-24 23:40 kellan - - * CHANGES, ChangeLog: update changes - -2004-01-24 23:37 kellan - - * rss_fetch.inc: updated version - -2004-01-24 23:35 kellan - - * rss_parse.inc: whitespace - -2004-01-24 23:23 kellan - - * extlib/Snoopy.class.inc: support badly formatted http headers - -2004-01-24 23:20 kellan - - * rss_parse.inc: added alpha atom parsing support - -2003-06-25 22:34 kellan - - * extlib/Snoopy.class.inc: fixed fread 4.3.2 compatibility problems - -2003-06-13 11:31 kellan - - * rss_fetch.inc: reset cache on 304 - -2003-06-12 21:37 kellan - - * rss_cache.inc, rss_fetch.inc, rss_parse.inc, rss_utils.inc: - bumped up version numbers - -2003-06-12 21:32 kellan - - * htdocs/index.html: updated news - -2003-06-12 21:27 kellan - - * NEWS: a manual blog :) - -2003-06-12 21:22 kellan - - * htdocs/index.html: fully qualified img - -2003-06-12 21:20 kellan - - * htdocs/index.html: clean up. added badge. - -2003-06-12 21:04 kellan - - * rss_utils.inc: clean up regex - -2003-06-12 21:02 kellan - - * rss_cache.inc: suppress some warnings - -2003-05-30 20:44 kellan - - * extlib/Snoopy.class.inc: more comments, cleaned up notice - -2003-05-30 15:14 kellan - - * extlib/Snoopy.class.inc: don't advertise gzip support if the user - hasn't built php with gzinflate support - -2003-05-12 22:32 kellan - - * ChangeLog: changes - -2003-05-12 22:11 kellan - - * htdocs/index.html: announce 0.5 - -2003-05-12 21:42 kellan - - * htdocs/index.html: change - -2003-05-12 21:39 kellan - - * rss_fetch.inc: use gzip - -2003-05-12 21:37 kellan - - * extlib/Snoopy.class.inc: added support gzip encoded content - negoiation - -2003-05-12 21:32 kellan - - * rss_cache.inc, rss_fetch.inc, rss_parse.inc, rss_utils.inc: fixed - typoes - -2003-04-26 21:44 kellan - - * rss_parse.inc: fix minor typo - -2003-04-18 08:19 kellan - - * htdocs/cookbook.html: updated cookbook to show more code for - limiting items - -2003-03-03 16:02 kellan - - * rss_parse.inc, scripts/magpie_slashbox.php: committed (or - adpated) patch from Nicola (www.technick.com) to quell 'Undefined - Indexes' notices - -2003-03-03 15:59 kellan - - * rss_fetch.inc: commited patch from nicola (www.technick.com) to - quell 'undefined indexes' notices. - - * Magpie now automatically includes its version in the - user-agent, & whether cacheing is turned on. - -2003-02-12 01:22 kellan - - * CHANGES, ChangeLog: ChangeLog now auto-generated by cvs2cl - -2003-02-12 00:21 kellan - - * rss_fetch.inc: better errors, hopefully stomped on pesky notices - -2003-02-12 00:19 kellan - - * rss_parse.inc: check to see is xml is supported, if not die - - also throw better xml errors - -2003-02-12 00:18 kellan - - * rss_cache.inc: hopefully cleared up some notices that were being - thrown into the log - - fixed a debug statement that was being called as an error - -2003-02-12 00:15 kellan - - * scripts/: magpie_simple.php, magpie_slashbox.php: moved - magpie_simple to magpie_slashbox, and replaced it with a simpler - demo. - -2003-02-12 00:02 kellan - - * INSTALL, README, TROUBLESHOOTING: Improved documentation. Better - install instructions. - - TROUBLESHOOTING cover common installation and usage problems - -2003-01-22 14:40 kellan - - * htdocs/cookbook.html: added cookbook.html - -2003-01-21 23:47 kellan - - * cookbook: a magpie cookbook - -2003-01-20 10:09 kellan - - * ChangeLog: updated - -2003-01-20 09:23 kellan - - * scripts/simple_smarty.php: minor clean up - -2003-01-20 09:15 kellan - - * scripts/README: added smarty url - -2003-01-20 09:14 kellan - - * magpie_simple.php, htdocs/index.html, scripts/README, - scripts/magpie_debug.php, scripts/magpie_simple.php, - scripts/simple_smarty.php, - scripts/smarty_plugin/modifier.rss_date_parse.php, - scripts/templates/simple.smarty: Added scripts directory for - examples on how to use MagpieRSS - - magpie_simple - is a simple example magpie_debug - spew all the - information from a parsed RSS feed simple_smary - example of - using magpie with Smarty template system - smarty_plugin/modifier.rss_date_parse.php - support file for the - smarty demo templates/simple.smary - template for the smarty demo - -2003-01-20 09:11 kellan - - * rss_fetch.inc, rss_parse.inc: changes to error handling to give - script authors more access to magpie's errors. - - added method magpie_error() to retrieve global MAGPIE_ERROR - variable for when fetch_rss() returns false - -2002-10-26 19:02 kellan - - * htdocs/index.html: putting the website under source control - -2002-10-26 18:43 kellan - - * AUTHORS, ChangeLog, INSTALL, README: some documentation to make - it all look official :) - -2002-10-25 23:04 kellan - - * magpie_simple.php: quxx - -2002-10-25 23:04 kellan - - * rss_parse.inc: added support for textinput and image - -2002-10-25 19:23 kellan - - * magpie_simple.php, rss_cache.inc, rss_fetch.inc, rss_parse.inc, - rss_utils.inc: switched to using Snoopy for fetching remote RSS - files. - - added support for conditional gets - -2002-10-25 19:22 kellan - - * rss_cache.inc, rss_fetch.inc, rss_parse.inc, rss_utils.inc: - Change comment style to slavishly imitate the phpinsider style - found in Smarty and Snoopy :) - -2002-10-25 19:18 kellan - - * extlib/Snoopy.class.inc: added Snoopy in order to support - conditional gets - -2002-10-23 23:19 kellan - - * magpie_simple.php, rss_cache.inc, rss_fetch.inc, rss_parse.inc: - MAJOR CLEANUP! - - * rss_fetch got rid of the options array, replaced it with a more - PHP-like solution of using defines. constants are setup, with - defaults, in the function init() - - got rid of the idiom of passing back an array, its was awkward to - deal with in PHP, and unusual (and consquently confusing to - people). now i return true/false values, and try to setup error - string where appropiate (rss_cache has the most complete example - of this) - - change the logic for interacting with the cache - - * rss_cache major re-working of how error are handled. tried to - make the code more resillient. the cache is now much more aware - of MAX_AGE, where before this was being driven out of rss_fetch - (which was silly) - - * rss_parse properly handles xml parse errors. used to sail - along blithely unaware. - -2002-09-11 11:11 kellan - - * rss_cache.inc, rss_parse.inc, magpie_simple.php, rss_fetch.inc, - rss_utils.inc: Initial revision - -2002-09-11 11:11 kellan - - * rss_cache.inc, rss_parse.inc, magpie_simple.php, rss_fetch.inc, - rss_utils.inc: initial import - diff --git a/html/includes/rss/INSTALL b/html/includes/rss/INSTALL deleted file mode 100644 index 640833d..0000000 --- a/html/includes/rss/INSTALL +++ /dev/null @@ -1,143 +0,0 @@ -REQUIREMENTS - - MapieRSS requires a recent PHP 4+ (developed with 4.2.0) - with xml (expat) support. - - Optionally: - * PHP5 with libxml2 support. - * cURL for SSL support - * iconv (preferred) or mb_string for expanded character set support - -QUICK START - - Magpie consists of 4 files (rss_fetch.inc, rss_parser.inc, rss_cache.inc, - and rss_utils.inc), and the directory extlib (which contains a modified - version of the Snoopy HTTP client) - - Copy these 5 resources to a directory named 'magpierss' in the same - directory as your PHP script. - - At the top of your script add the following line: - - require_once('magpierss/rss_fetch.inc'); - - Now you can use the fetch_rss() method: - - $rss = fetch_rss($url); - - Done. That's it. See README for more details on using MagpieRSS. - -NEXT STEPS - - Important: you'll probably want to get the cache directory working in - order to speed up your application, and not abuse the webserver you're - downloading the RSS from. - - Optionally you can install MagpieRSS in your PHP include path in order to - make it available server wide. - - Lastly you might want to look through the constants in rss_fetch.inc see if - there is anything you want to override (the defaults are pretty good) - - For more info, or if you have trouble, see TROUBLESHOOTING - -SETTING UP CACHING - - Magpie has built-in transparent caching. With caching Magpie will only - fetch and parse RSS feeds when there is new content. Without this feature - your pages will be slow, and the sites serving the RSS feed will be annoyed - with you. - -** Simple and Automatic ** - - By default Magpie will try to create a cache directory named 'cache' in the - same directory as your PHP script. - -** Creating a Local Cache Directory ** - - Often this will fail, because your webserver doesn't have sufficient - permissions to create the directory. - - Exact instructions for how to do this will vary from install to install and - platform to platform. The steps are: - - 1. Make a directory named 'cache' - 2. Give the web server write access to that directory. - - An example of how to do this on Debian would be: - - 1. mkdir /path/to/script/cache - 2. chgrp www-data /path/to/script/cache - 3. chmod 775 /path/to/script/cache - - On other Unixes you'll need to change 'www-data' to what ever user Apache - runs as. (on MacOS X the user would be 'www') - -** Cache in /tmp ** - - Sometimes you won't be able to create a local cache directory. Some reasons - might be: - - 1. No shell account - 2. Insufficient permissions to change ownership of a directory - 3. Webserver runs as 'nobody' - - In these situations using a cache directory in /tmp can often be a good - option. - - The drawback is /tmp is public, so anyone on the box can read the cache - files. Usually RSS feeds are public information, so you'll have to decide - how much of an issue that is. - - To use /tmp as your cache directory you need to add the following line to - your script: - - define('MAGPIE_CACHE_DIR', '/tmp/magpie_cache'); - -** Global Cache ** - - If you have several applications using Magpie, you can create a single - shared cache directory, either using the /tmp cache, or somewhere else on - the system. - - The upside is that you'll distribute fetching and parsing feeds across - several applications. - -INSTALLING MAGPIE SERVER WIDE - - Rather then following the Quickstart instructions which requires you to have - a copy of Magpie per application, alternately you can place it in some - shared location. - -** Adding Magpie to Your Include Path ** - - Copy the 5 resources (rss_fetch.inc, rss_parser.inc, rss_cache.inc, - rss_utils.inc, and extlib) to a directory named 'magpierss' in your include - path. Now any PHP file on your system can use Magpie with: - - require_once('magpierss/rss_fetch.inc'); - - Different installs have different include paths, and you'll have to figure - out what your include_path is. - - From shell you can try: - - php -i | grep 'include_path' - - Alternatley you can create a phpinfo.php file with contains: - - - - Debian's default is: - - /usr/share/php - - (though more idealogically pure location would be /usr/local/share/php) - - Apple's default include path is: - - /usr/lib/php - - While the Entropy PHP build seems to use: - - /usr/local/php/lib/php \ No newline at end of file diff --git a/html/includes/rss/NEWS b/html/includes/rss/NEWS deleted file mode 100644 index 5ac6b97..0000000 --- a/html/includes/rss/NEWS +++ /dev/null @@ -1,53 +0,0 @@ -MagpieRSS News - -MAGPIERSS 0.51 RELEASED - * important bugfix! - * fix "silent failure" when PHP doesn't have zlib - -FEED ON FEEDS USES MAGPIE - * web-based RSS aggregator built with Magpie - * easy to install, easy to use. - http://minutillo.com/steve/feedonfeeds/ - -MAGPIERSS 0.5 RELEASED - * supports transparent HTTP gzip content negotiation for reduced bandwidth usage - * quashed some undefined index notices - -MAGPIERSS 0.46 RELEASED - * minor release, more error handling clean up - * documentation fixes, simpler example - * new trouble shooting guide for installation and usage problems - http://magpierss.sourceforge.net/TROUBLESHOOTING - -MAGPIE NEWS AS RSS - * releases, bug fixes, releated stories in RSS - -MAGPIERSS COOKBOOK: SIMPLE PHP RSS HOW TOS - * answers some of the most frequently asked Magpie questions - * feedback, suggestions, requests, recipes welcome - http://magpierss.sourceforge.net/cookbook.html - -MAGPIERSS 0.4 RELEASED! - * improved error handling, more flexibility for script authors, backwards compatible - * new and better examples! including using MagpieRSS and Smarty - * new Smarty plugin for RSS date parsing - http://smarty.php.net - -INFINITE PENGUIN NOW SUPPORTS MAGPIE 0.3 - * simple, sophisticated RSS viewer - * includes auto-generated javascript ticker from RSS feed - http://www.infinitepenguins.net/rss/ - -TRAUMWIND RELEASES REX BACKEND FOR MAGPIERSS - * drop in support using regex based XML parser - * parses improperly formed XML that chokes expat - http://traumwind.de/blog/magpie/magpie_alike.php - -MAGPIERSS 0.3 RELEASED! - * Support added for HTTP Conditional GETs. - http://fishbowl.pastiche.org/archives/001132.html - -MAGPIERSS 0.2! - * Major clean up of the code. Easier to use. - * Simpler install on shared hosts. - * Better documentation and comments. diff --git a/html/includes/rss/README b/html/includes/rss/README deleted file mode 100644 index 6af7edb..0000000 --- a/html/includes/rss/README +++ /dev/null @@ -1,48 +0,0 @@ -NAME - - MagpieRSS - a simple RSS integration tool - -SYNOPSIS - - require_once(rss_fetch.inc); - $url = $_GET['url']; - $rss = fetch_rss( $url ); - - echo "Channel Title: " . $rss->channel['title'] . "

    "; - echo "

      "; - foreach ($rss->items as $item) { - $href = $item['link']; - $title = $item['title']; - echo "
    • $title
    • "; - } - echo "
    "; - -DESCRIPTION - - MapieRSS is an XML-based RSS parser in PHP. It attempts to be "PHP-like", - and simple to use. - - Some features include: - - * supports RSS 0.9 - 1.0, with limited RSS 2.0 support - * supports namespaces, and modules, including mod_content and mod_event - * open minded [1] - * simple, functional interface, to object oriented backend parser - * automatic caching of parsed RSS objects makes its easy to integrate - * supports conditional GET with Last-Modified, and ETag - * uses constants for easy override of default behaviour - * heavily commented - - -1. By open minded I mean Magpie will accept any tag it finds in good faith that - it was supposed to be here. For strict validation, look elsewhere. - - -GETTING STARTED - - - -COPYRIGHT: - Copyright(c) 2002 kellan@protest.net. All rights reserved. - This software is released under the GNU General Public License. - Please read the disclaimer at the top of the Snoopy.class.inc file. diff --git a/html/includes/rss/TROUBLESHOOTING b/html/includes/rss/TROUBLESHOOTING deleted file mode 100644 index 89068d3..0000000 --- a/html/includes/rss/TROUBLESHOOTING +++ /dev/null @@ -1,152 +0,0 @@ -TROUBLESHOOTING - - -Trouble Installing MagpieRSS: - -1. Fatal error: Failed opening required '/path/to/script/rss_fetch.inc' - (include_path='.:/usr/local/lib/php:/usr/local/lib/php/pear') - -2. Cache couldn't make dir './cache'. - -3. Fatal error: Failed to load PHP's XML Extension. - http://www.php.net/manual/en/ref.xml.php - -Trouble Using MagpieRSS - -4. Warning: MagpieRSS: Failed to fetch example.com/index.rdf. - (HTTP Error: Invalid protocol "") - -5. Warning: MagpieRSS: Failed to parse RSS file. - (not well-formed (invalid token) at line 19, column 98) - -6. Warning: MagpieRSS: Failed to fetch http://localhost/rss/features.1-0.rss. - (HTTP Response: HTTP/1.1 404 Not Found) - -If you would rather provide a custom error, see the COOKBOOK -(http://magpierss.sf.net/cookbook.html) recipe 2. - -************************************************************************* -1. Fatal error: Failed opening required '/path/to/script/rss_fetch.inc' - (include_path='.:/usr/local/lib/php:/usr/local/lib/php/pear') - - This could mean that: - - a) PHP can't find the MagpieRSS files. - b) PHP found them the MagpieRSS files, but can't read them. - - a. Telling PHP where to look for MagpieRSS file. - - This might mean your PHP program can't find the MagpieRSS libraries. - Magpie relies on 4 include files, rss_fetch.inc, rss_parse.inc, - rss_cache.inc, rss_util.inc, and for normal use you'll need all 4 (see the - cookbook for exceptions). - - This can be fixed by making sure the MagpieRSS files are in your include - path. - - If you can edit your include path (for example your on a shared host) then - you need to replace: - - require_once('rss_fetch.inc'); - - -with- - - define('MAGPIE_DIR', '/path/to/magpierss/'); - require_once(MAGPIE_DIR.'rss_fetch.inc'); - - b. PHP can't read the MagpieRSS files - - All PHP libraries need to be readable by your webserver. - - On Unix you can accomplish this with: - - chmod 755 rss_fetch.inc rss_parse.inc rss_cache.inc rss_util.inc - -************************************************************************* -2. Cache couldn't make dir './cache'. - - MagpieRSS caches the results of fetched and parsed RSS to reduce the load on - both your server, and the remote server providing the RSS. It does this by - writing files to a cache directory. - - This error means the webserver doesn't have write access to the current - directory. - - a. Make a webserver writeable cache directory - - Find the webserver's group. (on my system it is 'www') - - mkdir ./cache - chgrp www directory_name - chmod g+w directory_name - - (this is the best, and desired solution) - - b. Tell MagpieRSS to create the cache directory somewhere the webserver can - write to. - - define('MAGPIE_CACHE_DIR', '/tmp/magpierss'); - - (this is not a great solution, and might have security considerations) - - c. Turn off cacheing. - - Magpie can work fine with cacheing, but it will be slower, and you might - become a nuiance to the RSS provider, but it is an option. - - define('MAGPIE_CACHE_ON', 0); - - d. And lastly, do NOT - - chmod 777 ./cache - - Any of the above solutions are better then this. - - NOTE: If none of this works for you, let me know. I've got root, and a - custom compiled Apache on almost any box I ever touch, so I can be a little - out of touch with reality. But I won't know that if I don't feedback. - -************************************************************************* 3. -3. Fatal error: Failed to load PHP's XML Extension. - http://www.php.net/manual/en/ref.xml.php - - -or- - - Fatal error: Failed to create an instance of PHP's XML parser. - http://www.php.net/manual/en/ref.xml.php - - Make sure your PHP was built with --with-xml - - This has been turned on by default for several versions of PHP, but it might - be turned off in your build. - - See php.net for details on building and configuring PHP. - - -************************************************************************* -4. Warning: MagpieRSS: Failed to fetch index.rdf. - (HTTP Error: Invalid protocol "") - - You need to put http:// in front of your the URL to your RSS feed - -************************************************************************* -5. Warning: MagpieRSS: Failed to parse RSS file. - (not well-formed (invalid token) at line 19, column 98) - - There is a problem with the RSS feed you are trying to read. - MagpieRSS is an XML parser, and therefore can't parse RSS feed with invalid - characters. Some RSS parser are based on regular expressions, and can - parse invalid RSS but they have their own problems. - - You could try contacting the author of the RSS feed, and pointing them to - the online RSS validator at: - - http://feeds.archive.org/validator/ - -************************************************************************* -6. Warning: MagpieRSS: Failed to fetch http://example.com/index.rdf - (HTTP Response: HTTP/1.1 404 Not Found) - - Its a 404! The RSS file ain't there. - - diff --git a/html/includes/rss/cookbook b/html/includes/rss/cookbook deleted file mode 100644 index 45dda98..0000000 --- a/html/includes/rss/cookbook +++ /dev/null @@ -1,125 +0,0 @@ -MAGPIERSS RECIPES: Cooking with Corbies - - "Four and twenty blackbirds baked in a pie." - -1. LIMIT THE NUMBER OF HEADLINES(AKA ITEMS) RETURNED. - -PROBLEM: - -You want to display the 10 (or 3) most recent headlines, but the RSS feed -contains 15. - -SOLUTION: - -$num_items = 10; -$rss = fetch_rss($url); - -$items = array_slice($rss->items, 0, $num_items); - -DISCUSSION: - -Rather then trying to limit the number of items Magpie parses, a much simpler, -and more flexible approach is to take a "slice" of the array of items. And -array_slice() is smart enough to do the right thing if the feed has less items -then $num_items. - -See: http://www.php.net/array_slice - - -2. DISPLAY A CUSTOM ERROR MESSAGE IF SOMETHING GOES WRONG - -PROBLEM: - -You don't want Magpie's error messages showing up if something goes wrong. - -SOLUTION: - -# Magpie throws USER_WARNINGS only -# so you can cloak these, by only showing ERRORs -error_reporting(E_ERROR); - -# check the return value of fetch_rss() - -$rss = fetch_rss($url); - -if ( $rss ) { -...display rss feed... -} -else { - echo "An error occured! " . - "Consider donating more $$$ for restoration of services." . - "
    Error Message: " . magpie_error(); -} - -DISCUSSION: - -MagpieRSS triggers a warning in a number of circumstances. The 2 most common -circumstances are: if the specified RSS file isn't properly formed (usually -because it includes illegal HTML), or if Magpie can't download the remote RSS -file, and there is no cached version. - -If you don't want your users to see these warnings change your error_reporting -settings to only display ERRORs. Another option is to turn off display_error, -so that WARNINGs, and NOTICEs still go to the error_log but not to the webpages. - -You can do this with: - -ini_set('display_errors', 0); - -See: http://www.php.net/error_reporting, - http://www.php.net/ini_set, - http://www.php.net/manual/en/ref.errorfunc.php - -3. GENERATE A NEW RSS FEED - -PROBLEM: - -Create an RSS feed for other people to use. - -SOLUTION: - -Use Useful Inc's RSSWriter (http://usefulinc.com/rss/rsswriter/) - -DISCUSSION: - -An example of turning a Magpie parsed RSS object back into an RSS file is forth -coming. In the meantime RSSWriter has great documentation. - -4. DISPLAY HEADLINES MORE RECENT THEN X DATE - -PROBLEM: - -You only want to display headlines that were published on, or after a certain -date. - - -SOLUTION: - -require 'rss_utils.inc'; - -# get all headlines published today -$today = getdate(); - -# today, 12AM -$date = mktime(0,0,0,$today['mon'], $today['mday'], $today['year']); - -$rss = fetch_rss($url); - -foreach ( $rss->items as $item ) { - $published = parse_w3cdtf($item['dc']['date']); - if ( $published >= $date ) { - echo "Title: " . $item['title']; - echo "Published: " . date("h:i:s A", $published); - echo "

    "; - } -} - -DISCUSSION: - -This recipe only works for RSS 1.0 feeds that include the field. -(which is very good RSS style) - -parse_w3cdtf is defined in rss_utils.inc, and parses RSS style dates into Unix -epoch seconds. - -See: http://www.php.net/manual/en/ref.datetime.php diff --git a/html/includes/rss/extlib/Snoopy.class.inc b/html/includes/rss/extlib/Snoopy.class.inc deleted file mode 100644 index 3ddecba..0000000 --- a/html/includes/rss/extlib/Snoopy.class.inc +++ /dev/null @@ -1,900 +0,0 @@ - -Copyright (c): 1999-2000 ispi, all rights reserved -Version: 1.0 - - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -You may contact the author of Snoopy by e-mail at: -monte@ispi.net - -Or, write to: -Monte Ohrt -CTO, ispi -237 S. 70th suite 220 -Lincoln, NE 68510 - -The latest version of Snoopy can be obtained from: -http://snoopy.sourceforge.com - -*************************************************/ - -class Snoopy -{ - /**** Public variables ****/ - - /* user definable vars */ - - var $host = "www.php.net"; // host name we are connecting to - var $port = 80; // port we are connecting to - var $proxy_host = ""; // proxy host to use - var $proxy_port = ""; // proxy port to use - var $agent = "Snoopy v1.0"; // agent we masquerade as - var $referer = ""; // referer info to pass - var $cookies = array(); // array of cookies to pass - // $cookies["username"]="joe"; - var $rawheaders = array(); // array of raw headers to send - // $rawheaders["Content-type"]="text/html"; - - var $maxredirs = 5; // http redirection depth maximum. 0 = disallow - var $lastredirectaddr = ""; // contains address of last redirected address - var $offsiteok = true; // allows redirection off-site - var $maxframes = 0; // frame content depth maximum. 0 = disallow - var $expandlinks = true; // expand links to fully qualified URLs. - // this only applies to fetchlinks() - // or submitlinks() - var $passcookies = true; // pass set cookies back through redirects - // NOTE: this currently does not respect - // dates, domains or paths. - - var $user = ""; // user for http authentication - var $pass = ""; // password for http authentication - - // http accept types - var $accept = "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*"; - - var $results = ""; // where the content is put - - var $error = ""; // error messages sent here - var $response_code = ""; // response code returned from server - var $headers = array(); // headers returned from server sent here - var $maxlength = 500000; // max return data length (body) - var $read_timeout = 0; // timeout on read operations, in seconds - // supported only since PHP 4 Beta 4 - // set to 0 to disallow timeouts - var $timed_out = false; // if a read operation timed out - var $status = 0; // http request status - - var $curl_path = "/usr/bin/curl"; - // Snoopy will use cURL for fetching - // SSL content if a full system path to - // the cURL binary is supplied here. - // set to false if you do not have - // cURL installed. See http://curl.haxx.se - // for details on installing cURL. - // Snoopy does *not* use the cURL - // library functions built into php, - // as these functions are not stable - // as of this Snoopy release. - - // send Accept-encoding: gzip? - var $use_gzip = true; - - /**** Private variables ****/ - - var $_maxlinelen = 4096; // max line length (headers) - - var $_httpmethod = "GET"; // default http request method - var $_httpversion = "HTTP/1.0"; // default http request version - var $_submit_method = "POST"; // default submit method - var $_submit_type = "application/x-www-form-urlencoded"; // default submit type - var $_mime_boundary = ""; // MIME boundary for multipart/form-data submit type - var $_redirectaddr = false; // will be set if page fetched is a redirect - var $_redirectdepth = 0; // increments on an http redirect - var $_frameurls = array(); // frame src urls - var $_framedepth = 0; // increments on frame depth - - var $_isproxy = false; // set if using a proxy server - var $_fp_timeout = 30; // timeout for socket connection - -/*======================================================================*\ - Function: fetch - Purpose: fetch the contents of a web page - (and possibly other protocols in the - future like ftp, nntp, gopher, etc.) - Input: $URI the location of the page to fetch - Output: $this->results the output text from the fetch -\*======================================================================*/ - - function fetch($URI) - { - - //preg_match("|^([^:]+)://([^:/]+)(:[\d]+)*(.*)|",$URI,$URI_PARTS); - $URI_PARTS = parse_url($URI); - if (!empty($URI_PARTS["user"])) - $this->user = $URI_PARTS["user"]; - if (!empty($URI_PARTS["pass"])) - $this->pass = $URI_PARTS["pass"]; - - switch($URI_PARTS["scheme"]) - { - case "http": - $this->host = $URI_PARTS["host"]; - if(!empty($URI_PARTS["port"])) - $this->port = $URI_PARTS["port"]; - if($this->_connect($fp)) - { - if($this->_isproxy) - { - // using proxy, send entire URI - $this->_httprequest($URI,$fp,$URI,$this->_httpmethod); - } - else - { - $path = $URI_PARTS["path"].(isset($URI_PARTS["query"]) ? "?".$URI_PARTS["query"] : ""); - // no proxy, send only the path - $this->_httprequest($path, $fp, $URI, $this->_httpmethod); - } - - $this->_disconnect($fp); - - if($this->_redirectaddr) - { - /* url was redirected, check if we've hit the max depth */ - if($this->maxredirs > $this->_redirectdepth) - { - // only follow redirect if it's on this site, or offsiteok is true - if(preg_match("|^http://".preg_quote($this->host)."|i",$this->_redirectaddr) || $this->offsiteok) - { - /* follow the redirect */ - $this->_redirectdepth++; - $this->lastredirectaddr=$this->_redirectaddr; - $this->fetch($this->_redirectaddr); - } - } - } - - if($this->_framedepth < $this->maxframes && count($this->_frameurls) > 0) - { - $frameurls = $this->_frameurls; - $this->_frameurls = array(); - - while(list(,$frameurl) = each($frameurls)) - { - if($this->_framedepth < $this->maxframes) - { - $this->fetch($frameurl); - $this->_framedepth++; - } - else - break; - } - } - } - else - { - return false; - } - return true; - break; - case "https": - if(!$this->curl_path || (!is_executable($this->curl_path))) { - $this->error = "Bad curl ($this->curl_path), can't fetch HTTPS \n"; - return false; - } - $this->host = $URI_PARTS["host"]; - if(!empty($URI_PARTS["port"])) - $this->port = $URI_PARTS["port"]; - if($this->_isproxy) - { - // using proxy, send entire URI - $this->_httpsrequest($URI,$URI,$this->_httpmethod); - } - else - { - $path = $URI_PARTS["path"].($URI_PARTS["query"] ? "?".$URI_PARTS["query"] : ""); - // no proxy, send only the path - $this->_httpsrequest($path, $URI, $this->_httpmethod); - } - - if($this->_redirectaddr) - { - /* url was redirected, check if we've hit the max depth */ - if($this->maxredirs > $this->_redirectdepth) - { - // only follow redirect if it's on this site, or offsiteok is true - if(preg_match("|^http://".preg_quote($this->host)."|i",$this->_redirectaddr) || $this->offsiteok) - { - /* follow the redirect */ - $this->_redirectdepth++; - $this->lastredirectaddr=$this->_redirectaddr; - $this->fetch($this->_redirectaddr); - } - } - } - - if($this->_framedepth < $this->maxframes && count($this->_frameurls) > 0) - { - $frameurls = $this->_frameurls; - $this->_frameurls = array(); - - while(list(,$frameurl) = each($frameurls)) - { - if($this->_framedepth < $this->maxframes) - { - $this->fetch($frameurl); - $this->_framedepth++; - } - else - break; - } - } - return true; - break; - default: - // not a valid protocol - $this->error = 'Invalid protocol "'.$URI_PARTS["scheme"].'"\n'; - return false; - break; - } - return true; - } - - - -/*======================================================================*\ - Private functions -\*======================================================================*/ - - -/*======================================================================*\ - Function: _striplinks - Purpose: strip the hyperlinks from an html document - Input: $document document to strip. - Output: $match an array of the links -\*======================================================================*/ - - function _striplinks($document) - { - preg_match_all("'<\s*a\s+.*href\s*=\s* # find ]+)) # if quote found, match up to next matching - # quote, otherwise match up to next space - 'isx",$document,$links); - - - // catenate the non-empty matches from the conditional subpattern - - while(list($key,$val) = each($links[2])) - { - if(!empty($val)) - $match[] = $val; - } - - while(list($key,$val) = each($links[3])) - { - if(!empty($val)) - $match[] = $val; - } - - // return the links - return $match; - } - -/*======================================================================*\ - Function: _stripform - Purpose: strip the form elements from an html document - Input: $document document to strip. - Output: $match an array of the links -\*======================================================================*/ - - function _stripform($document) - { - preg_match_all("'<\/?(FORM|INPUT|SELECT|TEXTAREA|(OPTION))[^<>]*>(?(2)(.*(?=<\/?(option|select)[^<>]*>[\r\n]*)|(?=[\r\n]*))|(?=[\r\n]*))'Usi",$document,$elements); - - // catenate the matches - $match = implode("\r\n",$elements[0]); - - // return the links - return $match; - } - - - -/*======================================================================*\ - Function: _striptext - Purpose: strip the text from an html document - Input: $document document to strip. - Output: $text the resulting text -\*======================================================================*/ - - function _striptext($document) - { - - // I didn't use preg eval (//e) since that is only available in PHP 4.0. - // so, list your entities one by one here. I included some of the - // more common ones. - - $search = array("']*?>.*?'si", // strip out javascript - "'<[\/\!]*?[^<>]*?>'si", // strip out html tags - "'([\r\n])[\s]+'", // strip out white space - "'&(quote|#34);'i", // replace html entities - "'&(amp|#38);'i", - "'&(lt|#60);'i", - "'&(gt|#62);'i", - "'&(nbsp|#160);'i", - "'&(iexcl|#161);'i", - "'&(cent|#162);'i", - "'&(pound|#163);'i", - "'&(copy|#169);'i" - ); - $replace = array( "", - "", - "\\1", - "\"", - "&", - "<", - ">", - " ", - chr(161), - chr(162), - chr(163), - chr(169)); - - $text = preg_replace($search,$replace,$document); - - return $text; - } - -/*======================================================================*\ - Function: _expandlinks - Purpose: expand each link into a fully qualified URL - Input: $links the links to qualify - $URI the full URI to get the base from - Output: $expandedLinks the expanded links -\*======================================================================*/ - - function _expandlinks($links,$URI) - { - - preg_match("/^[^\?]+/",$URI,$match); - - $match = preg_replace("|/[^\/\.]+\.[^\/\.]+$|","",$match[0]); - - $search = array( "|^http://".preg_quote($this->host)."|i", - "|^(?!http://)(\/)?(?!mailto:)|i", - "|/\./|", - "|/[^\/]+/\.\./|" - ); - - $replace = array( "", - $match."/", - "/", - "/" - ); - - $expandedLinks = preg_replace($search,$replace,$links); - - return $expandedLinks; - } - -/*======================================================================*\ - Function: _httprequest - Purpose: go get the http data from the server - Input: $url the url to fetch - $fp the current open file pointer - $URI the full URI - $body body contents to send if any (POST) - Output: -\*======================================================================*/ - - function _httprequest($url,$fp,$URI,$http_method,$content_type="",$body="") - { - if($this->passcookies && $this->_redirectaddr) - $this->setcookies(); - - $URI_PARTS = parse_url($URI); - if(empty($url)) - $url = "/"; - $headers = $http_method." ".$url." ".$this->_httpversion."\r\n"; - if(!empty($this->agent)) - $headers .= "User-Agent: ".$this->agent."\r\n"; - if(!empty($this->host) && !isset($this->rawheaders['Host'])) - $headers .= "Host: ".$this->host."\r\n"; - if(!empty($this->accept)) - $headers .= "Accept: ".$this->accept."\r\n"; - - if($this->use_gzip) { - // make sure PHP was built with --with-zlib - // and we can handle gzipp'ed data - if ( function_exists(gzinflate) ) { - $headers .= "Accept-encoding: gzip\r\n"; - } - else { - trigger_error( - "use_gzip is on, but PHP was built without zlib support.". - " Requesting file(s) without gzip encoding.", - E_USER_NOTICE); - } - } - - if(!empty($this->referer)) - $headers .= "Referer: ".$this->referer."\r\n"; - if(!empty($this->cookies)) - { - if(!is_array($this->cookies)) - $this->cookies = (array)$this->cookies; - - reset($this->cookies); - if ( count($this->cookies) > 0 ) { - $cookie_headers .= 'Cookie: '; - foreach ( $this->cookies as $cookieKey => $cookieVal ) { - $cookie_headers .= $cookieKey."=".urlencode($cookieVal)."; "; - } - $headers .= substr($cookie_headers,0,-2) . "\r\n"; - } - } - if(!empty($this->rawheaders)) - { - if(!is_array($this->rawheaders)) - $this->rawheaders = (array)$this->rawheaders; - while(list($headerKey,$headerVal) = each($this->rawheaders)) - $headers .= $headerKey.": ".$headerVal."\r\n"; - } - if(!empty($content_type)) { - $headers .= "Content-type: $content_type"; - if ($content_type == "multipart/form-data") - $headers .= "; boundary=".$this->_mime_boundary; - $headers .= "\r\n"; - } - if(!empty($body)) - $headers .= "Content-length: ".strlen($body)."\r\n"; - if(!empty($this->user) || !empty($this->pass)) - $headers .= "Authorization: BASIC ".base64_encode($this->user.":".$this->pass)."\r\n"; - - $headers .= "\r\n"; - - // set the read timeout if needed - if ($this->read_timeout > 0) - socket_set_timeout($fp, $this->read_timeout); - $this->timed_out = false; - - fwrite($fp,$headers.$body,strlen($headers.$body)); - - $this->_redirectaddr = false; - unset($this->headers); - - // content was returned gzip encoded? - $is_gzipped = false; - - while($currentHeader = fgets($fp,$this->_maxlinelen)) - { - if ($this->read_timeout > 0 && $this->_check_timeout($fp)) - { - $this->status=-100; - return false; - } - - // if($currentHeader == "\r\n") - if(preg_match("/^\r?\n$/", $currentHeader) ) - break; - - // if a header begins with Location: or URI:, set the redirect - if(preg_match("/^(Location:|URI:)/i",$currentHeader)) - { - // get URL portion of the redirect - preg_match("/^(Location:|URI:)\s+(.*)/",chop($currentHeader),$matches); - // look for :// in the Location header to see if hostname is included - if(!preg_match("|\:\/\/|",$matches[2])) - { - // no host in the path, so prepend - $this->_redirectaddr = $URI_PARTS["scheme"]."://".$this->host.":".$this->port; - // eliminate double slash - if(!preg_match("|^/|",$matches[2])) - $this->_redirectaddr .= "/".$matches[2]; - else - $this->_redirectaddr .= $matches[2]; - } - else - $this->_redirectaddr = $matches[2]; - } - - if(preg_match("|^HTTP/|",$currentHeader)) - { - if(preg_match("|^HTTP/[^\s]*\s(.*?)\s|",$currentHeader, $status)) - { - $this->status= $status[1]; - } - $this->response_code = $currentHeader; - } - - if (preg_match("/Content-Encoding: gzip/", $currentHeader) ) { - $is_gzipped = true; - } - - $this->headers[] = $currentHeader; - } - - # $results = fread($fp, $this->maxlength); - $results = ""; - while ( $data = fread($fp, $this->maxlength) ) { - $results .= $data; - if ( - strlen($results) > $this->maxlength ) { - break; - } - } - - // gunzip - if ( $is_gzipped ) { - // per http://www.php.net/manual/en/function.gzencode.php - $results = substr($results, 10); - $results = gzinflate($results); - } - - if ($this->read_timeout > 0 && $this->_check_timeout($fp)) - { - $this->status=-100; - return false; - } - - // check if there is a a redirect meta tag - - if(preg_match("']*?content[\s]*=[\s]*[\"\']?\d+;[\s]+URL[\s]*=[\s]*([^\"\']*?)[\"\']?>'i",$results,$match)) - { - $this->_redirectaddr = $this->_expandlinks($match[1],$URI); - } - - // have we hit our frame depth and is there frame src to fetch? - if(($this->_framedepth < $this->maxframes) && preg_match_all("']+)'i",$results,$match)) - { - $this->results[] = $results; - for($x=0; $x_frameurls[] = $this->_expandlinks($match[1][$x],$URI_PARTS["scheme"]."://".$this->host); - } - // have we already fetched framed content? - elseif(is_array($this->results)) - $this->results[] = $results; - // no framed content - else - $this->results = $results; - - return true; - } - -/*======================================================================*\ - Function: _httpsrequest - Purpose: go get the https data from the server using curl - Input: $url the url to fetch - $URI the full URI - $body body contents to send if any (POST) - Output: -\*======================================================================*/ - - function _httpsrequest($url,$URI,$http_method,$content_type="",$body="") - { - if($this->passcookies && $this->_redirectaddr) - $this->setcookies(); - - $headers = array(); - - $URI_PARTS = parse_url($URI); - if(empty($url)) - $url = "/"; - // GET ... header not needed for curl - //$headers[] = $http_method." ".$url." ".$this->_httpversion; - if(!empty($this->agent)) - $headers[] = "User-Agent: ".$this->agent; - if(!empty($this->host)) - $headers[] = "Host: ".$this->host; - if(!empty($this->accept)) - $headers[] = "Accept: ".$this->accept; - if(!empty($this->referer)) - $headers[] = "Referer: ".$this->referer; - if(!empty($this->cookies)) - { - if(!is_array($this->cookies)) - $this->cookies = (array)$this->cookies; - - reset($this->cookies); - if ( count($this->cookies) > 0 ) { - $cookie_str = 'Cookie: '; - foreach ( $this->cookies as $cookieKey => $cookieVal ) { - $cookie_str .= $cookieKey."=".urlencode($cookieVal)."; "; - } - $headers[] = substr($cookie_str,0,-2); - } - } - if(!empty($this->rawheaders)) - { - if(!is_array($this->rawheaders)) - $this->rawheaders = (array)$this->rawheaders; - while(list($headerKey,$headerVal) = each($this->rawheaders)) - $headers[] = $headerKey.": ".$headerVal; - } - if(!empty($content_type)) { - if ($content_type == "multipart/form-data") - $headers[] = "Content-type: $content_type; boundary=".$this->_mime_boundary; - else - $headers[] = "Content-type: $content_type"; - } - if(!empty($body)) - $headers[] = "Content-length: ".strlen($body); - if(!empty($this->user) || !empty($this->pass)) - $headers[] = "Authorization: BASIC ".base64_encode($this->user.":".$this->pass); - - for($curr_header = 0; $curr_header < count($headers); $curr_header++) { - $cmdline_params .= " -H \"".$headers[$curr_header]."\""; - } - - if(!empty($body)) - $cmdline_params .= " -d \"$body\""; - - if($this->read_timeout > 0) - $cmdline_params .= " -m ".$this->read_timeout; - - $headerfile = uniqid(time()); - - # accept self-signed certs - $cmdline_params .= " -k"; - exec($this->curl_path." -D \"/tmp/$headerfile\"".escapeshellcmd($cmdline_params)." ".escapeshellcmd($URI),$results,$return); - - if($return) - { - $this->error = "Error: cURL could not retrieve the document, error $return."; - return false; - } - - - $results = implode("\r\n",$results); - - $result_headers = file("/tmp/$headerfile"); - - $this->_redirectaddr = false; - unset($this->headers); - - for($currentHeader = 0; $currentHeader < count($result_headers); $currentHeader++) - { - - // if a header begins with Location: or URI:, set the redirect - if(preg_match("/^(Location: |URI: )/i",$result_headers[$currentHeader])) - { - // get URL portion of the redirect - preg_match("/^(Location: |URI:)(.*)/",chop($result_headers[$currentHeader]),$matches); - // look for :// in the Location header to see if hostname is included - if(!preg_match("|\:\/\/|",$matches[2])) - { - // no host in the path, so prepend - $this->_redirectaddr = $URI_PARTS["scheme"]."://".$this->host.":".$this->port; - // eliminate double slash - if(!preg_match("|^/|",$matches[2])) - $this->_redirectaddr .= "/".$matches[2]; - else - $this->_redirectaddr .= $matches[2]; - } - else - $this->_redirectaddr = $matches[2]; - } - - if(preg_match("|^HTTP/|",$result_headers[$currentHeader])) - { - $this->response_code = $result_headers[$currentHeader]; - if(preg_match("|^HTTP/[^\s]*\s(.*?)\s|",$this->response_code, $match)) - { - $this->status= $match[1]; - } - } - $this->headers[] = $result_headers[$currentHeader]; - } - - // check if there is a a redirect meta tag - - if(preg_match("']*?content[\s]*=[\s]*[\"\']?\d+;[\s]+URL[\s]*=[\s]*([^\"\']*?)[\"\']?>'i",$results,$match)) - { - $this->_redirectaddr = $this->_expandlinks($match[1],$URI); - } - - // have we hit our frame depth and is there frame src to fetch? - if(($this->_framedepth < $this->maxframes) && preg_match_all("']+)'i",$results,$match)) - { - $this->results[] = $results; - for($x=0; $x_frameurls[] = $this->_expandlinks($match[1][$x],$URI_PARTS["scheme"]."://".$this->host); - } - // have we already fetched framed content? - elseif(is_array($this->results)) - $this->results[] = $results; - // no framed content - else - $this->results = $results; - - unlink("/tmp/$headerfile"); - - return true; - } - -/*======================================================================*\ - Function: setcookies() - Purpose: set cookies for a redirection -\*======================================================================*/ - - function setcookies() - { - for($x=0; $xheaders); $x++) - { - if(preg_match("/^set-cookie:[\s]+([^=]+)=([^;]+)/i", $this->headers[$x],$match)) - $this->cookies[$match[1]] = $match[2]; - } - } - - -/*======================================================================*\ - Function: _check_timeout - Purpose: checks whether timeout has occurred - Input: $fp file pointer -\*======================================================================*/ - - function _check_timeout($fp) - { - if ($this->read_timeout > 0) { - $fp_status = socket_get_status($fp); - if ($fp_status["timed_out"]) { - $this->timed_out = true; - return true; - } - } - return false; - } - -/*======================================================================*\ - Function: _connect - Purpose: make a socket connection - Input: $fp file pointer -\*======================================================================*/ - - function _connect(&$fp) - { - if(!empty($this->proxy_host) && !empty($this->proxy_port)) - { - $this->_isproxy = true; - $host = $this->proxy_host; - $port = $this->proxy_port; - } - else - { - $host = $this->host; - $port = $this->port; - } - - $this->status = 0; - - if($fp = fsockopen( - $host, - $port, - $errno, - $errstr, - $this->_fp_timeout - )) - { - // socket connection succeeded - - return true; - } - else - { - // socket connection failed - $this->status = $errno; - switch($errno) - { - case -3: - $this->error="socket creation failed (-3)"; - case -4: - $this->error="dns lookup failure (-4)"; - case -5: - $this->error="connection refused or timed out (-5)"; - default: - $this->error="connection failed (".$errno.")"; - } - return false; - } - } -/*======================================================================*\ - Function: _disconnect - Purpose: disconnect a socket connection - Input: $fp file pointer -\*======================================================================*/ - - function _disconnect($fp) - { - return(fclose($fp)); - } - - -/*======================================================================*\ - Function: _prepare_post_body - Purpose: Prepare post body according to encoding type - Input: $formvars - form variables - $formfiles - form upload files - Output: post body -\*======================================================================*/ - - function _prepare_post_body($formvars, $formfiles) - { - settype($formvars, "array"); - settype($formfiles, "array"); - - if (count($formvars) == 0 && count($formfiles) == 0) - return; - - switch ($this->_submit_type) { - case "application/x-www-form-urlencoded": - reset($formvars); - while(list($key,$val) = each($formvars)) { - if (is_array($val) || is_object($val)) { - while (list($cur_key, $cur_val) = each($val)) { - $postdata .= urlencode($key)."[]=".urlencode($cur_val)."&"; - } - } else - $postdata .= urlencode($key)."=".urlencode($val)."&"; - } - break; - - case "multipart/form-data": - $this->_mime_boundary = "Snoopy".md5(uniqid(microtime())); - - reset($formvars); - while(list($key,$val) = each($formvars)) { - if (is_array($val) || is_object($val)) { - while (list($cur_key, $cur_val) = each($val)) { - $postdata .= "--".$this->_mime_boundary."\r\n"; - $postdata .= "Content-Disposition: form-data; name=\"$key\[\]\"\r\n\r\n"; - $postdata .= "$cur_val\r\n"; - } - } else { - $postdata .= "--".$this->_mime_boundary."\r\n"; - $postdata .= "Content-Disposition: form-data; name=\"$key\"\r\n\r\n"; - $postdata .= "$val\r\n"; - } - } - - reset($formfiles); - while (list($field_name, $file_names) = each($formfiles)) { - settype($file_names, "array"); - while (list(, $file_name) = each($file_names)) { - if (!is_readable($file_name)) continue; - - $fp = fopen($file_name, "r"); - $file_content = fread($fp, filesize($file_name)); - fclose($fp); - $base_name = basename($file_name); - - $postdata .= "--".$this->_mime_boundary."\r\n"; - $postdata .= "Content-Disposition: form-data; name=\"$field_name\"; filename=\"$base_name\"\r\n\r\n"; - $postdata .= "$file_content\r\n"; - } - } - $postdata .= "--".$this->_mime_boundary."--\r\n"; - break; - } - - return $postdata; - } -} - -?> diff --git a/html/includes/rss/htdocs/cookbook.html b/html/includes/rss/htdocs/cookbook.html deleted file mode 100644 index 2a18e74..0000000 --- a/html/includes/rss/htdocs/cookbook.html +++ /dev/null @@ -1,237 +0,0 @@ - - - Magie RSS Recipes: Simple PHP RSS How To - - - -

    -

    MagpieRSS Recipes: Cooking with Corbies

    - -

    "Four and twenty blackbirds baked in a -pie."

    -

    -

    -

      -
    1. Limit the Number of Headlines(aka Items) Returned
    2. -
    3. Display a Custom Error Message if Something Goes -Wrong
    4. -
    5. Generate a New RSS Feed
    6. -
    7. Display Headlines More Recent then X Date
    8. -
    9. Parse a Local File Containing RSS
    10. - -
    -

    - -

    1. Limit the Number of Headlines(aka Items) Returned.

    - -

    Problem:

    - -You want to display the 10 (or 3 or whatever) most recent headlines, but the RSS feed -contains 15. - -

    Solution:

    - -
    -$num_items = 10;
    -$rss = fetch_rss($url);
    -
    -$items = array_slice($rss->items, 0, $num_items);
    -
    -foreach ( $items as $item ) {
    -
    -

    Discussion:

    - -Rather then trying to limit the number of items Magpie parses, a much simpler, -and more flexible approach is to take a "slice" of the array of items. And -array_slice() is smart enough to do the right thing if the feed has less items -then $num_items. - -

    See:

    http://www.php.net/array_slice -

    - -

    2. Display a Custom Error Message if Something Goes Wrong

    - -

    Problem:

    - -You don't want Magpie's error messages showing up if something goes wrong. - -

    Solution:

    -
    -# Magpie throws USER_WARNINGS only
    -# so you can cloak these, by only showing ERRORs
    -error_reporting(E_ERROR);
    -
    -# check the return value of fetch_rss()
    -
    -$rss = fetch_rss($url);
    -
    -if ( $rss ) {
    -...display rss feed...
    -}
    -else {
    -   echo "An error occured!  " .
    -        "Consider donating more $$$ for restoration of services." .
    -        "<br>Error Message: " . magpie_error();
    -}
    -
    -

    Discussion:

    - -MagpieRSS triggers a warning in a number of circumstances. The 2 most common -circumstances are: if the specified RSS file isn't properly formed (usually -because it includes illegal HTML), or if Magpie can't download the remote RSS -file, and there is no cached version. - -If you don't want your users to see these warnings change your error_reporting -settings to only display ERRORs.
    -Another option is to turn off display_error, -so that WARNINGs, and NOTICEs still go to the error_log but not to the webpages. - -You can do this with: - -
    -# you can also do this in your php.ini file
    -ini_set('display_errors', 0);
    -
    - -

    See:

    -http://www.php.net/error_reporting,
    -http://www.php.net/ini_set,
    -http://www.php.net/manual/en/ref.errorfunc.php
    - -

    3. Generate a New RSS Feed

    - -

    Problem:

    - -Create an RSS feed for other people to use. - -

    Solution:

    - -Use Useful Inc's RSSWriter. - -

    Discussion:

    - -An example of turning a Magpie parsed RSS object back into an RSS file is -forthcoming. In the meantime RSSWriter is well documented. - -

    4. Display Headlines More Recent then X Date

    - -

    Problem:

    - -You only want to display headlines that were published on, or after a certain -date. - - -

    Solution:

    -
    -require_once('rss_utils.inc');
    -
    -# get all headlines published today
    -$today = getdate();
    -
    -# today, 12AM
    -$date = mktime(0,0,0,$today['mon'], $today['mday'], $today['year']);
    -
    -$rss = fetch_rss($url);
    -
    -foreach ( $rss->items as $item ) {
    -   $published = parse_w3cdtf($item['dc']['date']);
    -   if ( $published >= $date ) {
    -        echo "Title: " . $item['title'];
    -        echo "Published: " . date("h:i:s A", $published);
    -        echo "<p>";
    -    }
    -}
    -
    -

    Discussion:

    - -This recipe only works for RSS 1.0 feeds that include the field. -(which is very good RSS style)
    -parse_w3cdtf() is defined in -rss_utils.inc, and parses RSS style dates into Unix epoch -seconds. - -

    See:

    -http://www.php.net/manual/en/ref.datetime.php - - -

    5. Parse a Local File Containing RSS

    -

    Problem:

    -MagpieRSS provides fetch_rss() which takes a URL and returns a -parsed RSS object, but what if you want to parse a file stored locally that -doesn't have a URL? - -

    Solution

    -
    -require_once('rss_parse.inc');
    -
    -$rss_file = 'some_rss_file.rdf';
    -$rss_string = read_file($rss_file);
    -$rss = new MagpieRSS( $rss_string );
    -
    -if ( $rss and !$rss->ERROR) {
    -...display rss...
    -}
    -else {
    -    echo "Error: " . $rss->ERROR;
    -}
    -
    -# efficiently read a file into a string
    -# in php >= 4.3.0 you can simply use file_get_contents()
    -#
    -function read_file($filename) {
    -    $fh = fopen($filename, 'r') or die($php_errormsg);
    -    $rss_string = fread($fh, filesize($filename) );
    -    fclose($fh);
    -    return $rss_string;
    -}
    -
    - -

    Discussion

    -Here we are using MagpieRSS's RSS parser directly without the convience wrapper -of fetch_rss(). We read the contents of the RSS file into a -string, and pass it to the parser constructor. Notice also that error handling -is subtly different. - -

    See:

    -http://www.php.net/manual/en/ref.filesystem.php,
    -http://www.php.net/manual/en/language.oop.php - - - - - diff --git a/html/includes/rss/htdocs/index.html b/html/includes/rss/htdocs/index.html deleted file mode 100644 index e6b24b5..0000000 --- a/html/includes/rss/htdocs/index.html +++ /dev/null @@ -1,419 +0,0 @@ - - - Magpie RSS - PHP RSS Parser - - - - - -

    MagpieRSS

    -

    -

    MagpieRSS provides an XML-based (expat) RSS parser in PHP.

    -

    - MagpieRSS is compatible with RSS .9 through RSS 1.0, and supports the - RSS 1.0's modules. (with a few exceptions) -

    -

    - -

    News!

    - -

    -

    - -

    Why?

    - I wrote MagpieRSS out of a frustration with the limitations of existing - solutions. In particular many of the existing PHP solutions seemed to: -
      -
    • use a parser based on regular expressions, making for an inherently - fragile solution -
    • only support early versions of RSS -
    • discard all the interesting information besides item title, description, - and link. -
    • not build proper separation between parsing the RSS and displaying it. -
    - In particular I failed to find any PHP RSS parsers that could sufficiently - parse RSS 1.0 feeds, to be useful on the RSS based event feeds we generate - at Protest.net. -

    -

    - -

    Features

    - -
      -
    • -

      Easy to Use

      - As simple as: -
      -require('rss_fetch.inc');
      -$rss = fetch_rss($url);
      -
      - -
    • -
    • -

      Parses RSS 0.9 - RSS 1.0

      - - Parses most RSS formats, including support for - 1.0 modules and limited - namespace support. RSS is packed into convenient data structures; easy to - use in PHP, and appropriate for passing to a templating system, like - Smarty. -
    • -
    • -

      Integrated Object Cache

      - - Caching the parsed RSS means that the 2nd request is fast, and that -including the rss_fetch call in your PHP page won't destroy your performance, -and force you to reply on an external cron job. And it happens transparently. - -
    • -
    • -

      HTTP Conditional GETs

      - - Save bandwidth and speed up download times with intelligent use of - Last-Modified and ETag.
      See HTTP Conditional Get for RSS Hackers -
    • - -
    • Configurable

      - - Makes extensive use of constants to allow overriding default behaviour, and - installation on shared hosts. -
    • -
    • Modular

      -
        -
      • rss_fetch.inc - wraps a simple interface (fetch_rss()) - around the library. -
      • rss_parse.inc - provides the RSS parser, and the RSS object -
      • rss_cache.inc - a simple (no GC) object cache, optimized for RSS objects -
      • rss_utils.inc - utility functions for working with RSS. currently - provides parse_w3cdtf(), for parsing W3CDTF into epoch seconds. -
      -
    - - -

    -

    - -

    Magpie's approach to parsing RSS

    - - Magpie takes a naive, and inclusive approach. Absolutely - non-validating, as long as the RSS feed is well formed, Magpie will - cheerfully parse new, and never before seen tags in your RSS feeds. -

    -

    - This makes it very simple support the varied versions of RSS simply, but - forces the consumer of a RSS feed to be cognizant of how it is - structured.(at least if you want to do something fancy) -

    -

    - Magpie parses a RSS feed into a simple object, with 4 fields: - channel, items, image, and - textinput. -

    -

    -

    channel

    - $rss->channel contains key-value pairs of all tags, without - nested tags, found between the root tag (<rdf:RDF>, or <rss>) - and the end of the document. -

    -

    -

    items

    - $rss->items is an array of associative arrays, each one - describing a single item. An example that looks like: -
    -<item rdf:about="http://protest.net/NorthEast/calendrome.cgi?span=event&ID=210257">
    -<title>Weekly Peace Vigil</title>
    -<link>http://protest.net/NorthEast/calendrome.cgi?span=event&ID=210257</link>
    -<description>Wear a white ribbon</description>
    -<dc:subject>Peace</dc:subject>
    -<ev:startdate>2002-06-01T11:00:00</ev:startdate>
    -<ev:location>Northampton, MA</ev:location>
    -<ev:enddate>2002-06-01T12:00:00</ev:enddate>
    -<ev:type>Protest</ev:type>
    -</item>
    -	

    - Is parsed, and pushed on the $rss->items array as: -

    -array(
    -	title => 'Weekly Peace Vigil',
    -	link => 'http://protest.net/NorthEast/calendrome.cgi?span=event&ID=210257',
    -	description => 'Wear a white ribbon',
    -	dc => array (
    -			subject => 'Peace'
    -		),
    -	ev => array (
    -		startdate => '2002-06-01T11:00:00',
    -		enddate => '2002-06-01T12:00:00',
    -		type => 'Protest',
    -		location => 'Northampton, MA'
    -	)
    -);
    -
    -

    -

    -

    image and textinput

    -$rss->image and $rss-textinput are associative arrays -including name-value pairs for anything found between the respective parent -tags. -

    -

    - -

    Usage Examples:

    - -A very simple example would be: -
    -require_once 'rss_fetch.inc';
    -
    -$url = 'http://magpie.sf.net/samples/imc.1-0.rdf';
    -$rss = fetch_rss($url);
    -
    -echo "Site: ", $rss->channel['title'], "<br>\n";
    -foreach ($rss->items as $item ) {
    -	$title = $item[title];
    -	$url   = $item[link];
    -	echo "<a href=$url>$title</a></li><br>\n";
    -}
    -
    -More soon....in the meantime you can check out a -cool tool built with -MagpieRSS, version 0.1. -

    -

    - -

    Todos

    -

    RSS Parser

    -
      -
    • Swap in a smarter parser that includes optional - support for validation, and required fields.
    • - -
    • Support RSS 2.0 (as much as I'm annoyed by it)
    • - -
    • Improve support for modules that rely on attributes
    • -
    - -

    RSS Cache

    -
      -
    • Light-weight garbage collection -
    - -

    Fetch RSS

    - -

    Misc

    -
      -
    • More examples
    • -
    • A test suite
    • -
    • RSS generation, perhaps with RSSwriter? -
    • -
    - -

    -

    -

    RSS Resources

    - . -

    -

    License and Contact Info

    -Magpie is distributed under the GPL license... -

    -coded by: kellan (at) protest.net, feedback is always appreciated. -

    -SourceForge.net Logo - - - diff --git a/html/includes/rss/rss_cache.inc b/html/includes/rss/rss_cache.inc deleted file mode 100644 index b8d436c..0000000 --- a/html/includes/rss/rss_cache.inc +++ /dev/null @@ -1,200 +0,0 @@ - - * Version: 0.51 - * License: GPL - * - * The lastest version of MagpieRSS can be obtained from: - * http://magpierss.sourceforge.net - * - * For questions, help, comments, discussion, etc., please join the - * Magpie mailing list: - * http://lists.sourceforge.net/lists/listinfo/magpierss-general - * - */ - -class RSSCache { - var $BASE_CACHE = './cache'; // where the cache files are stored - var $MAX_AGE = 3600; // when are files stale, default one hour - var $ERROR = ""; // accumulate error messages - - function RSSCache ($base='', $age='') { - if ( $base ) { - $this->BASE_CACHE = $base; - } - if ( $age ) { - $this->MAX_AGE = $age; - } - - // attempt to make the cache directory - if ( ! file_exists( $this->BASE_CACHE ) ) { - $status = @mkdir( $this->BASE_CACHE, 0755 ); - - // if make failed - if ( ! $status ) { - $this->error( - "Cache couldn't make dir '" . $this->BASE_CACHE . "'." - ); - } - } - } - -/*=======================================================================*\ - Function: set - Purpose: add an item to the cache, keyed on url - Input: url from wich the rss file was fetched - Output: true on sucess -\*=======================================================================*/ - function set ($url, $rss) { - $this->ERROR = ""; - $cache_file = $this->file_name( $url ); - $fp = @fopen( $cache_file, 'w' ); - - if ( ! $fp ) { - $this->error( - "Cache unable to open file for writing: $cache_file" - ); - return 0; - } - - - $data = $this->serialize( $rss ); - fwrite( $fp, $data ); - fclose( $fp ); - - return $cache_file; - } - -/*=======================================================================*\ - Function: get - Purpose: fetch an item from the cache - Input: url from wich the rss file was fetched - Output: cached object on HIT, false on MISS -\*=======================================================================*/ - function get ($url) { - $this->ERROR = ""; - $cache_file = $this->file_name( $url ); - - if ( ! file_exists( $cache_file ) ) { - $this->debug( - "Cache doesn't contain: $url (cache file: $cache_file)" - ); - return 0; - } - - $fp = @fopen($cache_file, 'r'); - if ( ! $fp ) { - $this->error( - "Failed to open cache file for reading: $cache_file" - ); - return 0; - } - - if ($filesize = filesize($cache_file) ) { - $data = fread( $fp, filesize($cache_file) ); - $rss = $this->unserialize( $data ); - - return $rss; - } - - return 0; - } - -/*=======================================================================*\ - Function: check_cache - Purpose: check a url for membership in the cache - and whether the object is older then MAX_AGE (ie. STALE) - Input: url from wich the rss file was fetched - Output: cached object on HIT, false on MISS -\*=======================================================================*/ - function check_cache ( $url ) { - $this->ERROR = ""; - $filename = $this->file_name( $url ); - - if ( file_exists( $filename ) ) { - // find how long ago the file was added to the cache - // and whether that is longer then MAX_AGE - $mtime = filemtime( $filename ); - $age = time() - $mtime; - if ( $this->MAX_AGE > $age ) { - // object exists and is current - return 'HIT'; - } - else { - // object exists but is old - return 'STALE'; - } - } - else { - // object does not exist - return 'MISS'; - } - } - - function cache_age( $cache_key ) { - $filename = $this->file_name( $url ); - if ( file_exists( $filename ) ) { - $mtime = filemtime( $filename ); - $age = time() - $mtime; - return $age; - } - else { - return -1; - } - } - -/*=======================================================================*\ - Function: serialize -\*=======================================================================*/ - function serialize ( $rss ) { - return serialize( $rss ); - } - -/*=======================================================================*\ - Function: unserialize -\*=======================================================================*/ - function unserialize ( $data ) { - return unserialize( $data ); - } - -/*=======================================================================*\ - Function: file_name - Purpose: map url to location in cache - Input: url from wich the rss file was fetched - Output: a file name -\*=======================================================================*/ - function file_name ($url) { - $filename = md5( $url ); - return join( DIRECTORY_SEPARATOR, array( $this->BASE_CACHE, $filename ) ); - } - -/*=======================================================================*\ - Function: error - Purpose: register error -\*=======================================================================*/ - function error ($errormsg, $lvl=E_USER_WARNING) { - // append PHP's error message if track_errors enabled - if ( isset($php_errormsg) ) { - $errormsg .= " ($php_errormsg)"; - } - $this->ERROR = $errormsg; - if ( MAGPIE_DEBUG ) { - trigger_error( $errormsg, $lvl); - } - else { - error_log( $errormsg, 0); - } - } - - function debug ($debugmsg, $lvl=E_USER_NOTICE) { - if ( MAGPIE_DEBUG ) { - $this->error("MagpieRSS [debug] $debugmsg", $lvl); - } - } - -} - -?> diff --git a/html/includes/rss/rss_fetch.inc b/html/includes/rss/rss_fetch.inc deleted file mode 100644 index f2fa2fa..0000000 --- a/html/includes/rss/rss_fetch.inc +++ /dev/null @@ -1,458 +0,0 @@ - - * License: GPL - * - * The lastest version of MagpieRSS can be obtained from: - * http://magpierss.sourceforge.net - * - * For questions, help, comments, discussion, etc., please join the - * Magpie mailing list: - * magpierss-general@lists.sourceforge.net - * - */ - -// Setup MAGPIE_DIR for use on hosts that don't include -// the current path in include_path. -// with thanks to rajiv and smarty -if (!defined('DIR_SEP')) { - define('DIR_SEP', DIRECTORY_SEPARATOR); -} - -if (!defined('MAGPIE_DIR')) { - define('MAGPIE_DIR', dirname(__FILE__) . DIR_SEP); -} - -require_once( MAGPIE_DIR . 'rss_parse.inc' ); -require_once( MAGPIE_DIR . 'rss_cache.inc' ); - -// for including 3rd party libraries -define('MAGPIE_EXTLIB', MAGPIE_DIR . 'extlib' . DIR_SEP); -require_once( MAGPIE_EXTLIB . 'Snoopy.class.inc'); - - -/* - * CONSTANTS - redefine these in your script to change the - * behaviour of fetch_rss() currently, most options effect the cache - * - * MAGPIE_CACHE_ON - Should Magpie cache parsed RSS objects? - * For me a built in cache was essential to creating a "PHP-like" - * feel to Magpie, see rss_cache.inc for rationale - * - * - * MAGPIE_CACHE_DIR - Where should Magpie cache parsed RSS objects? - * This should be a location that the webserver can write to. If this - * directory does not already exist Mapie will try to be smart and create - * it. This will often fail for permissions reasons. - * - * - * MAGPIE_CACHE_AGE - How long to store cached RSS objects? In seconds. - * - * - * MAGPIE_CACHE_FRESH_ONLY - If remote fetch fails, throw error - * instead of returning stale object? - * - * MAGPIE_DEBUG - Display debugging notices? - * -*/ - - -/*=======================================================================*\ - Function: fetch_rss: - Purpose: return RSS object for the give url - maintain the cache - Input: url of RSS file - Output: parsed RSS object (see rss_parse.inc) - - NOTES ON CACHEING: - If caching is on (MAGPIE_CACHE_ON) fetch_rss will first check the cache. - - NOTES ON RETRIEVING REMOTE FILES: - If conditional gets are on (MAGPIE_CONDITIONAL_GET_ON) fetch_rss will - return a cached object, and touch the cache object upon recieving a - 304. - - NOTES ON FAILED REQUESTS: - If there is an HTTP error while fetching an RSS object, the cached - version will be return, if it exists (and if MAGPIE_CACHE_FRESH_ONLY is off) -\*=======================================================================*/ - -define('MAGPIE_VERSION', '0.72'); - -$MAGPIE_ERROR = ""; - -function fetch_rss ($url) { - // initialize constants - init(); - - if ( !isset($url) ) { - error("fetch_rss called without a url"); - return false; - } - - // if cache is disabled - if ( !MAGPIE_CACHE_ON ) { - // fetch file, and parse it - $resp = _fetch_remote_file( $url ); - if ( is_success( $resp->status ) ) { - return _response_to_rss( $resp ); - } - else { - error("Failed to fetch $url and cache is off"); - return false; - } - } - // else cache is ON - else { - // Flow - // 1. check cache - // 2. if there is a hit, make sure its fresh - // 3. if cached obj fails freshness check, fetch remote - // 4. if remote fails, return stale object, or error - - $cache = new RSSCache( MAGPIE_CACHE_DIR, MAGPIE_CACHE_AGE ); - - if (MAGPIE_DEBUG and $cache->ERROR) { - debug($cache->ERROR, E_USER_WARNING); - } - - - $cache_status = 0; // response of check_cache - $request_headers = array(); // HTTP headers to send with fetch - $rss = 0; // parsed RSS object - $errormsg = 0; // errors, if any - - // store parsed XML by desired output encoding - // as character munging happens at parse time - $cache_key = $url . MAGPIE_OUTPUT_ENCODING; - - if (!$cache->ERROR) { - // return cache HIT, MISS, or STALE - $cache_status = $cache->check_cache( $cache_key); - } - - // if object cached, and cache is fresh, return cached obj - if ( $cache_status == 'HIT' ) { - $rss = $cache->get( $cache_key ); - if ( isset($rss) and $rss ) { - // should be cache age - $rss->from_cache = 1; - if ( MAGPIE_DEBUG > 1) { - debug("MagpieRSS: Cache HIT", E_USER_NOTICE); - } - return $rss; - } - } - - // else attempt a conditional get - - // setup headers - if ( $cache_status == 'STALE' ) { - $rss = $cache->get( $cache_key ); - if ( $rss and $rss->etag and $rss->last_modified ) { - $request_headers['If-None-Match'] = $rss->etag; - $request_headers['If-Last-Modified'] = $rss->last_modified; - } - } - - $resp = _fetch_remote_file( $url, $request_headers ); - - if (isset($resp) and $resp) { - if ($resp->status == '304' ) { - // we have the most current copy - if ( MAGPIE_DEBUG > 1) { - debug("Got 304 for $url"); - } - // reset cache on 304 (at minutillo insistent prodding) - $cache->set($cache_key, $rss); - return $rss; - } - elseif ( is_success( $resp->status ) ) { - $rss = _response_to_rss( $resp ); - if ( $rss ) { - if (MAGPIE_DEBUG > 1) { - debug("Fetch successful"); - } - // add object to cache - $cache->set( $cache_key, $rss ); - return $rss; - } - } - else { - $errormsg = "Failed to fetch $url "; - if ( $resp->status == '-100' ) { - $errormsg .= "(Request timed out after " . MAGPIE_FETCH_TIME_OUT . " seconds)"; - } - elseif ( $resp->error ) { - # compensate for Snoopy's annoying habbit to tacking - # on '\n' - $http_error = substr($resp->error, 0, -2); - $errormsg .= "(HTTP Error: $http_error)"; - } - else { - $errormsg .= "(HTTP Response: " . $resp->response_code .')'; - } - } - } - else { - $errormsg = "Unable to retrieve RSS file for unknown reasons."; - } - - // else fetch failed - - // attempt to return cached object - if ($rss) { - if ( MAGPIE_DEBUG ) { - debug("Returning STALE object for $url"); - } - return $rss; - } - - // else we totally failed - error( $errormsg ); - - return false; - - } // end if ( !MAGPIE_CACHE_ON ) { -} // end fetch_rss() - -/*=======================================================================*\ - Function: error - Purpose: set MAGPIE_ERROR, and trigger error -\*=======================================================================*/ - -function error ($errormsg, $lvl=E_USER_WARNING) { - global $MAGPIE_ERROR; - - // append PHP's error message if track_errors enabled - if ( isset($php_errormsg) ) { - $errormsg .= " ($php_errormsg)"; - } - if ( $errormsg ) { - $errormsg = "MagpieRSS: $errormsg"; - $MAGPIE_ERROR = $errormsg; - trigger_error( $errormsg, $lvl); - } -} - -function debug ($debugmsg, $lvl=E_USER_NOTICE) { - trigger_error("MagpieRSS [debug] $debugmsg", $lvl); -} - -/*=======================================================================*\ - Function: magpie_error - Purpose: accessor for the magpie error variable -\*=======================================================================*/ -function magpie_error ($errormsg="") { - global $MAGPIE_ERROR; - - if ( isset($errormsg) and $errormsg ) { - $MAGPIE_ERROR = $errormsg; - } - - return $MAGPIE_ERROR; -} - -/*=======================================================================*\ - Function: _fetch_remote_file - Purpose: retrieve an arbitrary remote file - Input: url of the remote file - headers to send along with the request (optional) - Output: an HTTP response object (see Snoopy.class.inc) -\*=======================================================================*/ -function _fetch_remote_file ($url, $headers = "" ) { - // Snoopy is an HTTP client in PHP - $client = new Snoopy(); - $client->agent = MAGPIE_USER_AGENT; - $client->read_timeout = MAGPIE_FETCH_TIME_OUT; - $client->use_gzip = MAGPIE_USE_GZIP; - if (is_array($headers) ) { - $client->rawheaders = $headers; - } - - @$client->fetch($url); - return $client; - -} - -/*=======================================================================*\ - Function: _response_to_rss - Purpose: parse an HTTP response object into an RSS object - Input: an HTTP response object (see Snoopy) - Output: parsed RSS object (see rss_parse) -\*=======================================================================*/ -function _response_to_rss ($resp) { - $rss = new MagpieRSS( $resp->results, MAGPIE_OUTPUT_ENCODING, MAGPIE_INPUT_ENCODING, MAGPIE_DETECT_ENCODING ); - - // if RSS parsed successfully - if ( $rss and !$rss->ERROR) { - - // find Etag, and Last-Modified - foreach($resp->headers as $h) { - // 2003-03-02 - Nicola Asuni (www.tecnick.com) - fixed bug "Undefined offset: 1" - if (strpos($h, ": ")) { - list($field, $val) = explode(": ", $h, 2); - } - else { - $field = $h; - $val = ""; - } - - if ( $field == 'ETag' ) { - $rss->etag = $val; - } - - if ( $field == 'Last-Modified' ) { - $rss->last_modified = $val; - } - } - - return $rss; - } // else construct error message - else { - $errormsg = "Failed to parse RSS file."; - - if ($rss) { - $errormsg .= " (" . $rss->ERROR . ")"; - } - error($errormsg); - - return false; - } // end if ($rss and !$rss->error) -} - -/*=======================================================================*\ - Function: init - Purpose: setup constants with default values - check for user overrides -\*=======================================================================*/ -function init () { - if ( defined('MAGPIE_INITALIZED') ) { - return; - } - else { - define('MAGPIE_INITALIZED', true); - } - - if ( !defined('MAGPIE_CACHE_ON') ) { - define('MAGPIE_CACHE_ON', true); - } - - if ( !defined('MAGPIE_CACHE_DIR') ) { - define('MAGPIE_CACHE_DIR', './cache'); - } - - if ( !defined('MAGPIE_CACHE_AGE') ) { - define('MAGPIE_CACHE_AGE', 60*60); // one hour - } - - if ( !defined('MAGPIE_CACHE_FRESH_ONLY') ) { - define('MAGPIE_CACHE_FRESH_ONLY', false); - } - - if ( !defined('MAGPIE_OUTPUT_ENCODING') ) { - define('MAGPIE_OUTPUT_ENCODING', 'ISO-8859-1'); - } - - if ( !defined('MAGPIE_INPUT_ENCODING') ) { - define('MAGPIE_INPUT_ENCODING', null); - } - - if ( !defined('MAGPIE_DETECT_ENCODING') ) { - define('MAGPIE_DETECT_ENCODING', true); - } - - if ( !defined('MAGPIE_DEBUG') ) { - define('MAGPIE_DEBUG', 0); - } - - if ( !defined('MAGPIE_USER_AGENT') ) { - $ua = 'MagpieRSS/'. MAGPIE_VERSION . ' (+http://magpierss.sf.net'; - - if ( MAGPIE_CACHE_ON ) { - $ua = $ua . ')'; - } - else { - $ua = $ua . '; No cache)'; - } - - define('MAGPIE_USER_AGENT', $ua); - } - - if ( !defined('MAGPIE_FETCH_TIME_OUT') ) { - define('MAGPIE_FETCH_TIME_OUT', 5); // 5 second timeout - } - - // use gzip encoding to fetch rss files if supported? - if ( !defined('MAGPIE_USE_GZIP') ) { - define('MAGPIE_USE_GZIP', true); - } -} - -// NOTE: the following code should really be in Snoopy, or at least -// somewhere other then rss_fetch! - -/*=======================================================================*\ - HTTP STATUS CODE PREDICATES - These functions attempt to classify an HTTP status code - based on RFC 2616 and RFC 2518. - - All of them take an HTTP status code as input, and return true or false - - All this code is adapted from LWP's HTTP::Status. -\*=======================================================================*/ - - -/*=======================================================================*\ - Function: is_info - Purpose: return true if Informational status code -\*=======================================================================*/ -function is_info ($sc) { - return $sc >= 100 && $sc < 200; -} - -/*=======================================================================*\ - Function: is_success - Purpose: return true if Successful status code -\*=======================================================================*/ -function is_success ($sc) { - return $sc >= 200 && $sc < 300; -} - -/*=======================================================================*\ - Function: is_redirect - Purpose: return true if Redirection status code -\*=======================================================================*/ -function is_redirect ($sc) { - return $sc >= 300 && $sc < 400; -} - -/*=======================================================================*\ - Function: is_error - Purpose: return true if Error status code -\*=======================================================================*/ -function is_error ($sc) { - return $sc >= 400 && $sc < 600; -} - -/*=======================================================================*\ - Function: is_client_error - Purpose: return true if Error status code, and its a client error -\*=======================================================================*/ -function is_client_error ($sc) { - return $sc >= 400 && $sc < 500; -} - -/*=======================================================================*\ - Function: is_client_error - Purpose: return true if Error status code, and its a server error -\*=======================================================================*/ -function is_server_error ($sc) { - return $sc >= 500 && $sc < 600; -} - -?> diff --git a/html/includes/rss/rss_parse.inc b/html/includes/rss/rss_parse.inc deleted file mode 100644 index 56d420f..0000000 --- a/html/includes/rss/rss_parse.inc +++ /dev/null @@ -1,605 +0,0 @@ - -* @version 0.7a -* @license GPL -* -*/ - -define('RSS', 'RSS'); -define('ATOM', 'Atom'); - -require_once (MAGPIE_DIR . 'rss_utils.inc'); - -/** -* Hybrid parser, and object, takes RSS as a string and returns a simple object. -* -* see: rss_fetch.inc for a simpler interface with integrated caching support -* -*/ -class MagpieRSS { - var $parser; - - var $current_item = array(); // item currently being parsed - var $items = array(); // collection of parsed items - var $channel = array(); // hash of channel fields - var $textinput = array(); - var $image = array(); - var $feed_type; - var $feed_version; - var $encoding = ''; // output encoding of parsed rss - - var $_source_encoding = ''; // only set if we have to parse xml prolog - - var $ERROR = ""; - var $WARNING = ""; - - // define some constants - - var $_CONTENT_CONSTRUCTS = array('content', 'summary', 'info', 'title', 'tagline', 'copyright'); - var $_KNOWN_ENCODINGS = array('UTF-8', 'US-ASCII', 'ISO-8859-1'); - - // parser variables, useless if you're not a parser, treat as private - var $stack = array(); // parser stack - var $inchannel = false; - var $initem = false; - var $incontent = false; // if in Atom field - var $intextinput = false; - var $inimage = false; - var $current_namespace = false; - - - /** - * Set up XML parser, parse source, and return populated RSS object.. - * - * @param string $source string containing the RSS to be parsed - * - * NOTE: Probably a good idea to leave the encoding options alone unless - * you know what you're doing as PHP's character set support is - * a little weird. - * - * NOTE: A lot of this is unnecessary but harmless with PHP5 - * - * - * @param string $output_encoding output the parsed RSS in this character - * set defaults to ISO-8859-1 as this is PHP's - * default. - * - * NOTE: might be changed to UTF-8 in future - * versions. - * - * @param string $input_encoding the character set of the incoming RSS source. - * Leave blank and Magpie will try to figure it - * out. - * - * - * @param bool $detect_encoding if false Magpie won't attempt to detect - * source encoding. (caveat emptor) - * - */ - function MagpieRSS ($source, $output_encoding='ISO-8859-1', - $input_encoding=null, $detect_encoding=true) - { - # if PHP xml isn't compiled in, die - # - if (!function_exists('xml_parser_create')) { - $this->error( "Failed to load PHP's XML Extension. " . - "http://www.php.net/manual/en/ref.xml.php", - E_USER_ERROR ); - } - - list($parser, $source) = $this->create_parser($source, - $output_encoding, $input_encoding, $detect_encoding); - - - if (!is_resource($parser)) { - $this->error( "Failed to create an instance of PHP's XML parser. " . - "http://www.php.net/manual/en/ref.xml.php", - E_USER_ERROR ); - } - - - $this->parser = $parser; - - # pass in parser, and a reference to this object - # setup handlers - # - xml_set_object( $this->parser, $this ); - xml_set_element_handler($this->parser, - 'feed_start_element', 'feed_end_element' ); - - xml_set_character_data_handler( $this->parser, 'feed_cdata' ); - - $status = xml_parse( $this->parser, $source ); - - if (! $status ) { - $errorcode = xml_get_error_code( $this->parser ); - if ( $errorcode != XML_ERROR_NONE ) { - $xml_error = xml_error_string( $errorcode ); - $error_line = xml_get_current_line_number($this->parser); - $error_col = xml_get_current_column_number($this->parser); - $errormsg = "$xml_error at line $error_line, column $error_col"; - - $this->error( $errormsg ); - } - } - - xml_parser_free( $this->parser ); - - $this->normalize(); - } - - function feed_start_element($p, $element, &$attrs) { - $el = $element = strtolower($element); - $attrs = array_change_key_case($attrs, CASE_LOWER); - - // check for a namespace, and split if found - $ns = false; - if ( strpos( $element, ':' ) ) { - list($ns, $el) = split( ':', $element, 2); - } - if ( $ns and $ns != 'rdf' ) { - $this->current_namespace = $ns; - } - - # if feed type isn't set, then this is first element of feed - # identify feed from root element - # - if (!isset($this->feed_type) ) { - if ( $el == 'rdf' ) { - $this->feed_type = RSS; - $this->feed_version = '1.0'; - } - elseif ( $el == 'rss' ) { - $this->feed_type = RSS; - $this->feed_version = $attrs['version']; - } - elseif ( $el == 'feed' ) { - $this->feed_type = ATOM; - $this->feed_version = $attrs['version']; - $this->inchannel = true; - } - return; - } - - if ( $el == 'channel' ) - { - $this->inchannel = true; - } - elseif ($el == 'item' or $el == 'entry' ) - { - $this->initem = true; - if ( isset($attrs['rdf:about']) ) { - $this->current_item['about'] = $attrs['rdf:about']; - } - } - - // if we're in the default namespace of an RSS feed, - // record textinput or image fields - elseif ( - $this->feed_type == RSS and - $this->current_namespace == '' and - $el == 'textinput' ) - { - $this->intextinput = true; - } - - elseif ( - $this->feed_type == RSS and - $this->current_namespace == '' and - $el == 'image' ) - { - $this->inimage = true; - } - - # handle atom content constructs - elseif ( $this->feed_type == ATOM and in_array($el, $this->_CONTENT_CONSTRUCTS) ) - { - // avoid clashing w/ RSS mod_content - if ($el == 'content' ) { - $el = 'atom_content'; - } - - $this->incontent = $el; - - - } - - // if inside an Atom content construct (e.g. content or summary) field treat tags as text - elseif ($this->feed_type == ATOM and $this->incontent ) - { - // if tags are inlined, then flatten - $attrs_str = join(' ', - array_map('map_attrs', - array_keys($attrs), - array_values($attrs) ) ); - - $this->append_content( "<$element $attrs_str>" ); - - array_unshift( $this->stack, $el ); - } - - // Atom support many links per containging element. - // Magpie treats link elements of type rel='alternate' - // as being equivalent to RSS's simple link element. - // - elseif ($this->feed_type == ATOM and $el == 'link' ) - { - if ( isset($attrs['rel']) and $attrs['rel'] == 'alternate' ) - { - $link_el = 'link'; - } - else { - $link_el = 'link_' . $attrs['rel']; - } - - $this->append($link_el, $attrs['href']); - } - // set stack[0] to current element - else { - array_unshift($this->stack, $el); - } - } - - - - function feed_cdata ($p, $text) { - if ($this->feed_type == ATOM and $this->incontent) - { - $this->append_content( $text ); - } - else { - $current_el = join('_', array_reverse($this->stack)); - $this->append($current_el, $text); - } - } - - function feed_end_element ($p, $el) { - $el = strtolower($el); - - if ( $el == 'item' or $el == 'entry' ) - { - $this->items[] = $this->current_item; - $this->current_item = array(); - $this->initem = false; - } - elseif ($this->feed_type == RSS and $this->current_namespace == '' and $el == 'textinput' ) - { - $this->intextinput = false; - } - elseif ($this->feed_type == RSS and $this->current_namespace == '' and $el == 'image' ) - { - $this->inimage = false; - } - elseif ($this->feed_type == ATOM and in_array($el, $this->_CONTENT_CONSTRUCTS) ) - { - $this->incontent = false; - } - elseif ($el == 'channel' or $el == 'feed' ) - { - $this->inchannel = false; - } - elseif ($this->feed_type == ATOM and $this->incontent ) { - // balance tags properly - // note: i don't think this is actually neccessary - if ( $this->stack[0] == $el ) - { - $this->append_content(""); - } - else { - $this->append_content("<$el />"); - } - - array_shift( $this->stack ); - } - else { - array_shift( $this->stack ); - } - - $this->current_namespace = false; - } - - function concat (&$str1, $str2="") { - if (!isset($str1) ) { - $str1=""; - } - $str1 .= $str2; - } - - - - function append_content($text) { - if ( $this->initem ) { - $this->concat( $this->current_item[ $this->incontent ], $text ); - } - elseif ( $this->inchannel ) { - $this->concat( $this->channel[ $this->incontent ], $text ); - } - } - - // smart append - field and namespace aware - function append($el, $text) { - if (!$el) { - return; - } - if ( $this->current_namespace ) - { - if ( $this->initem ) { - $this->concat( - $this->current_item[ $this->current_namespace ][ $el ], $text); - } - elseif ($this->inchannel) { - $this->concat( - $this->channel[ $this->current_namespace][ $el ], $text ); - } - elseif ($this->intextinput) { - $this->concat( - $this->textinput[ $this->current_namespace][ $el ], $text ); - } - elseif ($this->inimage) { - $this->concat( - $this->image[ $this->current_namespace ][ $el ], $text ); - } - } - else { - if ( $this->initem ) { - $this->concat( - $this->current_item[ $el ], $text); - } - elseif ($this->intextinput) { - $this->concat( - $this->textinput[ $el ], $text ); - } - elseif ($this->inimage) { - $this->concat( - $this->image[ $el ], $text ); - } - elseif ($this->inchannel) { - $this->concat( - $this->channel[ $el ], $text ); - } - - } - } - - function normalize () { - // if atom populate rss fields - if ( $this->is_atom() ) { - $this->channel['description'] = $this->channel['tagline']; - for ( $i = 0; $i < count($this->items); $i++) { - $item = $this->items[$i]; - if ( isset($item['summary']) ) - $item['description'] = $item['summary']; - if ( isset($item['atom_content'])) - $item['content']['encoded'] = $item['atom_content']; - - $atom_date = (isset($item['issued']) ) ? $item['issued'] : $item['modified']; - if ( $atom_date ) { - $epoch = @parse_w3cdtf($atom_date); - if ($epoch and $epoch > 0) { - $item['date_timestamp'] = $epoch; - } - } - - $this->items[$i] = $item; - } - } - elseif ( $this->is_rss() ) { - $this->channel['tagline'] = $this->channel['description']; - for ( $i = 0; $i < count($this->items); $i++) { - $item = $this->items[$i]; - if ( isset($item['description'])) - $item['summary'] = $item['description']; - if ( isset($item['content']['encoded'] ) ) - $item['atom_content'] = $item['content']['encoded']; - - if ( $this->is_rss() == '1.0' and isset($item['dc']['date']) ) { - $epoch = @parse_w3cdtf($item['dc']['date']); - if ($epoch and $epoch > 0) { - $item['date_timestamp'] = $epoch; - } - } - elseif ( isset($item['pubdate']) ) { - $epoch = @strtotime($item['pubdate']); - if ($epoch > 0) { - $item['date_timestamp'] = $epoch; - } - } - - $this->items[$i] = $item; - } - } - } - - - function is_rss () { - if ( $this->feed_type == RSS ) { - return $this->feed_version; - } - else { - return false; - } - } - - function is_atom() { - if ( $this->feed_type == ATOM ) { - return $this->feed_version; - } - else { - return false; - } - } - - /** - * return XML parser, and possibly re-encoded source - * - */ - function create_parser($source, $out_enc, $in_enc, $detect) { - if ( substr(phpversion(),0,1) == 5) { - $parser = $this->php5_create_parser($in_enc, $detect); - } - else { - list($parser, $source) = $this->php4_create_parser($source, $in_enc, $detect); - } - if ($out_enc) { - $this->encoding = $out_enc; - xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, $out_enc); - } - - return array($parser, $source); - } - - /** - * Instantiate an XML parser under PHP5 - * - * PHP5 will do a fine job of detecting input encoding - * if passed an empty string as the encoding. - * - * All hail libxml2! - * - */ - function php5_create_parser($in_enc, $detect) { - // by default php5 does a fine job of detecting input encodings - if(!$detect && $in_enc) { - return xml_parser_create($in_enc); - } - else { - return xml_parser_create(''); - } - } - - /** - * Instaniate an XML parser under PHP4 - * - * Unfortunately PHP4's support for character encodings - * and especially XML and character encodings sucks. As - * long as the documents you parse only contain characters - * from the ISO-8859-1 character set (a superset of ASCII, - * and a subset of UTF-8) you're fine. However once you - * step out of that comfy little world things get mad, bad, - * and dangerous to know. - * - * The following code is based on SJM's work with FoF - * @see http://minutillo.com/steve/weblog/2004/6/17/php-xml-and-character-encodings-a-tale-of-sadness-rage-and-data-loss - * - */ - function php4_create_parser($source, $in_enc, $detect) { - if ( !$detect ) { - return array(xml_parser_create($in_enc), $source); - } - - if (!$in_enc) { - if (preg_match('//m', $source, $m)) { - $in_enc = strtoupper($m[1]); - $this->source_encoding = $in_enc; - } - else { - $in_enc = 'UTF-8'; - } - } - - if ($this->known_encoding($in_enc)) { - return array(xml_parser_create($in_enc), $source); - } - - // the dectected encoding is not one of the simple encodings PHP knows - - // attempt to use the iconv extension to - // cast the XML to a known encoding - // @see http://php.net/iconv - - if (function_exists('iconv')) { - $encoded_source = iconv($in_enc,'UTF-8', $source); - if ($encoded_source) { - return array(xml_parser_create('UTF-8'), $encoded_source); - } - } - - // iconv didn't work, try mb_convert_encoding - // @see http://php.net/mbstring - if(function_exists('mb_convert_encoding')) { - $encoded_source = mb_convert_encoding($source, 'UTF-8', $in_enc ); - if ($encoded_source) { - return array(xml_parser_create('UTF-8'), $encoded_source); - } - } - - // else - $this->error("Feed is in an unsupported character encoding. ($in_enc) " . - "You may see strange artifacts, and mangled characters.", - E_USER_NOTICE); - - return array(xml_parser_create(), $source); - } - - function known_encoding($enc) { - $enc = strtoupper($enc); - if ( in_array($enc, $this->_KNOWN_ENCODINGS) ) { - return $enc; - } - else { - return false; - } - } - - function error ($errormsg, $lvl=E_USER_WARNING) { - // append PHP's error message if track_errors enabled - if ( isset($php_errormsg) ) { - $errormsg .= " ($php_errormsg)"; - } - if ( MAGPIE_DEBUG ) { - trigger_error( $errormsg, $lvl); - } - else { - error_log( $errormsg, 0); - } - - $notices = E_USER_NOTICE|E_NOTICE; - if ( $lvl&$notices ) { - $this->WARNING = $errormsg; - } else { - $this->ERROR = $errormsg; - } - } - - -} // end class RSS - -function map_attrs($k, $v) { - return "$k=\"$v\""; -} - -// patch to support medieval versions of PHP4.1.x, -// courtesy, Ryan Currie, ryan@digibliss.com - -if (!function_exists('array_change_key_case')) { - define("CASE_UPPER",1); - define("CASE_LOWER",0); - - - function array_change_key_case($array,$case=CASE_LOWER) { - if ($case=CASE_LOWER) $cmd=strtolower; - elseif ($case=CASE_UPPER) $cmd=strtoupper; - foreach($array as $key=>$value) { - $output[$cmd($key)]=$value; - } - return $output; - } - -} - -?> diff --git a/html/includes/rss/rss_utils.inc b/html/includes/rss/rss_utils.inc deleted file mode 100644 index 2a29e72..0000000 --- a/html/includes/rss/rss_utils.inc +++ /dev/null @@ -1,67 +0,0 @@ - - * Version: 0.51 - * License: GPL - * - * The lastest version of MagpieRSS can be obtained from: - * http://magpierss.sourceforge.net - * - * For questions, help, comments, discussion, etc., please join the - * Magpie mailing list: - * magpierss-general@lists.sourceforge.net - */ - - -/*======================================================================*\ - Function: parse_w3cdtf - Purpose: parse a W3CDTF date into unix epoch - - NOTE: http://www.w3.org/TR/NOTE-datetime -\*======================================================================*/ - -function parse_w3cdtf ( $date_str ) { - - # regex to match wc3dtf - $pat = "/(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})(:(\d{2}))?(?:([-+])(\d{2}):?(\d{2})|(Z))?/"; - - if ( preg_match( $pat, $date_str, $match ) ) { - list( $year, $month, $day, $hours, $minutes, $seconds) = - array( $match[1], $match[2], $match[3], $match[4], $match[5], $match[6]); - - # calc epoch for current date assuming GMT - $epoch = gmmktime( $hours, $minutes, $seconds, $month, $day, $year); - - $offset = 0; - if ( $match[10] == 'Z' ) { - # zulu time, aka GMT - } - else { - list( $tz_mod, $tz_hour, $tz_min ) = - array( $match[8], $match[9], $match[10]); - - # zero out the variables - if ( ! $tz_hour ) { $tz_hour = 0; } - if ( ! $tz_min ) { $tz_min = 0; } - - $offset_secs = (($tz_hour*60)+$tz_min)*60; - - # is timezone ahead of GMT? then subtract offset - # - if ( $tz_mod == '+' ) { - $offset_secs = $offset_secs * -1; - } - - $offset = $offset_secs; - } - $epoch = $epoch + $offset; - return $epoch; - } - else { - return -1; - } -} - -?> diff --git a/html/includes/rss/scripts/README b/html/includes/rss/scripts/README deleted file mode 100644 index e37afe5..0000000 --- a/html/includes/rss/scripts/README +++ /dev/null @@ -1,27 +0,0 @@ -Some example on how to use Magpie: - -* magpie_simple.php * - Simple example of fetching and parsing an RSS file. Expects to be - called with a query param 'rss_url=http://' - -* simple_smarty.php * - Similiar to magpie_simple, but using the Smarty template engine to do - display. Also demostrates using rss_utils.inc and a smarty plugin to - parse and display when each RSS item was published. - -* magpie_debug.php * - Displays all the information available from a parsed feed. - -* smarty_plugin/modifier.rss_date_parse.php * - - A Smarty plugin for parsing RSS style dates. You must include rss_utils.inc - for this plugin to work. It also must be installed in the Smarty plugin - directory, see the Smarty docs for details. - -* templates/simple.smarty - A Smarty template used by simple_smarty.php which demostrates - displaying an RSS feed and using the date parse plugin. - - -The Smarty template engine and documentation on how to use it are available from -http://smarty.php.net diff --git a/html/includes/rss/scripts/magpie_debug.php b/html/includes/rss/scripts/magpie_debug.php deleted file mode 100644 index 84549db..0000000 --- a/html/includes/rss/scripts/magpie_debug.php +++ /dev/null @@ -1,80 +0,0 @@ -Example Output"; - echo "Channel: " . $rss->channel['title'] . "

    "; - echo "

      "; - foreach ($rss->items as $item) { - $href = $item['link']; - $title = $item['title']; - echo "
    • $title
    • "; - } - echo "
    "; -} -else { - echo "Error: " . magpie_error(); -} -?> - -
    - RSS URL:
    - -
    - -

    Parsed Results (var_dump'ed)

    -
    -
    -
    - -Error: PHP compiled without XML support (--with-xml), Mapgie won't work without PHP support for XML.
    \n"; - exit; - } - else { - echo "OK: Found an XML parser.
    \n"; - } - - if ( ! function_exists('gzinflate') ) { - echo "Warning: PHP compiled without Zlib support (--with-zlib). No support for GZIP encoding.
    \n"; - } - else { - echo "OK: Support for GZIP encoding.
    \n"; - } - - if ( ! (function_exists('iconv') and function_exists('mb_convert_encoding') ) ) { - echo "Warning: No support for iconv (--with-iconv) or multi-byte strings (--enable-mbstring)." . - "No support character set munging.
    \n"; - } - else { - echo "OK: Support for character munging.
    \n"; - } -} - -?> diff --git a/html/includes/rss/scripts/magpie_simple.php b/html/includes/rss/scripts/magpie_simple.php deleted file mode 100644 index 282735e..0000000 --- a/html/includes/rss/scripts/magpie_simple.php +++ /dev/null @@ -1,29 +0,0 @@ -channel['title'] . "

    "; - echo "

      "; - foreach ($rss->items as $item) { - $href = $item['link']; - $title = $item['title']; - echo "
    • $title
    • "; - } - echo "
    "; -} -?> - -
    - RSS URL:
    - -
    - -

    -

    Security Note:

    -This is a simple example script. If this was a real script we probably wouldn't allow strangers to submit random URLs, and we certainly wouldn't simply echo anything passed in the URL. Additionally its a bad idea to leave this example script lying around. -

    \ No newline at end of file diff --git a/html/includes/rss/scripts/magpie_slashbox.php b/html/includes/rss/scripts/magpie_slashbox.php deleted file mode 100644 index bbef30b..0000000 --- a/html/includes/rss/scripts/magpie_slashbox.php +++ /dev/null @@ -1,66 +0,0 @@ - - - - -
    - -
    - -"; - $rss = fetch_rss( $url ); - echo slashbox ($rss); -} - -echo "
    ";
    -print_r($rss);
    -echo "
    "; -?> - - - - -
    "; - - # get the channel title and link properties off of the rss object - # - $title = $rss->channel['title']; - $link = $rss->channel['link']; - - echo "$title"; - echo "
    "; - echo ""; - echo $item['title']; - echo "
    "; -} - -?> diff --git a/html/includes/rss/scripts/simple_smarty.php b/html/includes/rss/scripts/simple_smarty.php deleted file mode 100644 index a904d88..0000000 --- a/html/includes/rss/scripts/simple_smarty.php +++ /dev/null @@ -1,58 +0,0 @@ -compile_check = true; - -// url of an rss file -$url = $_GET['rss_url']; - - -if ( $url ) { - // assign a variable to smarty for use in the template - $smarty->assign('rss_url', $url); - - // use MagpieRSS to fetch remote RSS file, and parse it - $rss = fetch_rss( $url ); - - // if fetch_rss returned false, we encountered an error - if ( !$rss ) { - $smarty->assign( 'error', magpie_error() ); - } - $smarty->assign('rss', $rss ); - - $item = $rss->items[0]; - $date = parse_w3cdtf( $item['dc']['date'] ); - $smarty->assign( 'date', $date ); -} - -// parse smarty template, and display using the variables we assigned -$smarty->display('simple.smarty'); - -?> diff --git a/html/includes/rss/scripts/smarty_plugin/modifier.rss_date_parse.php b/html/includes/rss/scripts/smarty_plugin/modifier.rss_date_parse.php deleted file mode 100644 index 593270e..0000000 --- a/html/includes/rss/scripts/smarty_plugin/modifier.rss_date_parse.php +++ /dev/null @@ -1,31 +0,0 @@ - diff --git a/html/includes/rss/scripts/templates/simple.smarty b/html/includes/rss/scripts/templates/simple.smarty deleted file mode 100644 index c0761cf..0000000 --- a/html/includes/rss/scripts/templates/simple.smarty +++ /dev/null @@ -1,46 +0,0 @@ - - -A Simple RSS Box: I'm not a designer - - - -
    -RSS File: - - -
    - -Displaying: {$rss_url} -

    - -{* if $error display the error - elseif parsed RSS object display the RSS - else solicit user for a URL -*} - -{if $error } -Error: {$error} -{elseif $rss} - - - - - {foreach from=$rss->items item=item} - - - - - {/foreach} -
    - {$rss->channel.title} -
    - {$item.title} - - {$item.dc.date|rss_date_parse|date_format:"%A, %B %e, %Y"} -
    -{else} - Enter the URL of an RSS file to display. -{/if} - - - diff --git a/html/includes/utils.inc.php b/html/includes/utils.inc.php index 1fbd948..3e499c9 100644 --- a/html/includes/utils.inc.php +++ b/html/includes/utils.inc.php @@ -5,7 +5,7 @@ require_once(dirname(__FILE__).'/../config.inc.php'); function get_update_information(){ global $cfg; - + // initialize array $updateinfo=array( "found_update_info" => false, @@ -86,7 +86,7 @@ function get_update_information(){ // Nagios might be shutdown (ie, no status file), so try and read data from the retention file - // read retentiion file (just first few lines) + // read retention file (just first few lines) $rfc=read_retention_file($rf,50); //print_r($rfc); //exit(); @@ -217,6 +217,7 @@ function read_cgi_config_file($thefile=""){ // do not allow for multiple values $contents[$v[0]] = $v[1]; + $cfg[$v[0]] = $v[1]; } } fclose($fh); diff --git a/html/index.php b/html/index.php deleted file mode 100644 index 55be47a..0000000 --- a/html/index.php +++ /dev/null @@ -1,64 +0,0 @@ - - - - - -Nagios Core - - - - - - - - - - - -<!-- This page requires a web browser which supports frames. --> -<h2>Nagios Core</h2> -<p align="center"> -<a href="http://www.nagios.org/">www.nagios.org</a><br> -Copyright &copy; 2010-<?php echo date("Y");?> Nagios Core Development Team and Community Contributors. -Copyright &copy; 1999-2010 Ethan Galstad<br> -</p> -<p> -<i>Note: These pages require a browser which supports frames</i> -</p> - - - - - - diff --git a/html/index.php.in b/html/index.php.in new file mode 100644 index 0000000..ffe368d --- /dev/null +++ b/html/index.php.in @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + <!-- This page requires a web browser which supports frames. --> + <h2>Nagios Core</h2> + <p align="center"> + <a href="https://www.nagios.org/">www.nagios.org</a><br> + Copyright &copy; 2010-<?php echo $this_year; ?> Nagios Core Development Team and Community Contributors. + Copyright &copy; 1999-2010 Ethan Galstad<br> + </p> + <p> + <i>Note: These pages require a browser which supports frames</i> + </p> + + + + diff --git a/html/infobox.html b/html/infobox.html new file mode 100644 index 0000000..e241e31 --- /dev/null +++ b/html/infobox.html @@ -0,0 +1,51 @@ + + + + + + +
    + + + {{decorationTitle}} + +
    + Last Updated: {{lastUpdate | date:'EEE MMM dd HH:mm:ss yyyy'}} +
    + Nagios® Core™ {{json.data.programstatus.version}} - + www.nagios.org +
    + + Updated every {{updateInterval}} seconds +
    +
    + + Logged in as {{json.result.user}} +
    +
    +
    + Warning: Monitoring process may not be running! +
    + Click here + for more info. +
    + +
    + - Notifications are disabled +
    +
    + - Service checks are disabled +
    +
    +
    +

    diff --git a/html/js/histogram-events.js b/html/js/histogram-events.js new file mode 100644 index 0000000..ad177a1 --- /dev/null +++ b/html/js/histogram-events.js @@ -0,0 +1,85 @@ +angular.module("histogramEvents", []) + + .service("histogramEventsService", function() { + // Raw events values + this.hostUp = 1; + this.hostDown = 2; + this.hostUnreachable = 4; + this.serviceOk = 8; + this.serviceWarning = 16; + this.serviceUnknown = 32; + this.serviceCritical = 64; + + // Calculated events values + this.hostProblems = this.hostDown + this.hostUnreachable; + this.hostAll = this.hostUp + this.hostProblems; + this.serviceProblems = this.serviceWarning + + this.serviceUnknown + this.serviceCritical; + this.serviceAll = this.serviceOK + this.serviceProblems; + + return { + // Host events list + hostEvents: [ + { + value: this.hostAll, + label: "All host events", + states: "up down unreachable" + }, + { + value: this.hostProblems, + label: "Host problem events", + states: "down unreachable" + }, + { + value: this.hostUp, + label: "Host up events", + states: "up" + }, + { + value: this.hostDown, + label: "Host down events", + states: "down" + }, + { + value: this.hostUnreachable, + label: "Host unreachable events", + states: "unreachable" + } + ], + + // Service events list + serviceEvents: [ + { + value: this.serviceAll, + label: "All service events", + states: "ok warning unknown critical" + }, + { + value: this.serviceProblems, + label: "Service problem events", + states: "warning unknown critical" + }, + { + value: this.serviceOk, + label: "Service ok events", + states: "ok" + }, + { + value: this.serviceWarning, + label: "Service warning events", + states: "warning" + }, + { + value: this.serviceUnknown, + label: "Service unknown events", + states: "unknown" + }, + { + value: this.serviceCritical, + label: "Service critical events", + states: "critical" + }, + ] + }; + }); + diff --git a/html/js/histogram-form.js b/html/js/histogram-form.js new file mode 100644 index 0000000..da8ceef --- /dev/null +++ b/html/js/histogram-form.js @@ -0,0 +1,184 @@ +angular.module("histogramApp") + .controller("histogramFormCtrl", function($scope, $modalInstance, $http, + statisticsBreakdown, histogramEventsService, nagiosTimeService, + params) { + + $scope.params = params; + $scope.hostlist = []; + $scope.servicelist = []; + $scope.timeperiodlist = nagiosTimeService.timeperiodlist(); + $scope.statisticsBreakdown = statisticsBreakdown; + + if (!$scope.params.hasOwnProperty("t1")) { + $scope.params.t1 = 0; + } + + if (!$scope.params.hasOwnProperty("t2")) { + $scope.params.t2 = 0; + } + + $scope.apply = function () { + if ($scope.params.timeperiod != "custom") { + var times = nagiosTimeService.calculateReportTimes(new Date(), + $scope.params.timeperiod); + $scope.params.t1 = times.start.getTime() / 1000; + $scope.params.t2 = times.end.getTime() / 1000; + } + $modalInstance.close($scope.params); + }; + + $scope.cancel = function () { + $modalInstance.dismiss('cancel'); + }; + + $scope.showHost = function() { + return $scope.params.reporttype != ""; + }; + + $scope.showService = function() { + return $scope.params.reporttype == "services"; + }; + + $scope.showTimeperiod = function() { + switch ($scope.params.reporttype) { + case "": + return false; + break; + case "hosts": + return $scope.params.host != ""; + break; + case "services": + return $scope.params.host != "" && + $scope.params.service != ""; + break; + } + }; + + $scope.showDates = function() { + return $scope.params.timeperiod == "custom"; + }; + + var isTimeperiodValid = function() { + switch ($scope.params.timeperiod) { + case "": + return false; + break; + case "custom": + if ($scope.params.t1 == 0 || + $scope.params.t1 == "Invalid Date" || + $scope.params.t2 == 0 || + $scope.params.t2 == "Invalid Date") { + return false; + } + else { + return true; + } + break; + default: + return true; + break; + } + }; + + $scope.disableApply = function() { + switch ($scope.params.reporttype) { + case "": + return true; + break; + case "hosts": + if ($scope.params.host == "") { + return true; + } + return !isTimeperiodValid(); + break; + case "services": + if ($scope.params.host == "" || + $scope.params.service == "") { + return true; + } + return !isTimeperiodValid(); + break; + } + } + + var getHostList = function() { + var url = $scope.params.cgiurl + + "/objectjson.cgi?query=hostlist"; + $http.get(url, { withCredentials: true}) + .success(function(results) { + $scope.hostlist = results.data.hostlist; + }) + .error(function(err) { + console.log(err); + }); + }; + + var getServiceList = function(hostname) { + if (hostname != "") { + var url = $scope.params.cgiurl + + "/objectjson.cgi?query=servicelist&hostname=" + + hostname; + $http.get(url, { withCredentials: true}) + .success(function(results) { + $scope.servicelist = + results.data.servicelist[hostname]; + }) + .error(function(err) { + console.log(err); + }); + } + }; + + $scope.onBlurCgiurl = function(evt) { + getHostList(); + }; + + $scope.$watch('params.reporttype', function(newValue) { + switch (newValue) { + case "hosts": + getHostList(); + $scope.eventslist = histogramEventsService.hostEvents; + break; + case "services": + getHostList(); + $scope.eventslist = histogramEventsService.serviceEvents; + break; + case "": + $scope.eventslist = []; + } + }); + + $scope.$watch('params.host', function(newValue) { + if (newValue != "") { + getServiceList($scope.params.host); + } + }); + + $scope.$watch("params.timeperiod", function(newValue) { + if (newValue != null || newValue != "custom") { + var times = nagiosTimeService.calculateReportTimes(new Date, newValue); + $scope.params.t1 = times.start / 1000; + $scope.params.t2 = times.start / 1000; + } + }); + + $scope.$watch('params.startDate', function(newValue) { + if (newValue != undefined) { + time = new Date(newValue); + if (time != "Invalid Date") { + $scope.params.t1 = time.getTime() / 1000; + } + } + }); + + $scope.$watch('params.endDate', function(newValue) { + if (newValue != undefined) { + time = new Date(newValue); + if (time != "Invalid Date") { + $scope.params.t2 = time.getTime() / 1000; + } + } + }); + + }); + diff --git a/html/js/histogram-graph.js b/html/js/histogram-graph.js new file mode 100644 index 0000000..3aac406 --- /dev/null +++ b/html/js/histogram-graph.js @@ -0,0 +1,446 @@ +angular.module("histogramApp") + .directive("nagiosHistogram", function() { + return { + templateUrl: "histogram-graph.html", + restrict: "AE", + scope: { + cgiurl: "@cgiurl", + reporttype: "@reporttype", + host: "@host", + service: "@service", + timeperiod: "@timeperiod", + t1: "@t1", + t2: "@t2", + breakdown: "@breakdown", + graphevents: "@graphevents", + graphstatetypes: "@graphstatetypes", + assumestateretention: "@assumestateretention", + initialstateslogged: "@initialstateslogged", + ignorerepeatedstates: "@ignorerepeatedstates", + lastUpdate: "=lastUpdate", + reload: "@reload", + build: "&build" + }, + controller: function($scope, $element, $attrs, $http, + histogramEventsService, statisticsBreakdown) { + + // Layout variables + $scope.fontSize = 11; + $scope.graphMargin = { + top: 40, + right: 290, + bottom: 84, + left: 60 + }; + $scope.svgHeight = 320; + $scope.svgWidth = 900; + $scope.dateFormat = d3.time.format("%a %b %d %H:%M:%S %Y"); + + // Application state variables + $scope.fetchingAlerts = false; + + $scope.$watch("reload", function(newValue) { + // Remove any previous graphs + d3.select("g#grid").selectAll("path").remove(); + // Set the start and end times + $scope.startTime = $scope.t1 * 1000; + $scope.endTime = $scope.t2 * 1000; + // Show the histogram + showHistogram(); + }); + + // Get the statistics breakdown label + $scope.statisticsBreakdownLabel = function(value) { + for (var i = 0; i < statisticsBreakdown.length; i++) { + var bd = statisticsBreakdown[i]; + if (bd.value == value) { + return bd.label; + } + } + }; + + // Get the x-axis scale domain + var getXScaleDomain = function() { + + // Set up the x-axis scale domain + var domain = []; + + switch($scope.breakdown) { + case "monthly": + domain = d3.range(0,13); + break; + case "dayofweek": + domain = d3.range(0,8); + break; + case "hourly": + domain = d3.range(0,25); + break; + case "dayofmonth": + default: + domain = d3.range(0,32); + break; + } + + return domain; + }; + + // Get the x-axis tick values + var getXAxisTickValue = function(d) { + + // Set up the x-axis tick values + var values = []; + + switch($scope.breakdown) { + case "monthly": + var months = ["January", "February", "March", + "April", "May", "June", "July", "August", + "September", "October", "November", + "December", "January"]; + return months[d % 12]; + break; + case "dayofweek": + var days = ["Sunday", "Monday", "Tuesday", + "Wednesday", "Thursday", "Friday", + "Saturday", "Sunday"]; + return days[d % 7]; + break; + case "hourly": + var hourFormat = d3.format("02d"); + return hourFormat(d % 24) + ":00"; + break; + case "dayofmonth": + default: + var value = ((d + 1) % 32); + return (value == 0 ? 1 : value); + break; + } + }; + + // Get the number of periods for the breakdown + $scope.getBreakdownPeriods = function() { + switch($scope.breakdown) { + case "monthly": + return 12; + break; + case "dayofweek": + return 7; + break; + case "hourly": + return 24; + break; + case "dayofmonth": + default: + return 31; + break; + } + }; + + // Determine the y-axis maximum + getYMax = function() { + + var states = ["up", "down", "unreachable", "ok", + "warning", "unknown", "critical" ]; + var yMax = 0; + + states.forEach(function(e, i, a) { + yMax = Math.max($scope.summary[$scope.breakdown].maxima[e], yMax); + }); + + return yMax; + }; + + // Display the graph + var displayGraph = function() { + + // Local variables + var graphHeight = $scope.svgHeight - + ($scope.graphMargin.bottom + + $scope.graphMargin.top); + var graphWidth = $scope.svgWidth - + ($scope.graphMargin.right + + $scope.graphMargin.left); + var gridCenter = $scope.graphMargin.left + + graphWidth / 2; + + // Get the header group + var gridGroup = d3.select("svg#histogram") + .select("g#grid") + .attr({ + transform: function() { + return "translate(" + + $scope.graphMargin.left + "," + + $scope.graphMargin.top + ")"; + } + }); + + // Build the x-axis scale + var xScale = d3.scale.ordinal() + .domain(getXScaleDomain()) + .rangePoints([0, graphWidth]); + + // Build the x-axis + var xAxis = d3.svg.axis() + .scale(xScale) + .orient("bottom") + .tickSize(graphHeight) + .tickFormat(function(d) { + return getXAxisTickValue(d); + }); + + // Display the x-axis + d3.select("g#xaxis").call(xAxis); + + // Rotate the value labels for the x-axis + var translate = -(graphHeight + ($scope.fontSize / 2)); + d3.select("g#xaxis") + .selectAll("text") + .attr({ + transform: function() { + return "rotate(-90) translate(" + + translate + "," + translate + ")"; + } + }) + .style({ + "text-anchor": "end" + }); + + // Build the y-axis scale + var yScale = d3.scale.linear() + .domain([getYMax(), 0]) + .rangeRound([0, graphHeight]); + + // Build the y-axis + var yAxis = d3.svg.axis() + .scale(yScale) + .orient("left") + .tickSize(graphWidth); + + // Display the y-axis + d3.select("g#yaxis").call(yAxis); + + // Generate the lines + var states = []; + if($scope.reporttype == "hosts") { + states = ["up", "down", "unreachable"]; + } + else { + states = ["ok", "warning", "unknown", "critical"]; + } + states.forEach(function(e, i, a) { + var line = d3.svg.line() + .x(function(d, i) { return xScale(i); }) + .y(function(d) { return yScale(d[e]); }) + .interpolate("linear"); + + gridGroup.append("path") + .attr({ + "d": line($scope.summary[$scope.breakdown].details), + "class": e + }); + }); + }; + + // Initialize the data for display + var initializeData = function(obj, size) { + + var states = ["up", "down", "unreachable", "ok", + "warning", "unknown", "critical" ]; + + obj.maxima = new Object; + obj.minima = new Object; + obj.totals = new Object; + states.forEach(function(e, i, a) { + obj.maxima[e] = 0; + obj.minima[e] = -1; + obj.totals[e] = 0; + }); + + obj.details = new Array; + for(var i = 0; i < size; i++) { + obj.details.push({ + "up": 0, + "down": 0, + "unreachable": 0, + "ok": 0, + "warning": 0, + "unknown": 0, + "critical": 0 + }); + } + }; + + // Update the summary data + var updateData = function(obj, state, index) { + + obj.details[index][state]++; + obj.maxima[state] = Math.max(obj.maxima[state], + obj.details[index][state]); + obj.totals[state]++; + if(index == 0) { + // If this is the first entry in the breakdown, + // also update the last because the graph + // "wraps around" + obj.details[obj.details.length - 1][state]++; + } + }; + + // Calculate the minima + var calculateMinima = function(obj) { + for(var key in obj.minima) { + obj.minima[key] = obj.details[0][key]; + for(var j = 1; j < obj.details.length; j++) { + obj.minima[key] = Math.min(obj.minima[key], + obj.details[j][key]); + } + } + }; + + // Summarize the data for display + var summarizeData = function() { + + // Initialize the data + $scope.summary = { + monthly: new Object, + dayofmonth: new Object, + dayofweek: new Object, + hourly: new Object, + }; + initializeData($scope.summary.monthly, 13); + initializeData($scope.summary.dayofmonth, 32); + initializeData($scope.summary.dayofweek, 8); + initializeData($scope.summary.hourly, 25); + + $scope.json.data.alertlist.forEach(function(e, i, a) { + // Create a Javascript date object + var ts = new Date(e.timestamp); + + // Update the monthly data + updateData($scope.summary.monthly, e.state, + ts.getMonth()); + + // Update the day of month data + updateData($scope.summary.dayofmonth, e.state, + ts.getDate() - 1); + + // Update the day of week data + updateData($scope.summary.dayofweek, e.state, + ts.getDay()); + + // Update the hourly data + updateData($scope.summary.hourly, e.state, + ts.getHours()); + + }); + + // Calculate the minima + calculateMinima($scope.summary.monthly); + calculateMinima($scope.summary.dayofmonth); + calculateMinima($scope.summary.dayofweek); + calculateMinima($scope.summary.hourly); + }; + + // Show the graph + var showHistogram = function() { + + if(!$scope.build()) { + return; + } + + // Build the list of parameters for the JSON query + var parameters = { + query: "alertlist", + formatoptions: "enumerate bitmask", + objecttypes: ($scope.reporttype == "hosts" ? + "host" : "service"), + hostname: $scope.host, + starttime: $scope.t1, + endtime: $scope.t2, + statetypes: function() { + switch($scope.graphstatetypes) { + case 1: + return "soft"; + break; + case 2: + return "hard"; + break; + case 3: + default: + return "hard soft"; + break; + } + }(), + backtrackedarchives: $scope.backtracks + }; + + switch($scope.reporttype) { + case "hosts": + var events = histogramEventsService.hostEvents.filter(function(e) { + return e.value == $scope.graphevents; + }); + if(events.length > 0) { + parameters.hoststates = events[0].states; + } + else { + parameters.hoststates = "up down unreachable"; + } + break; + case "services": + var events = histogramEventsService.serviceEvents.filter(function(e) { + return e.value == $scope.graphevents; + }); + parameters.servicedescription = $scope.service; + if(events.length > 0) { + parameters.servicestates = events[0].states; + } + else { + parameters.servicestates = + "ok warning unknown critical"; + } + break; + } + + var getConfig = { + params: parameters, + withCredentials: true + }; + + // Where to place the spinner + var spinnerdiv = d3.select("div#spinner"); + var spinner = null; + + // Send the JSON query + $http.get($scope.cgiurl + "archivejson.cgi", getConfig) + .error(function(err) { + console.warn(err); + // Stop the spinner + $scope.fetchingAlerts = false; + spinner.stop(); + }) + .success(function(json) { + // Stop the spinner + $scope.fetchingAlerts = false; + spinner.stop(); + + // Save the json results + $scope.json = json; + + // Record the query time + $scope.lastUpdate = new Date(json.result.query_time); + + // Summarize the results + summarizeData(); + + // Display the graph + displayGraph(); + + // Display the summary + }); + + // Start the spinner + $scope.fetchingAlerts = true; + spinner = new Spinner($scope.spinnerOpts).spin(spinnerdiv[0][0]); + }; + + } + }; + }); diff --git a/html/js/histogram.js b/html/js/histogram.js new file mode 100644 index 0000000..e110f2d --- /dev/null +++ b/html/js/histogram.js @@ -0,0 +1,131 @@ +angular.module("histogramApp", ["ui.bootstrap", "ui.utils", + "histogramEvents", "nagiosDecorations", "nagiosTime"]) + + // Statistics breakdown list + .constant("statisticsBreakdown", [ + { value: "monthly", label: "Month" }, + { value: "dayofmonth", label: "Day of the Month" }, + { value: "dayofweek", label: "Day of the Week" }, + { value: "hourly", label: "Hour of the Day" } + ]) + + .config(function($locationProvider) { + $locationProvider.html5Mode({ + enabled: true, + requireBase: false + }) + }) + + .controller("histogramCtrl", function($scope, $location, $modal) { + + // Parameters found in the URL + $scope.search = $location.search(); + + // URL parameters + $scope.params = { + cgiurl: $scope.search.cgiurl ? $scope.search.cgiurl : + $location.absUrl().replace(/histogram\.html.*$/, "cgi-bin/"), + reporttype: $scope.search.reporttype ? + $scope.search.reporttype : "", + host: $scope.search.host ? $scope.search.host : "", + service: $scope.search.service ? + $scope.search.service : "", + timeperiod: $scope.search.timeperiod ? + $scope.search.timeperiod : "", + t1: $scope.search.t1 ? $scope.search.t1 : 0, + t2: $scope.search.t2 ? $scope.search.t2 : 0, + breakdown: $scope.search.breakdown ? $scope.search.breakdown : + "dayofmonth", + graphevents: $scope.search.graphevents ? + parseInt($scope.search.graphevents) : 0, + graphstatetypes: $scope.search.graphstatetypes ? + parseInt($scope.search.graphstatetypes) : 3, + assumestateretention: $scope.search.assumestateretention ? + $scope.search.assumestateretention : false, + initialstateslogged: $scope.search.initialstateslogged ? + $scope.search.initialstateslogged : false, + ignorerepeatedstates: $scope.search.ignorerepeatedstates ? + $scope.search.ignorerepeatedstates : false + }; + + // Reload index - increment to cause nagios-histogram to reload + $scope.reload = 0; + + // Application state variables + $scope.formDisplayed = false; + + // Decoration-related variables + $scope.lastUpdate = "none"; + + var notBlank = function(value) { + return value != undefined && value != ""; + }; + + // Do we have everything necessary to build a histogram? + $scope.canBuildHistogram = function() { + if ($scope.params.reporttype == "services" || + (notBlank($scope.params.host) && + notBlank($scope.params.service))) { + if ((($scope.params.timeperiod != "") || + (($scope.params.t1 != 0) && + ($scope.params.t2 != 0)))) { + $scope.params.reporttype = "services"; + return true; + } + return false; + } + else if ($scope.params.reporttype == "hosts" || + notBlank($scope.params.host)) { + if ((($scope.params.timeperiod != "") || + (($scope.params.t1 != 0) && + ($scope.params.t2 != 0)))) { + $scope.params.reporttype = "hosts"; + return true; + } + return false; + } + return false; + }; + + $scope.displayForm = function(size) { + $scope.formDisplayed = true; + var modalInstance = $modal.open({ + templateUrl: 'histogram-form.html', + controller: 'histogramFormCtrl', + size: size, + resolve: { + params: function () { + return $scope.params; + } + } + }); + + modalInstance.result.then(function(params) { + $scope.formDisplayed = false; + $scope.params = params; + $scope.reload++; + }, + function(reason) { + $scope.formDisplayed = false; + }); + }; + + if(!$scope.canBuildHistogram()) { + $scope.displayForm(); + } + + $scope.infoBoxTitle = function() { + switch ($scope.params.reporttype) { + case "hosts": + return "Host Alert Histogram"; + break; + case "services": + return "Service Alert Histogram"; + break; + default: + return "Alert Histogram"; + break; + } + }; + + }); diff --git a/html/js/jquery-1.7.1.min.js b/html/js/jquery-1.7.1.min.js new file mode 100644 index 0000000..198b3ff --- /dev/null +++ b/html/js/jquery-1.7.1.min.js @@ -0,0 +1,4 @@ +/*! jQuery v1.7.1 jquery.com | jquery.org/license */ +(function(a,b){function cy(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cv(a){if(!ck[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){cl||(cl=c.createElement("iframe"),cl.frameBorder=cl.width=cl.height=0),b.appendChild(cl);if(!cm||!cl.createElement)cm=(cl.contentWindow||cl.contentDocument).document,cm.write((c.compatMode==="CSS1Compat"?"":"")+""),cm.close();d=cm.createElement(a),cm.body.appendChild(d),e=f.css(d,"display"),b.removeChild(cl)}ck[a]=e}return ck[a]}function cu(a,b){var c={};f.each(cq.concat.apply([],cq.slice(0,b)),function(){c[this]=a});return c}function ct(){cr=b}function cs(){setTimeout(ct,0);return cr=f.now()}function cj(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ci(){try{return new a.XMLHttpRequest}catch(b){}}function cc(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g0){if(c!=="border")for(;g=0===c})}function S(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function K(){return!0}function J(){return!1}function n(a,b,c){var d=b+"defer",e=b+"queue",g=b+"mark",h=f._data(a,d);h&&(c==="queue"||!f._data(a,e))&&(c==="mark"||!f._data(a,g))&&setTimeout(function(){!f._data(a,e)&&!f._data(a,g)&&(f.removeData(a,d,!0),h.fire())},0)}function m(a){for(var b in a){if(b==="data"&&f.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function l(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(k,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNumeric(d)?parseFloat(d):j.test(d)?f.parseJSON(d):d}catch(g){}f.data(a,c,d)}else d=b}return d}function h(a){var b=g[a]={},c,d;a=a.split(/\s+/);for(c=0,d=a.length;c)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,n=/^[\],:{}\s]*$/,o=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,q=/(?:^|:|,)(?:\s*\[)+/g,r=/(webkit)[ \/]([\w.]+)/,s=/(opera)(?:.*version)?[ \/]([\w.]+)/,t=/(msie) ([\w.]+)/,u=/(mozilla)(?:.*? rv:([\w.]+))?/,v=/-([a-z]|[0-9])/ig,w=/^-ms-/,x=function(a,b){return(b+"").toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=m.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.7.1",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.add(a);return this},eq:function(a){a=+a;return a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j0)return;A.fireWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").off("ready")}},bindReady:function(){if(!A){A=e.Callbacks("once memory");if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a&&typeof a=="object"&&"setInterval"in a},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||D.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw new Error(a)},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(n.test(b.replace(o,"@").replace(p,"]").replace(q,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(c){var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&e.error("Invalid XML: "+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,"ms-").replace(v,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i1?i.call(arguments,0):b,j.notifyWith(k,e)}}function l(a){return function(c){b[a]=arguments.length>1?i.call(arguments,0):c,--g||j.resolveWith(j,b)}}var b=i.call(arguments,0),c=0,d=b.length,e=Array(d),g=d,h=d,j=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred(),k=j.promise();if(d>1){for(;c
    a",d=q.getElementsByTagName("*"),e=q.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=q.getElementsByTagName("input")[0],b={leadingWhitespace:q.firstChild.nodeType===3,tbody:!q.getElementsByTagName("tbody").length,htmlSerialize:!!q.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:q.className!=="t",enctype:!!c.createElement("form").enctype,html5Clone:c.createElement("nav").cloneNode(!0).outerHTML!=="<:nav>",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0},i.checked=!0,b.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,b.optDisabled=!h.disabled;try{delete q.test}catch(s){b.deleteExpando=!1}!q.addEventListener&&q.attachEvent&&q.fireEvent&&(q.attachEvent("onclick",function(){b.noCloneEvent=!1}),q.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),b.radioValue=i.value==="t",i.setAttribute("checked","checked"),q.appendChild(i),k=c.createDocumentFragment(),k.appendChild(q.lastChild),b.checkClone=k.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=i.checked,k.removeChild(i),k.appendChild(q),q.innerHTML="",a.getComputedStyle&&(j=c.createElement("div"),j.style.width="0",j.style.marginRight="0",q.style.width="2px",q.appendChild(j),b.reliableMarginRight=(parseInt((a.getComputedStyle(j,null)||{marginRight:0}).marginRight,10)||0)===0);if(q.attachEvent)for(o in{submit:1,change:1,focusin:1})n="on"+o,p=n in q,p||(q.setAttribute(n,"return;"),p=typeof q[n]=="function"),b[o+"Bubbles"]=p;k.removeChild(q),k=g=h=j=q=i=null,f(function(){var a,d,e,g,h,i,j,k,m,n,o,r=c.getElementsByTagName("body")[0];!r||(j=1,k="position:absolute;top:0;left:0;width:1px;height:1px;margin:0;",m="visibility:hidden;border:0;",n="style='"+k+"border:5px solid #000;padding:0;'",o="
    "+""+"
    ",a=c.createElement("div"),a.style.cssText=m+"width:0;height:0;position:static;top:0;margin-top:"+j+"px",r.insertBefore(a,r.firstChild),q=c.createElement("div"),a.appendChild(q),q.innerHTML="
    t
    ",l=q.getElementsByTagName("td"),p=l[0].offsetHeight===0,l[0].style.display="",l[1].style.display="none",b.reliableHiddenOffsets=p&&l[0].offsetHeight===0,q.innerHTML="",q.style.width=q.style.paddingLeft="1px",f.boxModel=b.boxModel=q.offsetWidth===2,typeof q.style.zoom!="undefined"&&(q.style.display="inline",q.style.zoom=1,b.inlineBlockNeedsLayout=q.offsetWidth===2,q.style.display="",q.innerHTML="
    ",b.shrinkWrapBlocks=q.offsetWidth!==2),q.style.cssText=k+m,q.innerHTML=o,d=q.firstChild,e=d.firstChild,h=d.nextSibling.firstChild.firstChild,i={doesNotAddBorder:e.offsetTop!==5,doesAddBorderForTableAndCells:h.offsetTop===5},e.style.position="fixed",e.style.top="20px",i.fixedPosition=e.offsetTop===20||e.offsetTop===15,e.style.position=e.style.top="",d.style.overflow="hidden",d.style.position="relative",i.subtractsBorderForOverflowNotVisible=e.offsetTop===-5,i.doesNotIncludeMarginInBodyOffset=r.offsetTop!==j,r.removeChild(a),q=a=null,f.extend(b,i))});return b}();var j=/^(?:\{.*\}|\[.*\])$/,k=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!m(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i,j=f.expando,k=typeof c=="string",l=a.nodeType,m=l?f.cache:a,n=l?a[j]:a[j]&&j,o=c==="events";if((!n||!m[n]||!o&&!e&&!m[n].data)&&k&&d===b)return;n||(l?a[j]=n=++f.uuid:n=j),m[n]||(m[n]={},l||(m[n].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?m[n]=f.extend(m[n],c):m[n].data=f.extend(m[n].data,c);g=h=m[n],e||(h.data||(h.data={}),h=h.data),d!==b&&(h[f.camelCase(c)]=d);if(o&&!h[c])return g.events;k?(i=h[c],i==null&&(i=h[f.camelCase(c)])):i=h;return i}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e,g,h=f.expando,i=a.nodeType,j=i?f.cache:a,k=i?a[h]:h;if(!j[k])return;if(b){d=c?j[k]:j[k].data;if(d){f.isArray(b)||(b in d?b=[b]:(b=f.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,g=b.length;e-1)return!0;return!1},val:function(a){var c,d,e,g=this[0];{if(!!arguments.length){e=f.isFunction(a);return this.each(function(d){var g=f(this),h;if(this.nodeType===1){e?h=a.call(this,d,g.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.nodeName.toLowerCase()]||f.valHooks[this.type];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}if(g){c=f.valHooks[g.nodeName.toLowerCase()]||f.valHooks[g.type];if(c&&"get"in c&&(d=c.get(g,"value"))!==b)return d;d=g.value;return typeof d=="string"?d.replace(q,""):d==null?"":d}}}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,g=a.selectedIndex,h=[],i=a.options,j=a.type==="select-one";if(g<0)return null;c=j?g:0,d=j?g+1:i.length;for(;c=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,d,e){var g,h,i,j=a.nodeType;if(!!a&&j!==3&&j!==8&&j!==2){if(e&&c in f.attrFn)return f(a)[c](d);if(typeof a.getAttribute=="undefined")return f.prop(a,c,d);i=j!==1||!f.isXMLDoc(a),i&&(c=c.toLowerCase(),h=f.attrHooks[c]||(u.test(c)?x:w));if(d!==b){if(d===null){f.removeAttr(a,c);return}if(h&&"set"in h&&i&&(g=h.set(a,d,c))!==b)return g;a.setAttribute(c,""+d);return d}if(h&&"get"in h&&i&&(g=h.get(a,c))!==null)return g;g=a.getAttribute(c);return g===null?b:g}},removeAttr:function(a,b){var c,d,e,g,h=0;if(b&&a.nodeType===1){d=b.toLowerCase().split(p),g=d.length;for(;h=0}})});var z=/^(?:textarea|input|select)$/i,A=/^([^\.]*)?(?:\.(.+))?$/,B=/\bhover(\.\S+)?\b/,C=/^key/,D=/^(?:mouse|contextmenu)|click/,E=/^(?:focusinfocus|focusoutblur)$/,F=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,G=function(a){var b=F.exec(a);b&&(b[1]=(b[1]||"").toLowerCase(),b[3]=b[3]&&new RegExp("(?:^|\\s)"+b[3]+"(?:\\s|$)"));return b},H=function(a,b){var c=a.attributes||{};return(!b[1]||a.nodeName.toLowerCase()===b[1])&&(!b[2]||(c.id||{}).value===b[2])&&(!b[3]||b[3].test((c["class"]||{}).value))},I=function(a){return f.event.special.hover?a:a.replace(B,"mouseenter$1 mouseleave$1")}; +f.event={add:function(a,c,d,e,g){var h,i,j,k,l,m,n,o,p,q,r,s;if(!(a.nodeType===3||a.nodeType===8||!c||!d||!(h=f._data(a)))){d.handler&&(p=d,d=p.handler),d.guid||(d.guid=f.guid++),j=h.events,j||(h.events=j={}),i=h.handle,i||(h.handle=i=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.dispatch.apply(i.elem,arguments):b},i.elem=a),c=f.trim(I(c)).split(" ");for(k=0;k=0&&(h=h.slice(0,-1),k=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if((!e||f.event.customEvent[h])&&!f.event.global[h])return;c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.isTrigger=!0,c.exclusive=k,c.namespace=i.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)"):null,o=h.indexOf(":")<0?"on"+h:"";if(!e){j=f.cache;for(l in j)j[l].events&&j[l].events[h]&&f.event.trigger(c,d,j[l].handle.elem,!0);return}c.result=b,c.target||(c.target=e),d=d!=null?f.makeArray(d):[],d.unshift(c),p=f.event.special[h]||{};if(p.trigger&&p.trigger.apply(e,d)===!1)return;r=[[e,p.bindType||h]];if(!g&&!p.noBubble&&!f.isWindow(e)){s=p.delegateType||h,m=E.test(s+h)?e:e.parentNode,n=null;for(;m;m=m.parentNode)r.push([m,s]),n=m;n&&n===e.ownerDocument&&r.push([n.defaultView||n.parentWindow||a,s])}for(l=0;le&&i.push({elem:this,matches:d.slice(e)});for(j=0;j0?this.on(b,null,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0),C.test(b)&&(f.event.fixHooks[b]=f.event.keyHooks),D.test(b)&&(f.event.fixHooks[b]=f.event.mouseHooks)}),function(){function x(a,b,c,e,f,g){for(var h=0,i=e.length;h0){k=j;break}}j=j[a]}e[h]=k}}}function w(a,b,c,e,f,g){for(var h=0,i=e.length;h+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d="sizcache"+(Math.random()+"").replace(".",""),e=0,g=Object.prototype.toString,h=!1,i=!0,j=/\\/g,k=/\r\n/g,l=/\W/;[0,0].sort(function(){i=!1;return 0});var m=function(b,d,e,f){e=e||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return e;var i,j,k,l,n,q,r,t,u=!0,v=m.isXML(d),w=[],x=b;do{a.exec(""),i=a.exec(x);if(i){x=i[3],w.push(i[1]);if(i[2]){l=i[3];break}}}while(i);if(w.length>1&&p.exec(b))if(w.length===2&&o.relative[w[0]])j=y(w[0]+w[1],d,f);else{j=o.relative[w[0]]?[d]:m(w.shift(),d);while(w.length)b=w.shift(),o.relative[b]&&(b+=w.shift()),j=y(b,j,f)}else{!f&&w.length>1&&d.nodeType===9&&!v&&o.match.ID.test(w[0])&&!o.match.ID.test(w[w.length-1])&&(n=m.find(w.shift(),d,v),d=n.expr?m.filter(n.expr,n.set)[0]:n.set[0]);if(d){n=f?{expr:w.pop(),set:s(f)}:m.find(w.pop(),w.length===1&&(w[0]==="~"||w[0]==="+")&&d.parentNode?d.parentNode:d,v),j=n.expr?m.filter(n.expr,n.set):n.set,w.length>0?k=s(j):u=!1;while(w.length)q=w.pop(),r=q,o.relative[q]?r=w.pop():q="",r==null&&(r=d),o.relative[q](k,r,v)}else k=w=[]}k||(k=j),k||m.error(q||b);if(g.call(k)==="[object Array]")if(!u)e.push.apply(e,k);else if(d&&d.nodeType===1)for(t=0;k[t]!=null;t++)k[t]&&(k[t]===!0||k[t].nodeType===1&&m.contains(d,k[t]))&&e.push(j[t]);else for(t=0;k[t]!=null;t++)k[t]&&k[t].nodeType===1&&e.push(j[t]);else s(k,e);l&&(m(l,h,e,f),m.uniqueSort(e));return e};m.uniqueSort=function(a){if(u){h=i,a.sort(u);if(h)for(var b=1;b0},m.find=function(a,b,c){var d,e,f,g,h,i;if(!a)return[];for(e=0,f=o.order.length;e":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!l.test(b)){b=b.toLowerCase();for(;e=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(j,"")},TAG:function(a,b){return a[1].replace(j,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||m.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&m.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(j,"");!f&&o.attrMap[g]&&(a[1]=o.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(j,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=m(b[3],null,null,c);else{var g=m.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(o.match.POS.test(b[0])||o.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!m(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return bc[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=o.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||n([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||!!a.nodeName&&a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=m.attr?m.attr(a,c):o.attrHandle[c]?o.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":!f&&m.attr?d!=null:f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=o.setFilters[e];if(f)return f(a,c,b,d)}}},p=o.match.POS,q=function(a,b){return"\\"+(b-0+1)};for(var r in o.match)o.match[r]=new RegExp(o.match[r].source+/(?![^\[]*\])(?![^\(]*\))/.source),o.leftMatch[r]=new RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[r].source.replace(/\\(\d+)/g,q));var s=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(t){s=function(a,b){var c=0,d=b||[];if(g.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var e=a.length;c",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(o.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},o.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(o.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(o.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=m,b=c.createElement("div"),d="__sizzle__";b.innerHTML="

    ";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){m=function(b,e,f,g){e=e||c;if(!g&&!m.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return s(e.getElementsByTagName(b),f);if(h[2]&&o.find.CLASS&&e.getElementsByClassName)return s(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return s([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return s([],f);if(i.id===h[3])return s([i],f)}try{return s(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var k=e,l=e.getAttribute("id"),n=l||d,p=e.parentNode,q=/^\s*[+~]/.test(b);l?n=n.replace(/'/g,"\\$&"):e.setAttribute("id",n),q&&p&&(e=e.parentNode);try{if(!q||p)return s(e.querySelectorAll("[id='"+n+"'] "+b),f)}catch(r){}finally{l||k.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)m[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}m.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!m.isXML(a))try{if(e||!o.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return m(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="
    ";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;o.order.splice(1,0,"CLASS"),o.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?m.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?m.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:m.contains=function(){return!1},m.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var y=function(a,b,c){var d,e=[],f="",g=b.nodeType?[b]:b;while(d=o.match.PSEUDO.exec(a))f+=d[0],a=a.replace(o.match.PSEUDO,"");a=o.relative[a]?a+"*":a;for(var h=0,i=g.length;h0)for(h=g;h=0:f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h=1;while(g&&g.ownerDocument&&g!==b){for(d=0;d-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a)return this[0]&&this[0].parentNode?this.prevAll().length:-1;if(typeof a=="string")return f.inArray(this[0],f(a));return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(S(c[0])||S(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling(a.parentNode.firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c);L.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!R[a]?f.unique(e):e,(this.length>1||N.test(d))&&M.test(a)&&(e=e.reverse());return this.pushStack(e,a,P.call(arguments).join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var V="abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",W=/ jQuery\d+="(?:\d+|null)"/g,X=/^\s+/,Y=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Z=/<([\w:]+)/,$=/
    ","
    "],tr:[2,"","
    "],td:[3,"","
    "],col:[2,"","
    "],area:[1,"",""],_default:[0,"",""]},bh=U(c);bg.optgroup=bg.option,bg.tbody=bg.tfoot=bg.colgroup=bg.caption=bg.thead,bg.th=bg.td,f.support.htmlSerialize||(bg._default=[1,"div
    ","
    "]),f.fn.extend({text:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.text(a.call(this,b,c.text()))});if(typeof a!="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return f.text(this)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=f.isFunction(a);return this.each(function(c){f(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f.clean(arguments);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f.clean(arguments));return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function() +{for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(W,""):null;if(typeof a=="string"&&!ba.test(a)&&(f.support.leadingWhitespace||!X.test(a))&&!bg[(Z.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Y,"<$1>");try{for(var c=0,d=this.length;c1&&l0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d,e,g,h=f.support.html5Clone||!bc.test("<"+a.nodeName)?a.cloneNode(!0):bo(a);if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bk(a,h),d=bl(a),e=bl(h);for(g=0;d[g];++g)e[g]&&bk(d[g],e[g])}if(b){bj(a,h);if(c){d=bl(a),e=bl(h);for(g=0;d[g];++g)bj(d[g],e[g])}}d=e=null;return h},clean:function(a,b,d,e){var g;b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var h=[],i;for(var j=0,k;(k=a[j])!=null;j++){typeof k=="number"&&(k+="");if(!k)continue;if(typeof k=="string")if(!_.test(k))k=b.createTextNode(k);else{k=k.replace(Y,"<$1>");var l=(Z.exec(k)||["",""])[1].toLowerCase(),m=bg[l]||bg._default,n=m[0],o=b.createElement("div");b===c?bh.appendChild(o):U(b).appendChild(o),o.innerHTML=m[1]+k+m[2];while(n--)o=o.lastChild;if(!f.support.tbody){var p=$.test(k),q=l==="table"&&!p?o.firstChild&&o.firstChild.childNodes:m[1]===""&&!p?o.childNodes:[];for(i=q.length-1;i>=0;--i)f.nodeName(q[i],"tbody")&&!q[i].childNodes.length&&q[i].parentNode.removeChild(q[i])}!f.support.leadingWhitespace&&X.test(k)&&o.insertBefore(b.createTextNode(X.exec(k)[0]),o.firstChild),k=o.childNodes}var r;if(!f.support.appendChecked)if(k[0]&&typeof (r=k.length)=="number")for(i=0;i=0)return b+"px"}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return br.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=f.isNumeric(b)?"alpha(opacity="+b*100+")":"",g=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&f.trim(g.replace(bq,""))===""){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bq.test(g)?g.replace(bq,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){var c;f.swap(a,{display:"inline-block"},function(){b?c=bz(a,"margin-right","marginRight"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(bA=function(a,b){var c,d,e;b=b.replace(bs,"-$1").toLowerCase(),(d=a.ownerDocument.defaultView)&&(e=d.getComputedStyle(a,null))&&(c=e.getPropertyValue(b),c===""&&!f.contains(a.ownerDocument.documentElement,a)&&(c=f.style(a,b)));return c}),c.documentElement.currentStyle&&(bB=function(a,b){var c,d,e,f=a.currentStyle&&a.currentStyle[b],g=a.style;f===null&&g&&(e=g[b])&&(f=e),!bt.test(f)&&bu.test(f)&&(c=g.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),g.left=b==="fontSize"?"1em":f||0,f=g.pixelLeft+"px",g.left=c,d&&(a.runtimeStyle.left=d));return f===""?"auto":f}),bz=bA||bB,f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style&&a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)});var bD=/%20/g,bE=/\[\]$/,bF=/\r?\n/g,bG=/#.*$/,bH=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bI=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bJ=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,bK=/^(?:GET|HEAD)$/,bL=/^\/\//,bM=/\?/,bN=/)<[^<]*)*<\/script>/gi,bO=/^(?:select|textarea)/i,bP=/\s+/,bQ=/([?&])_=[^&]*/,bR=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bS=f.fn.load,bT={},bU={},bV,bW,bX=["*/"]+["*"];try{bV=e.href}catch(bY){bV=c.createElement("a"),bV.href="",bV=bV.href}bW=bR.exec(bV.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bS)return bS.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("
    ").append(c.replace(bN,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bO.test(this.nodeName)||bI.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bF,"\r\n")}}):{name:b.name,value:c.replace(bF,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.on(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?b_(a,f.ajaxSettings):(b=a,a=f.ajaxSettings),b_(a,b);return a},ajaxSettings:{url:bV,isLocal:bJ.test(bW[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":bX},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:bZ(bT),ajaxTransport:bZ(bU),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a>0?4:0;var o,r,u,w=c,x=l?cb(d,v,l):b,y,z;if(a>=200&&a<300||a===304){if(d.ifModified){if(y=v.getResponseHeader("Last-Modified"))f.lastModified[k]=y;if(z=v.getResponseHeader("Etag"))f.etag[k]=z}if(a===304)w="notmodified",o=!0;else try{r=cc(d,x),w="success",o=!0}catch(A){w="parsererror",u=A}}else{u=w;if(!w||a)w="error",a<0&&(a=0)}v.status=a,v.statusText=""+(c||w),o?h.resolveWith(e,[r,w,v]):h.rejectWith(e,[v,w,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.fireWith(e,[v,w]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f.Callbacks("once memory"),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bH.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.add,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bG,"").replace(bL,bW[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bP),d.crossDomain==null&&(r=bR.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bW[1]&&r[2]==bW[2]&&(r[3]||(r[1]==="http:"?80:443))==(bW[3]||(bW[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),b$(bT,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bK.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bM.test(d.url)?"&":"?")+d.data,delete d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bQ,"$1_="+x);d.url=y+(y===d.url?(bM.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", "+bX+"; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=b$(bU,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){if(s<2)w(-1,z);else throw z}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)ca(g,a[g],c,e);return d.join("&").replace(bD,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var cd=f.now(),ce=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+cd++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=b.contentType==="application/x-www-form-urlencoded"&&typeof b.data=="string";if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(ce.test(b.url)||e&&ce.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(ce,l),b.url===j&&(e&&(k=k.replace(ce,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var cf=a.ActiveXObject?function(){for(var a in ch)ch[a](0,1)}:!1,cg=0,ch;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ci()||cj()}:ci,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,cf&&delete ch[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n),m.text=h.responseText;try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cg,cf&&(ch||(ch={},f(a).unload(cf)),ch[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var ck={},cl,cm,cn=/^(?:toggle|show|hide)$/,co=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,cp,cq=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cr;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(cu("show",3),a,b,c);for(var g=0,h=this.length;g=i.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),i.animatedProperties[this.prop]=!0;for(b in i.animatedProperties)i.animatedProperties[b]!==!0&&(g=!1);if(g){i.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){h.style["overflow"+b]=i.overflow[a]}),i.hide&&f(h).hide();if(i.hide||i.show)for(b in i.animatedProperties)f.style(h,b,i.orig[b]),f.removeData(h,"fxshow"+b,!0),f.removeData(h,"toggle"+b,!0);d=i.complete,d&&(i.complete=!1,d.call(h))}return!1}i.duration==Infinity?this.now=e:(c=e-this.startTime,this.state=c/i.duration,this.pos=f.easing[i.animatedProperties[this.prop]](this.state,c,0,1,i.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){var a,b=f.timers,c=0;for(;c-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cx.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cx.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each(["Left","Top"],function(a,c){var d="scroll"+c;f.fn[d]=function(c){var e,g;if(c===b){e=this[0];if(!e)return null;g=cy(e);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:f.support.boxModel&&g.document.documentElement[d]||g.document.body[d]:e[d]}return this.each(function(){g=cy(this),g?g.scrollTo(a?f(g).scrollLeft():c,a?c:f(g).scrollTop()):this[d]=c})}}),f.each(["Height","Width"],function(a,c){var d=c.toLowerCase();f.fn["inner"+c]=function(){var a=this[0];return a?a.style?parseFloat(f.css(a,d,"padding")):this[d]():null},f.fn["outer"+c]=function(a){var b=this[0];return b?b.style?parseFloat(f.css(b,d,a?"margin":"border")):this[d]():null},f.fn[d]=function(a){var e=this[0];if(!e)return a==null?null:this;if(f.isFunction(a))return this.each(function(b){var c=f(this);c[d](a.call(this,b,c[d]()))});if(f.isWindow(e)){var g=e.document.documentElement["client"+c],h=e.document.body;return e.document.compatMode==="CSS1Compat"&&g||h&&h["client"+c]||g}if(e.nodeType===9)return Math.max(e.documentElement["client"+c],e.body["scroll"+c],e.documentElement["scroll"+c],e.body["offset"+c],e.documentElement["offset"+c]);if(a===b){var i=f.css(e,d),j=parseFloat(i);return f.isNumeric(j)?j:i}return this.css(d,typeof a=="string"?a:a+"px")}}),a.jQuery=a.$=f,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return f})})(window); \ No newline at end of file diff --git a/html/js/jsonquery.js b/html/js/jsonquery.js new file mode 100644 index 0000000..925e84f --- /dev/null +++ b/html/js/jsonquery.js @@ -0,0 +1,566 @@ +$( document).ready( function() { + var parts = $(location).attr( 'href').split( '/'); + parts.pop() + var baseurl = parts.join( '/'); + + $('#query button').attr('disabled','disabled'); + + var disableWhenDependsOnValueBlank = false; + + var help = Object(); + + var true_false = { + "valid_values": [ + "True", + "False", + ] + }; + + function buildSelect( label, name, option) { + var optlist = Array(); + optlist.push( $( '') + .attr({ + value: option.valid_values[ x] + }) + .text( option.valid_values[ x]) + ); + } + } + else if( option.valid_values instanceof Object) { + for( var key in option.valid_values) { + var valid_value = option.valid_values[ key]; + optlist.push( $( '') + .attr({ + value: key, + title: valid_value.description + }) + .text( key) + ); + } + } + var html = $( '
    ') + .addClass( 'generated') + .attr( 'id', name + 'row').append( + $( '') + .addClass( 'label') + .text( label), + $( '').append( + $( '') + .attr({ + id: name, + name: name + }) + .append( + $( optlist).map( function() { + return this.toArray() + }) + ) + ) + ); + + return html; + } + + function buildCheckbox( label, name, option) { + var inputs = Array(); + if( option.valid_values instanceof Array) { + for( var x = 0; x < option.valid_values.length; x++) { + inputs.push( $('') + .attr({ + type: 'checkbox', + name: name, + value: option.valid_values[ x] + }) + ); + inputs.push( $( '').text( option.valid_values[ x])); + inputs.push( $( '
    ')); + } + } + else if( option.valid_values instanceof Object) { + for( var key in option.valid_values) { + var valid_value = option.valid_values[ key]; + inputs.push( $('') + .attr({ + type: 'checkbox', + name: name, + value: key, + title: valid_value.description + }) + ); + inputs.push( $( '').text( key)); + inputs.push( $( '
    ')); + } + } + var html = $('') + .addClass('generated') + .attr('id', name + 'row') + .append( + $('').addClass( 'label').text( label), + $('').append( + $( inputs).map( function() { + return this.toArray() + }) + ) + ); + + return html; + } + + function buildRadioButtons( label, name, option) { + var inputs = Array(); + if( option.valid_values instanceof Array) { + for( var x = 0; x < option.valid_values.length; x++) { + inputs.push( $('') + .attr({ + type: 'radio', + name: name, + value: option.valid_values[ x] + }) + ); + inputs.push( $( '').text( option.valid_values[ x])); + inputs.push( $( '
    ')); + } + } + else if( option.valid_values instanceof Object) { + for( var key in option.valid_values) { + inputs.push( $('') + .attr({ + type: 'radio', + name: name, + value: key + }) + ); + inputs.push( $( '').text( key)); + inputs.push( $( '
    ')); + } + } + var html = $('') + .addClass('generated') + .attr('id', name + 'row') + .append( + $('').addClass( 'label').text( label), + $('').append( + $( inputs).map( function() { + return this.toArray() + }) + ) + ); + return html; + } + + function buildTextField( label, name, option) { + var html = $('') + .addClass('generated') + .attr('id', name + 'row') + .append( + $('').addClass('label').text( label), + $('').append( + $('').attr({ + type: "text", + name: name, + title: option.description + }) + ) + ); + return html; + } + + function isRequired( option, query) { + var required = false; + if( option.hasOwnProperty( 'required') && + ( option.required.length > 0)) { + if( option.required[ 0] == "all") { + required = true; + } + else { + for( var x = 0; x < option.required.length; x++) { + if( option.required[ x] == query) { + required = true; + } + } + } + } + return required; + } + + function isOptional( option, query) { + var optional = false; + if( option.hasOwnProperty( 'optional') && + ( option.optional.length > 0)) { + if( option.optional[ 0] == "all") { + optional = true; + } + else { + for( var x = 0; x < option.optional.length; x++) { + if( option.optional[ x] == query) { + optional = true; + } + } + } + } + return optional; + } + + function getNagiosObject( key, option) { + var queryspec = option.type.substr( "nagios:".length); + var slash = queryspec.search( "/"); + var cgi = queryspec.substr( 0, slash); + var query = queryspec.substr( slash+1); + var success = function(data, results) { + var nagobjs = {}; + nagobjs[ 'valid_values'] = new Object(); + for( var vvkey in option.valid_values) { + nagobjs.valid_values[ vvkey] = option.valid_values[ vvkey]; + } + if( query == "servicelist") { + // Special case because services are nested under hosts + var services = new Array(); + for( var hostname in data.data[ query]) { + var host = data.data[ query][ hostname]; + for( var x = 0; x < host.length; x++) { + if( services.indexOf( host[ x]) == -1) { + services.push( host[ x]); + } + } + } + services.sort(); + for( var x = 0; x < services.length; x++) { + nagobjs.valid_values[ services[ x]] = {}; + } + } + else { + for( var x = 0; x < data.data[ query].length; x++) { + nagobjs.valid_values[ data.data[ query][ x]] = new Object(); + nagobjs.valid_values[ data.data[ query][ x]][ 'description'] = data.data[ query][ x]; + } + } + var selector = '#cgiform #' + key + 'row'; + $(selector).replaceWith( + buildSelect( option.label, key, nagobjs) + ); + }; + var parameters = Object(); + parameters.query = query; + if( option.depends_on != "") { + var dependsOnValue = getValue( option.depends_on, + help.data.options[ option.depends_on]); + if( dependsOnValue != "") { + parameters[ option.depends_on] = dependsOnValue; + } + } + $.ajax({ + url: baseurl + '/cgi-bin/' + cgi + '.cgi', + data: parameters, + success: success, + async: false + }); + } + + function updateOption(query, key, option) { + var required = isRequired( option, query); + var optional = isOptional( option, query); + var row = '#' + key + 'row'; // row selector + // If either optional or required, show the parameter + if( required || optional) { + // If the parameter is Nagios object, fetch it + if( /^nagios:/.test( option.type)) { + if( option.depends_on == "") { + getNagiosObject( key, option); + } + else { + var dependsOnValue = getValue( option.depends_on, + help.data.options[ option.depends_on]); + if(( dependsOnValue == "") && + disableWhenDependsOnValueBlank) { + $(row + ' select').attr( "disabled", "disabled"); + } + else { + getNagiosObject( key, option); + $(row + ' select').removeAttr( "disabled"); + } + $('select#' + option.depends_on).change(function() { + var query = getValue( 'query', help.data.options.query); + for( var key in help.data.options) { + var option = help.data.options[ key]; + if( option.depends_on === $(this).attr( "id")) { + updateOption(query, key, option); + } + } + }); + } + } + $( row).show(); + } + else { + $( row).hide(); + } + // If required, highlight the label + if( required) { + $( row + ' td.label').addClass( 'required'); + } + else { + $( row + ' td.label').removeClass( 'required'); + } + } + + function updateForm(query) { + $('#query button').attr('disabled','disabled'); + for( var key in help.data.options ) { + updateOption(query, key, help.data.options[ key]); + } + } + + function getValue( name, option) { + switch( option.type) { + case "enumeration": + return $( '#' + name + 'row select option:selected').val(); + break; + case "list": + output = Array(); + if( option.valid_values instanceof Array) { + for( var x = 0; x < option.valid_values.length; x++) { + if( $( '#' + name + 'row input[value=' + + valid_values[ x] + ']').attr( 'checked') == + 'checked') { + output.push( valid_values[ x]); + } + } + } + else if( option.valid_values instanceof Object) { + for( var key in option.valid_values) { + if( $( '#' + name + 'row input[value=' + key + + ']').attr( 'checked') == 'checked') { + output.push( key); + }; + } + } + return output; + break; + case "integer": + case "string": + return $( '#' + name + 'row input').val(); + break; + case "boolean": + if( $( '#' + name + 'row input:radio[name=' + name + + ']:checked').val() == "True") { + return true; + } + else { + return false; + } + break; + default: + if( /^nagios:/.test( option.type)) { + return $( '#' + name + 'row select option:selected').val(); + } + break; + } + } + + function buildForm() { + $('#cgiform tr.generated').remove(); + $('#cgiform').append( buildSelect( 'Query', 'query', + help.data.options.query)); + $('#queryrow td.label').addClass( 'required'); + for( var key in help.data.options ) { + if( key != "query") { + var option = help.data.options[ key] + switch( option.type) { + case "enumeration": + $('#cgiform').append( buildSelect( option.label, key, + option)); + break; + case "list": + $('#cgiform').append( buildCheckbox( option.label, key, + option)); + break; + case "integer": + case "string": + $('#cgiform').append( buildTextField( option.label, key, + option)); + break; + case "boolean": + $('#cgiform').append( buildRadioButtons( option.label, key, + true_false)); + break; + default: + if( /^nagios:/.test( option.type)) { + var nagobjs = { + "valid_values": [ + ] + }; + $('#cgiform').append( buildSelect( option.label, + key, nagobjs)); + } + else { + $('#cgiform').append( ''); + } + break; + } + if( !(( option.hasOwnProperty( 'required') && + ( option.required.length > 0) && + ( option.required[ 0] === "all")) || + ( option.hasOwnProperty( 'optional') && + ( option.optional.length > 0) && + ( option.optional[ 0] === "all")))) { + $('#' + key + 'row').hide(); + } + } + } + + $('select#query').change(function() { + var query = $('select#query').val(); + updateForm(query); + $('#query button').removeAttr('disabled'); + }); + $('#query button').removeAttr('disabled'); + } + + $('select#cginame').change(function() { + var cginame = $('select#cginame').val(); + if( cginame == 'none') { + $('#cgiform tr.generated').remove(); + $('#query button').attr('disabled','disabled'); + } + else { + $.get( baseurl + '/cgi-bin/' + cginame, + { query: "help" }, function(data, results) { + help = data; + buildForm(data); + }); + } + }); + + function indentf(padding, text) { + var result = ""; + for( var padvar = 0; padvar < padding; padvar++) { + result = result.concat( "    "); + } + result = result.concat( text); + return result; + } + + function arrayToString( padding, arr) { + var result = ""; + var members = Array(); + + result = result.concat( "[
    "); + padding++; + for( var x = 0; x < arr.length; x++) { + members.push( memberToString( padding, null, arr[ x])); + } + result = result.concat( members.join( ",
    ") + "
    "); + padding--; + result = result.concat( indentf(padding, "]")); + return result; + } + + function isString(o) { + return typeof o == "string" || + (typeof o == "object" && o.constructor === String); + } + + function memberToString( padding, key, value) { + var result = ""; + + if( key == null) { + result = result.concat( indentf( padding, '')); + } + else { + result = result.concat( indentf( padding, '"' + key + '": ')); + } + + if( value instanceof Array) { + result = result.concat( arrayToString( padding, value)); + } + else if( value instanceof Object) { + result = result.concat( objectToString( padding, value)); + } + else if(isString(value)) { + result = result.concat( '"' + value + '"') + } + else { + result = result.concat( value); + } + + return result; + } + + function objectToString( padding, obj) { + var result = ""; + var members = Array(); + + result = result.concat( "{
    "); + padding++; + for( var key in obj) { + members.push( memberToString( padding, key, obj[ key])); + } + result = result.concat( members.join( ",
    ") + "
    "); + padding--; + result = result.concat( indentf(padding, "}")); + return result; + } + + $('#query').submit( function() { + $('#results').html( ""); + var cginame = $('select#cginame').val(); + if( cginame != 'none') { + var query = $('select#query').val(); + var parameters = Object(); + for( var key in help.data.options) { + var option = help.data.options[ key]; + var required = isRequired( option, query); + var optional = isOptional( option, query); + if( required || optional) { + var value = getValue( key, option); + if(( value == null) || ( value == "")) { + if( required) { + $('#results').append( + $( '

    '). + addClass( 'error'). + append( option.label + " missing") + ); + } + } + else { + if( value instanceof Array) { + parameters[ key] = value.join( ' '); + } + else { + parameters[ key] = value; + } + } + } + } + var p = jQuery.param( parameters); + var url = baseurl + '/cgi-bin/' + cginame + '?' + p + $('#results').append( + $('

    ').text( 'URL: ').append( + $('').attr({ + href: url, + target: "_blank" + }).text( url) + ) + ); + $.get( baseurl + '/cgi-bin/' + cginame, + parameters, + function(data, results) { + $('#results').append( + $('

    ').html( objectToString( 0, data)) + ); + } + ); + } + return false; + }); + + $('select#cginame').val( 'none'); +}); diff --git a/html/js/map-directive.js b/html/js/map-directive.js new file mode 100644 index 0000000..1d13b37 --- /dev/null +++ b/html/js/map-directive.js @@ -0,0 +1,3691 @@ +angular.module("mapApp") + .directive("nagiosMap", function() { + return { + templateUrl: "map-directive.html", + restrict: "AE", + scope: { + cgiurl: "@cgiurl", + layoutIndex: "@layout", + dimensions: "@dimensions", + ulxValue: "@ulx", + ulyValue: "@uly", + lrxValue: "@lrx", + lryValue: "@lry", + root: "=root", + maxzoom: "=maxzoom", + nolinks: "@nolinks", + notext: "@notext", + nopopups: "@nopopups", + noresize: "@noresize", + noicons: "@noicons", + iconurl: "@iconurl", + updateIntervalValue: "@updateInterval", + lastUpdate: "=lastUpdate", + reload: "@reload", + svgWidth: "=mapWidth", + svgHeight: "=mapHeight", + build: "&build" + }, + controller: function($scope, $element, $attrs, $http, + nagiosProcessName, layouts) { + + // Contents of the popup + $scope.popupContents = {}; + + // Layout variables + $scope.diameter = Math.min($scope.svgHeight, + $scope.svgWidth); + $scope.mapZIndex = 20; + $scope.popupZIndex = 40; + $scope.popupPadding = 10; + $scope.fontSize = 10; // px + $scope.minRadius = 5; + // radius of node with zero services + $scope.maxRadiusCount = 20; + // number of services at which to max radius + $scope.maxRadius = 12; + // radius of node with maxRadiusCount+ services + $scope.swellRadius = 4; + // amount by which radius swells when updating + $scope.nodeID = 0; + // Incrementing unique node ID for each node + + // Display variables + $scope.layout = parseInt($scope.layoutIndex); + $scope.ulx = parseInt($scope.ulxValue); + $scope.uly = parseInt($scope.ulyValue); + $scope.lrx = parseInt($scope.lrxValue); + $scope.lry = parseInt($scope.lryValue); + $scope.showText = $scope.notext == "false"; + $scope.showLinks = $scope.nolinks == "false"; + $scope.showPopups = $scope.nopopups == "false"; + $scope.allowResize = $scope.noresize == "false"; + $scope.showIcons = $scope.noicons == "false"; + + // Resize handle variables + $scope.handleHeight = 8; + $scope.handleWidth = 8; + $scope.handlePadding = 2; + + // Host node tree - initialize the root node + $scope.hostTree = { + hostInfo: { + name: nagiosProcessName, + objectJSON: { + name: nagiosProcessName, + icon_image: "", + icon_image_alt: "", + x_2d: 0, + y_2d: 0 + }, + serviceCount: 0 + }, + saveArc: { + x: 0, + dx: 0, + y: 0, + dy: 0 + }, + saveLabel: { + x: 0, + dx: 0, + y: 0, + dy: 0 + } + }; + $scope.hostList = new Object; + + // Icon information + $scope.iconList = new Object; + $scope.iconsLoading = 0; + + // Update frequency + $scope.updateStatusInterval = + parseInt($scope.updateIntervalValue) * 1000; + + // Map update variables + $scope.updateDuration = 0; + + // Date format for popup dates + $scope.popupDateFormat = d3.time.format("%m-%d-%Y %H:%M:%S"); + + // Root node name + $scope.rootNodeName = nagiosProcessName; + $scope.rootNode = null; + + // Application state variables + $scope.fetchingHostlist = false; + $scope.displayPopup = false; + var previousLayout = -1; + var statusTimeout = null; + var displayMapDone = false; + + // Placeholder for saving icon url + var previousIconUrl; + + // User-supplied layout information + var userSuppliedLayout = { + dimensions: { + upperLeft: {}, + lowerRight: {} + }, + xScale: d3.scale.linear(), + yScale: d3.scale.linear() + } + + // Force layout information + var forceLayout = new Object; + + // Watch for changes on the reload value + $scope.$watch("reload", function(newValue) { + + // Cancel the timeout if necessary + if (statusTimeout != null) { + clearTimeout(statusTimeout); + } + + // Clean up after previous maps + var selectionExit; + switch (previousLayout) { + case layouts.UserSupplied.index: + selectionExit = d3.select("g#container") + .selectAll("g.node") + .data([]) + .exit(); + selectionExit.selectAll("circle").remove(); + selectionExit.selectAll("text").remove(); + selectionExit.remove(); + break; + case layouts.DepthLayers.index: + case layouts.DepthLayersVertical.index: + case layouts.CollapsedTree.index: + case layouts.CollapsedTreeVertical.index: + case layouts.BalancedTree.index: + case layouts.BalancedTreeVertical.index: + case layouts.CircularBalloon.index: + selectionExit = d3.select("g#container") + .selectAll(".node") + .data([]) + .exit(); + selectionExit.selectAll("circle").remove(); + selectionExit.selectAll("text").remove(); + selectionExit.remove(); + d3.select("g#container") + .select("g#links") + .selectAll(".link") + .data([]) + .exit() + .remove(); + d3.select("g#links").remove(); + break; + case layouts.CircularMarkup.index: + d3.select("g#container") + .select("g#paths") + .selectAll("path") + .data([]) + .remove(); + selectionExit = d3.select("g#container") + .selectAll("g.label") + .data([]) + .exit(); + selectionExit.selectAll("rect").remove(); + selectionExit.selectAll("text").remove(); + selectionExit.remove(); + d3.select("g#paths").remove(); + break; + case layouts.Force.index: + selectionExit = d3.select("g#container") + .selectAll(".link") + .data([]) + .exit(); + selectionExit.selectAll("line").remove(); + selectionExit.remove(); + selectionExit = d3.select("g#container") + .selectAll("g.node") + .data([]) + .exit(); + selectionExit.selectAll("circle").remove(); + selectionExit.selectAll("text").remove(); + selectionExit.remove(); + d3.select("g#links").remove(); + break; + } + + // Clean up the host list + $scope.hostList = {}; + + // Clean up the icon image cache if the icon url + // has changed + if (previousIconUrl != $scope.iconurl) { + d3.selectAll("div#image-cache img").remove(); + $scope.iconList = new Object; + $scope.iconsLoading = 0; + } + previousIconUrl = $scope.iconurl; + + // Reset the zoom and pan + $scope.zoom.translate([0,0]).scale(1); + // Show the map + if ($scope.build()) { + + // Determine the new layout + $scope.layout = parseInt($scope.layoutIndex); + + // Adjust the container appropriately + d3.select("svg#map g#container") + .attr({ + transform: function() { + return getContainerTransform(); + } + }); + + // Layout-specific steps + switch ($scope.layout) { + case layouts.UserSupplied.index: + userSuppliedLayout.dimensionType = $scope.dimensions + break; + case layouts.DepthLayers.index: + case layouts.DepthLayersVertical.index: + case layouts.CollapsedTree.index: + case layouts.CollapsedTreeVertical.index: + case layouts.BalancedTree.index: + case layouts.BalancedTreeVertical.index: + case layouts.CircularBalloon.index: + case layouts.CircularMarkup.index: + case layouts.Force.index: + break; + } + previousLayout = $scope.layout; + + // Start the spinner + $scope.spinnerdiv = d3.select("div#spinner"); + $scope.fetchingHostlist = true; + $scope.spinner = new Spinner($scope.spinnerOpts) + .spin($scope.spinnerdiv[0][0]); + + // Get the host list and move forward + getHostList(); + } + }); + + // Watch for changes in the size of the map + $scope.$watch("svgWidth", function(newValue) { + if (displayMapDone) { + updateOnResize(d3.select("#resize-handle").node()); + } + }); + $scope.$watch("svgHeight", function(newValue) { + if (displayMapDone) { + updateOnResize(d3.select("#resize-handle").node()); + } + }); + + // Get the services of the children of a specific node + var getServiceList = function() { + + var parameters = { + query: "servicelist", + formatoptions: "enumerate bitmask", + details: false + }; + + var getConfig = { + params: parameters, + withCredentials: true + }; + + if ($scope.showIcons && $scope.iconsLoading > 0) { + setTimeout(function() { + getServiceList() + }, 10); + return; + } + + // Send the JSON query + $http.get($scope.cgiurl + "objectjson.cgi", getConfig) + .error(function(err) { + console.warn(err); + }) + .success(function(json) { + // Record the time of the last update + $scope.lastUpdate = json.result.query_time; + + for(var host in json.data.servicelist) { + $scope.hostList[host].serviceCount = + json.data.servicelist[host].length; + } + }); + }; + + // Take action on the zoom start + var onZoomStart = function() { + + // Hide the popup window + $scope.displayPopup = false; + $scope.$apply("displayPopup"); + }; + + // Take action on the zoom + var onZoom = function() { + + // Get the event parameters + var zoomTranslate = $scope.zoom.translate(); + var zoomScale = $scope.zoom.scale(); + + var translate = []; + switch($scope.layout) { + case layouts.UserSupplied.index: + d3.selectAll("g.node") + .attr({ + transform: function(d) { + return getNodeTransform(d); + } + }); + d3.selectAll("g.node text") + .each(function(d) { + setTextAttrs(d, this); + }); + break; + case layouts.DepthLayers.index: + case layouts.DepthLayersVertical.index: + case layouts.CollapsedTree.index: + case layouts.CollapsedTreeVertical.index: + case layouts.BalancedTree.index: + case layouts.BalancedTreeVertical.index: + d3.selectAll("path.link") + .attr({ + d: $scope.diagonal + }); + d3.selectAll("g.node") + .attr({ + transform: function(d) { + return getNodeTransform(d); + } + }); + break; + case layouts.CircularBalloon.index: + // Calculate the real translation taking + // into account the centering + translate = [zoomTranslate[0] + + ($scope.svgWidth / 2) * zoomScale, + zoomTranslate[1] + + ($scope.svgHeight / 2) * zoomScale]; + d3.select("svg#map g#container") + .attr("transform", "translate(" + translate + + ")"); + d3.selectAll("path.link") + .attr({ + d: $scope.diagonal + }); + d3.selectAll("g.node") + .attr({ + transform: function(d) { + return getNodeTransform(d); + } + }); + break; + case layouts.CircularMarkup.index: + // Calculate the real translation taking + // into account the centering + translate = [zoomTranslate[0] + + ($scope.svgWidth / 2) * zoomScale, + zoomTranslate[1] + + ($scope.svgHeight / 2) * zoomScale]; + // Update the group with the new calculated values + d3.select("svg#map g#container") + .attr("transform", + "translate(" + translate + ")"); + d3.selectAll("path") + .attr("transform", "scale(" + zoomScale + ")"); + d3.selectAll("g.label") + .attr({ + transform: function(d) { + return getPartitionLabelGroupTransform(d); + } + }); + break; + case layouts.Force.index: + d3.selectAll("line.link") + .attr({ + x1: function(d) { + return $scope.xZoomScale(d.source.x); + }, + y1: function(d) { + return $scope.yZoomScale(d.source.y); + }, + x2: function(d) { + return $scope.xZoomScale(d.target.x); + }, + y2: function(d) { + return $scope.yZoomScale(d.target.y); + } + }); + d3.selectAll("g.node") + .attr({ + transform: function(d) { + return "translate(" + + $scope.xZoomScale(d.x) + ", " + + $scope.yZoomScale(d.y) + ")"; + } + }); + break; + } + }; + + // Get the tree size + var getTreeSize = function() { + + switch($scope.layout) { + case layouts.DepthLayers.index: + return [$scope.svgWidth, $scope.svgHeight - + layouts.DepthLayers.topPadding - + layouts.DepthLayers.bottomPadding]; + break; + case layouts.DepthLayersVertical.index: + return [$scope.svgHeight, $scope.svgWidth - + layouts.DepthLayersVertical.leftPadding - + layouts.DepthLayersVertical.rightPadding]; + break; + case layouts.CollapsedTree.index: + return [$scope.svgWidth, $scope.svgHeight - + layouts.CollapsedTree.topPadding - + layouts.CollapsedTree.bottomPadding]; + break; + case layouts.CollapsedTreeVertical.index: + return [$scope.svgHeight, $scope.svgWidth - + layouts.CollapsedTreeVertical.leftPadding - + layouts.CollapsedTreeVertical.rightPadding]; + break; + case layouts.BalancedTree.index: + return [$scope.svgWidth, $scope.svgHeight - + layouts.BalancedTree.topPadding - + layouts.BalancedTree.bottomPadding]; + break; + case layouts.BalancedTreeVertical.index: + return [$scope.svgHeight, $scope.svgWidth - + layouts.BalancedTreeVertical.leftPadding - + layouts.BalancedTreeVertical.rightPadding]; + break; + case layouts.CircularBalloon.index: + return [360, $scope.diameter / 2 - + layouts.CircularBalloon.outsidePadding]; + break; + } + }; + + // Get the node transform + var getNodeTransform = function(d) { + + switch($scope.layout) { + case layouts.UserSupplied.index: + var x1 = d.hostInfo.objectJSON.x_2d; + var x2 = userSuppliedLayout.xScale(x1); + var x3 = $scope.xZoomScale(x2); + var y1 = d.hostInfo.objectJSON.y_2d; + var y2 = userSuppliedLayout.yScale(y1); + var y3 = $scope.yZoomScale(y2); + return "translate(" + x3 + "," + y3 + ")"; + break; + case layouts.DepthLayers.index: + case layouts.CollapsedTree.index: + case layouts.BalancedTree.index: + return "translate(" + $scope.xZoomScale(d.x) + "," + + $scope.yZoomScale(d.y) + ")"; + break; + case layouts.DepthLayersVertical.index: + case layouts.CollapsedTreeVertical.index: + case layouts.BalancedTreeVertical.index: + return "translate(" + $scope.xZoomScale(d.y) + "," + + $scope.yZoomScale(d.x) + ")"; + break; + case layouts.CircularBalloon.index: + if(d.y == 0) return ""; + var rotateAngle = d.x + + layouts.CircularBalloon.rotation; + var translate = d.y * $scope.zoom.scale(); + return "rotate(" + rotateAngle + ") translate(" + + translate + ")"; + break; + } + }; + + // Determine the amount of text padding due to an icon + var getIconTextPadding = function(d) { + var iconHeight = 0, iconWidth = 0; + if (d.hostInfo.hasOwnProperty("iconInfo")) { + iconHeight = d.hostInfo.iconInfo.height; + iconWidth = d.hostInfo.iconInfo.width; + } + else { + return 0; + } + switch($scope.layout) { + case layouts.UserSupplied.index: + switch(layouts.UserSupplied.textAlignment) { + case "above": + case "below": + return iconHeight / 2; + break; + case "left": + case "right": + return iconWidth / 2; + break; + } + break; + case layouts.DepthLayers.index: + case layouts.CollapsedTree.index: + case layouts.BalancedTree.index: + return iconHeight / 2; + break; + case layouts.DepthLayersVertical.index: + case layouts.CollapsedTreeVertical.index: + case layouts.BalancedTreeVertical.index: + return iconWidth / 2; + break; + case layouts.CircularBalloon.index: + var rotateAngle = d.x + + layouts.CircularBalloon.rotation; + var angle; // angle used to calculate distance + var r; // radius used to calculate distance + if (rotateAngle < 45.0) { + // Text is right of icon + angle = rotateAngle; + r = iconWidth / 2; + } + else if(rotateAngle < 135.0) { + // Text is below icon + angle = Math.abs(90.0 - rotateAngle); + r = iconHeight / 2; + } + else if(rotateAngle < 225.0) { + // Text is left icon + angle = Math.abs(180.0 - rotateAngle); + r = iconWidth / 2; + } + else if(rotateAngle < 315.0) { + // Text is above icon + angle = Math.abs(270.0 - rotateAngle); + r = iconHeight / 2; + } + else { + // Text is right of icon + angle = 360.0 - rotateAngle; + r = iconWidth / 2; + } + var radians = angle * Math.PI / 180.0; + var cos = Math.cos(radians); + return r + (r - r * cos) * cos; + break; + case layouts.CircularMarkup.index: + return 0; + break; + case layouts.Force.index: + return iconWidth / 2; + break; + } + }; + + // Set the node label attributes + var setTextAttrs = function(d, domNode) { + + // Placeholder for attributes + var attrs = new Object; + var state = "ok"; + var stateCounts = {}; + + // Variables used for all layouts + var serviceCount = getObjAttr(d, ["serviceCount"], 0); + var iconTextPadding = getIconTextPadding(d); + var fontSize = $scope.fontSize + "px"; + + if (d.hostInfo.name == $scope.$parent.search.host) + fontSize = ($scope.fontSize * 2) + "px"; + attrs["font-size"] = fontSize; + attrs["font-weight"] = "normal"; + attrs["text-decoration"] = "none"; + attrs["fill"] = "#000000"; + + if (d.hostInfo.name != $scope.$parent.search.host && d.hostInfo.hasOwnProperty("serviceStatusJSON")) { + for (var service in d.hostInfo.serviceStatusJSON) { + var state = d.hostInfo.serviceStatusJSON[service]; + if(!stateCounts.hasOwnProperty(state)) + stateCounts[state] = 0; + stateCounts[state]++; + } + if (stateCounts["critical"]) + state = "critical"; + else if (stateCounts["warning"]) + state = "warning"; + else if (stateCounts["unknown"]) + state = "unknown"; + else if (stateCounts["pending"]) + state = "pending"; + } + + switch($scope.layout) { + case layouts.UserSupplied.index: + var textPadding = + layouts.UserSupplied.textPadding[layouts.UserSupplied.textAlignment]; + if (!d.hostInfo.hasOwnProperty("iconInfo")) { + textPadding += $scope.nodeScale(serviceCount); + } + var x = 0; + var y = 0; + switch(layouts.UserSupplied.textAlignment) { + case "above": + y = -(textPadding + iconTextPadding); + attrs["text-anchor"] = "middle"; + break; + case "left": + x = -(textPadding + iconTextPadding); + attrs["text-anchor"] = "end"; + attrs.dy = ".4em"; + break; + case "right": + x = textPadding + iconTextPadding; + attrs["text-anchor"] = "start"; + attrs.dy = ".4em"; + break; + case "below": + y = textPadding + iconTextPadding; + attrs["text-anchor"] = "middle"; + break; + } + attrs.transform = "translate(" + x + "," + y + ")"; + break; + case layouts.DepthLayers.index: + var textPadding = $scope.nodeScale(serviceCount) + + layouts.DepthLayers.dyText + iconTextPadding; + attrs.dy = d.children ? -textPadding : 0; + attrs.transform = d.children ? "" : + "rotate(90) translate(" + textPadding + + ", " + (($scope.fontSize / 2) - 1) + ")"; + attrs["text-anchor"] = d.children ? "middle" : + "start"; + break; + case layouts.DepthLayersVertical.index: + var textPadding = $scope.nodeScale(serviceCount) + + layouts.DepthLayersVertical.dxText + + iconTextPadding; + attrs.dx = d.children ? -textPadding : textPadding; + attrs.dy = layouts.DepthLayersVertical.dyText; + attrs["text-anchor"] = d.children ? "end" : "start"; + break; + case layouts.CollapsedTree.index: + var textPadding = $scope.nodeScale(serviceCount) + + layouts.CollapsedTree.dyText + + iconTextPadding; + attrs.dy = d.children ? -textPadding : 0; + attrs.transform = d.children ? "" : + "rotate(90) translate(" + textPadding + + ", " + (($scope.fontSize / 2) - 1) + ")"; + attrs["text-anchor"] = d.children ? "middle" : + "start"; + break; + case layouts.CollapsedTreeVertical.index: + var textPadding = $scope.nodeScale(serviceCount) + + layouts.CollapsedTreeVertical.dxText + + iconTextPadding; + attrs.dx = d.children ? -textPadding : textPadding; + attrs.dy = layouts.CollapsedTreeVertical.dyText; + attrs["text-anchor"] = d.children ? "end" : "start"; + break; + case layouts.BalancedTree.index: + var textPadding = $scope.nodeScale(serviceCount) + + layouts.BalancedTree.dyText + + iconTextPadding; + attrs.dy = d.children ? -textPadding : 0; + attrs.transform = d.children ? "" : + "rotate(90) translate(" + textPadding + + ", " + (($scope.fontSize / 2) - 1) + ")"; + attrs["text-anchor"] = d.children ? "middle" : + "start"; + break; + case layouts.BalancedTreeVertical.index: + var textPadding = $scope.nodeScale(serviceCount) + + layouts.BalancedTreeVertical.dxText + + iconTextPadding; + attrs.dx = d.children ? -textPadding : textPadding; + attrs.dy = layouts.BalancedTreeVertical.dyText; + attrs["text-anchor"] = d.children ? "end" : "start"; + break; + case layouts.CircularBalloon.index: + var textPadding = $scope.nodeScale(serviceCount) + + layouts.CircularBalloon.textPadding + + iconTextPadding; + if(d.y == 0) { + attrs["text-anchor"] = "middle"; + attrs.transform = "translate(0,-" + + $scope.fontSize + ")"; + } + else if(d.x < 180) { + attrs["text-anchor"] = "start"; + attrs.transform = "translate(" + textPadding + + ")"; + } + else { + attrs["text-anchor"] = "end"; + attrs.transform = "rotate(180) translate(-" + + textPadding + ")"; + } + attrs.dy = layouts.CircularBalloon.dyText; + break; + case layouts.CircularMarkup.index: + attrs["alignment-baseline"] = "middle"; + attrs["text-anchor"] = "middle"; + attrs["transform"] = ""; + if (d.hostInfo.hasOwnProperty("iconInfo")) { + var rotateAngle = (d.x + d.dx / 2) * 180 / Math.PI + + layouts.CircularBalloon.rotation; + var translate = (d.hostInfo.iconInfo.height + + layouts.CircularMarkup.textPadding) / 2; + attrs["transform"] = "rotate(" + -rotateAngle + + ") translate(0, " + translate + ")"; + } + else { + if (d.depth > 0 && d.x + d.dx / 2 > Math.PI) { + attrs["transform"] = "rotate(180)"; + } + } + break; + case layouts.Force.index: + attrs["alignment-baseline"] = "middle"; + attrs["x"] = $scope.nodeScale(serviceCount) + + layouts.Force.textPadding + iconTextPadding; + break; + } + + if (d.hostInfo.name == $scope.$parent.search.host) { + attrs["font-weight"] = "bold"; + attrs["stroke"] = "red"; + attrs["stroke-width"] = "1"; + attrs["fill"] = "#0000ff"; + } else if (state != "ok") { + attrs["font-weight"] = "bold"; + attrs["text-decoration"] = "underline"; + switch(state) { + case "critical":attrs["fill"] = "#ff0000"; break; + case "warning": attrs["fill"] = "#b0b214"; break; + case "unknown": attrs["fill"] = "#ff6419"; break; + case "pending": attrs["fill"] = "#cccccc"; break; + } + } + d3.select(domNode).attr(attrs); + }; + + // Get the quadrant of the mouse pointer within the svg + var getQuadrant = function(mouse, bcr) { + + var quadrant = 0; + + // mouse is relative to body - + // convert to relative to svg + var mouseX = mouse[0] - bcr.left; + var mouseY = mouse[1] - bcr.top; + + if(mouseX < ((bcr.width - bcr.left) / 2)) { + // Left half of svg + if(mouseY < ((bcr.height - bcr.top) / 2)) { + // Top half of svg + quadrant = 2; + } + else { + // Bottom half of svg + quadrant = 3; + } + } + else { + // Right half of svg + if(mouseY < ((bcr.height - bcr.top) / 2)) { + // Top half of svg + quadrant = 1; + } + else { + // Bottom half of svg + quadrant = 4; + } + } + + return quadrant; + }; + + // Display the popup + var displayPopup = function(d) { + + // Get the mouse position relative to the body + var body = d3.select("body"); + var mouse = d3.mouse(body.node()); + + // Get the bounding client rect of the div + // containing the map + var bcr = d3.select("div#mapsvg") + .node() + .getBoundingClientRect(); + + // Hide the popup by setting is z-index to + // less than that of the map div and by + // centering it under the map div + var popup = d3.select("#popup") + .style({ + "z-index": $scope.mapZIndex - 1, + left: $scope.svgWidth / 2 + "px", + top: $scope.svgHeight / 2 + "px" + }); + + // Set it's contents and "display" it (it's still not + // visible because of it's z-index) + setPopupContents(popup, d); + $scope.displayPopup = true; + $scope.$apply("displayPopup"); + + // Now that it's "displayed", we can get it's size and + // calculate it's proper placement. Do so and set it's + // z-index so it is displayed + var popupBR = popup[0][0].getBoundingClientRect(); + var left; + var top; + switch(getQuadrant(mouse, bcr)) { + case 1: + left = mouse[0] - bcr.left - popupBR.width - + $scope.popupPadding; + top = mouse[1] - bcr.top + $scope.popupPadding; + break; + case 2: + left = mouse[0] - bcr.left + $scope.popupPadding; + top = mouse[1] - bcr.top + $scope.popupPadding; + break; + case 3: + left = mouse[0] - bcr.left + $scope.popupPadding; + top = mouse[1] - bcr.top - popupBR.height - + $scope.popupPadding; + break; + case 4: + left = mouse[0] - bcr.left - popupBR.width - + $scope.popupPadding; + top = mouse[1] - bcr.top - popupBR.height - + $scope.popupPadding; + break; + default: // use first quadrant settings + left = mouse[0] - bcr.left - popupBR.width - + $scope.popupPadding; + top = mouse[1] - bcr.top + $scope.popupPadding; + break; + } + popup.style({ + "z-index": $scope.popupZIndex, + left: left + "px", + top: top + "px" + }); + }; + + // Prune any deleted hosts from the host tree + var pruneHostTree = function(node) { + + if(node.hasOwnProperty("children")) { + node.children = node.children.filter(function(e) { + return e.hostInfo != null; + }); + node.children.forEach(function(e) { + pruneHostTree(e); + }); + } + }; + + // Sort the children of a node recursively + var sortChildren = function(node) { + + if (node.hasOwnProperty("children")) { + // First sort the children + node.children.sort(function(a, b) { + if (a.hostInfo.objectJSON.name < + b.hostInfo.objectJSON.name) { + return -1; + } + else if (a.hostInfo.objectJSON.name > + b.hostInfo.objectJSON.name) { + return 1; + } + return 0; + }); + + // Next sort the children of each of these nodes + node.children.forEach(function(e, i, a) { + sortChildren(e); + }); + } + }; + + // Re-parent the tree with a new root + var reparentTree = function(node) { + + // The specified node becomes the new node and all + // it's children remain in place relative to it + var newTree = node; + + // Visit each parent of the specified node + var currentNode = node; + while (!(currentNode === $scope.hostTree)) { + // First record the parent node of the current node + var parent = currentNode.parent; + + // Next remove the current node as a child of + // the parent node + parent.children = parent.children.filter(function(e, i, a) { + if (e === currentNode) { + return false; + } + return true; + }); + + // Finally add the parent as a child + // to the current node + if (!currentNode.hasOwnProperty("children")) { + currentNode.children = new Array; + } + currentNode.children.push(parent); + + // Set the current node the former parent of the + // former current node + currentNode = parent; + } + + // Now sort the nodes in the tree + sortChildren(newTree); + + // Record the host name for the root node + $scope.rootNodeName = newTree.hostInfo.name; + $scope.rootNode = newTree; + + // Assign the new tree + $scope.hostTree = newTree; + $scope.focalPoint = newTree; + }; + + // Toggle a node + var toggleNode = function(d) { + + if (d.children) { + d._children = d.children; + d.children = null; + d.collapsed = true; + } + else { + switch($scope.layout) { + case layouts.CircularMarkup.index: + updateToggledNodes($scope.hostTree, + updateDescendantsOnExpand); + break; + } + d.children = d._children; + d._children = null; + d.collapsed = false; + } + }; + + // Interpolate the arcs in data space. + var arcTween = function(a) { + var i = d3.interpolate({x: a.saveArc.x, + dx: a.saveArc.dx, y: a.saveArc.y, + dy: a.saveArc.dy}, a); + return function(t) { + var b = i(t); + a.saveArc.x = b.x; + a.saveArc.dx = b.dx; + a.saveArc.y = b.y; + a.saveArc.dy = b.dy; + return $scope.arc(b); + }; + } + + // Interpolate the node labels in data space. + var labelGroupTween = function(a) { + var i = d3.interpolate({x: a.saveLabel.x, + dx: a.saveLabel.dx, y: a.saveLabel.y, + dy: a.saveLabel.dy}, a); + return function(t) { + var b = i(t); + a.saveLabel.x = b.x; + a.saveLabel.dx = b.dx; + a.saveLabel.y = b.y; + a.saveLabel.dy = b.dy; + return getPartitionLabelGroupTransform(b); + }; + } + + // Get the partition map label group transform + var getPartitionLabelGroupTransform = function(d) { + + var radians = d.x + d.dx / 2; + var rotate = (radians * 180 / Math.PI) - 90; + var exponent = 1 / layouts.CircularMarkup.radialExponent; + var radius = d.y + (d.y / (d.depth * 2)); + var translate = Math.pow(radius, exponent) * $scope.zoom.scale(); + var transform = ""; + + if(d.depth == 0) { + transform = ""; + } + else { + transform = "rotate(" + rotate + ")" + + " translate(" + translate + ")"; + } + return transform; + }; + + // Find a host in a sorted array of hosts + var findElement = function(list, key, accessor) { + + var start = 0; + var end = list.length - 1; + + while (start < end) { + var midpoint = parseInt(start + + (end - start + 1) / 2); + if (accessor(list, midpoint) == key) { + return midpoint; + } + else if (key < accessor(list, midpoint)) { + end = midpoint - 1; + } + else { + start = midpoint + 1; + } + } + return null; + }; + + // Update a node in the host tree + var updateHostTree = function(node, hosts) { + + // Sort the hosts array + hosts.sort(); + + // First remove any children of the node that are not + // in the list of hosts + if (node.hasOwnProperty("children") && + node.children != null) { + node.children = node.children.filter(function(e) { + return findElement(hosts, e.hostInfo.name, + function(list, index) { + return list[index]; + }) != null; + }); + // Sort the remaining children + node.children.sort(function(a, b) { + if (a.hostInfo.name == b.hostInfo.name) { + return 0; + } + else if (a.hostInfo.name < b.hostInfo.name) { + return -1; + } + else { + return 1; + } + }); + } + + // If the node has no children and the host list + // does, create the property and initialize it + if (!node.hasOwnProperty("children") || + node.children == null) { + node.children = new Array; + } + + // Next add any hosts in the list as children + // of the node, if they're not already + hosts.forEach(function(e) { + var childIndex = findElement(node.children, e, + function(list, index) { + return list[index].hostInfo.name; + }); + + if ($scope.hostList[e]) { + + if (childIndex == null) { + + // Create the node object + var hostNode = new Object; + + // Point the node's host info to the entry in + // the host list + hostNode.hostInfo = $scope.hostList[e]; + + // And vice versa + if (!$scope.hostList[e].hasOwnProperty("hostNodes")) { + $scope.hostList[e].hostNodes = new Array; + } + if (!$scope.hostList[e].hostNodes.reduce(function(a, b) { + return a && b === hostNode; }, false)) { + $scope.hostList[e].hostNodes.push(hostNode); + } + + // Set the parent of this node + hostNode.parent = node; + + // Initialize layout information for transitions + hostNode.saveArc = new Object; + hostNode.saveArc.x = 0; + hostNode.saveArc.dx = 0; + hostNode.saveArc.y = 0; + hostNode.saveArc.dy = 0; + hostNode.saveLabel = new Object; + hostNode.saveLabel.x = 0; + hostNode.saveLabel.dx = 0; + hostNode.saveLabel.y = 0; + hostNode.saveLabel.dy = 0; + + // Add the node to the parent node's children + node.children.push(hostNode); + + // Get the index + childIndex = node.children.length - 1; + } + // Recurse to all children of this host + if ($scope.hostList[e].objectJSON.child_hosts.length > 0) { + var childHosts = $scope.hostList[e].objectJSON.child_hosts; + updateHostTree(node.children[childIndex], + childHosts, hostNode); + } + } + }); + }; + + // Create an ID for an img based on a file name + var imgID = function(image) { + return "cache-" + image.replace(/\./, "_"); + }; + + // Update the image icon cache + var updateImageIconCache = function() { + var cache = d3.select("div#image-cache") + for (var host in $scope.hostList) { + var image = + $scope.hostList[host].objectJSON.icon_image; + if (image != "") { + if (!$scope.iconList.hasOwnProperty(imgID(image))) { + $scope.iconList[imgID(image)] = new Object; + $scope.iconsLoading++; + cache.append("img") + .attr({ + id: function() { + return imgID(image); + }, + src: $scope.iconurl + image + }) + .on("load", function() { + $scope.iconsLoading--; + var img = d3.select(d3.event.target); + var image = img.attr("id"); + $scope.iconList[image].width = + img.node().naturalWidth; + $scope.iconList[image].height = + img.node().naturalHeight; + }) + .on("error", function() { + $scope.iconsLoading--; + }); + } + $scope.hostList[host].iconInfo = + $scope.iconList[imgID(image)]; + } + } + }; + + // Build the host list and tree from the hosts returned + // from the JSON CGIs + var processHostList = function(json) { + + // First prune any host from the host list that + // is no longer in the hosts returned from the CGIs + for (var host in $scope.hostList) { + if(host != nagiosProcessName && + !json.data.hostlist.hasOwnProperty(host)) { + // Mark the entry as null (deletion is slow) + $scope.hostList[host] = null; + } + } + + // Next prune any deleted hosts from the host tree + pruneHostTree($scope.hostTree); + + // Now update the host list with the data + // returned from the CGIs + for (var host in json.data.hostlist) { + // If we don't know about the host yet, add it to + // the host list + if (!$scope.hostList.hasOwnProperty(host) || + $scope.hostList[host] == null) { + $scope.hostList[host] = new Object; + $scope.hostList[host].name = host; + $scope.hostList[host].serviceCount = 0; + } + // If a hosts' parent is not in the hostlist (user + // doesn't have permission to view parent) re-parent the + // host directly under the nagios process + for (var parent in json.data.hostlist[host].parent_hosts) { + var prnt = json.data.hostlist[host].parent_hosts[parent]; + if (!json.data.hostlist[prnt]) { + var p = json.data.hostlist[host].parent_hosts; + json.data.hostlist[host].parent_hosts.splice(0, 1); + } + } + // Update the information returned + $scope.hostList[host].objectJSON = + json.data.hostlist[host]; + } + + // Now update the host tree + var rootHosts = new Array; + for (var host in $scope.hostList) { + if ($scope.hostList[host] != null && + $scope.hostList[host].objectJSON.parent_hosts.length == 0) { + rootHosts.push(host); + } + } + updateHostTree($scope.hostTree, rootHosts); + + // Update the icon image cache + if ($scope.showIcons) { + updateImageIconCache(); + } + + // Finish the host list processing + finishProcessingHostList(); + }; + + var finishProcessingHostList = function() { + + if ($scope.showIcons && $scope.iconsLoading > 0) { + setTimeout(function() { + finishProcessingHostList() + }, 10); + return; + } + + // If this is the first time the map has + // been displayed... + if($scope.fetchingHostlist) { + // Stop the spinner + $scope.spinner.stop(); + $scope.fetchingHostlist = false; + + // Display the map + displayMap(); + } + + // Reparent the tree to specified root host + if ($scope.hostList.hasOwnProperty($scope.root) && + ($scope.rootNode != $scope.hostTree)) { + reparentTree($scope.hostList[$scope.root].hostNodes[0]); + } + + // Finally update the map + updateMap($scope.hostTree); + }; + + // Get list of all hosts + var getHostList = function() { + + var parameters = { + query: "hostlist", + formatoptions: "enumerate bitmask", + details: true + }; + + var getConfig = { + params: parameters, + withCredentials: true + }; + + // Send the JSON query + $http.get($scope.cgiurl + "objectjson.cgi?", getConfig) + .error(function(err) { + // Stop the spinner + $scope.spinner.stop(); + $scope.fetchingHostlist = false; + + console.warn(err); + }) + .success(function(json) { + // Record the last time Nagios core was started + $scope.lastNagiosStart = + json.result.program_start; + + // Record the time of the last update + $scope.lastUpdate = json.result.query_time; + + // Process the host list received + processHostList(json); + + // Get the services for each host + getServiceList(); + + // Get the status of each node + getAllStatus(0); + }) + }; + + // Get the node's stroke color + var getNodeStroke = function(hostStatus, collapsed) { + + var stroke; + + if(collapsed) { + stroke = "blue"; + } + else { + switch(hostStatus) { + case "up": + case "down": + case "unreachable": + stroke = getNodeFill(hostStatus, false); + break; + default: + stroke = "#cccccc"; + break; + } + } + + return stroke; + }; + + // Get the node's fill color + var getNodeFill = function(hostStatus, dark) { + + var fill; + + switch(hostStatus) { + case "up": + fill = dark ? "rgb(0, 105, 0)" : "rgb(0, 210, 0)"; + break; + case "down": + fill = dark ? "rgb(128, 0, 0)" : "rgb(255, 0, 0)"; + break; + case "unreachable": + fill = dark ? "rgb(64, 0, 0)" : "rgb(128, 0, 0)"; + break; + default: + switch($scope.layout) { + case layouts.UserSupplied.index: + case layouts.DepthLayers.index: + case layouts.DepthLayersVertical.index: + case layouts.CollapsedTree.index: + case layouts.CollapsedTreeVertical.index: + case layouts.BalancedTree.index: + case layouts.BalancedTreeVertical.index: + case layouts.CircularBalloon.index: + case layouts.Force.index: + fill = "#ffffff"; + break; + case layouts.CircularMarkup.index: + fill = "#cccccc"; + break; + } + break; + } + + return fill; + }; + + // Get the host status for the current node + var getHostStatus = function(d) { + + var hostStatus = "pending"; + + if(d.hasOwnProperty("hostInfo") && + d.hostInfo.hasOwnProperty("statusJSON")) { + hostStatus = d.hostInfo.statusJSON.status; + } + + return hostStatus; + }; + + // Get the service count for the current node + var getServiceCount = function(d) { + + var serviceCount = 0; + + if(d.hasOwnProperty("hostInfo") && + d.hostInfo.hasOwnProperty("serviceCount")) { + serviceCount = d.hostInfo.serviceCount; + } + + return serviceCount; + }; + + // Return the glow filter for an icon + var getGlowFilter = function(d) { + if (d.hostInfo.hasOwnProperty("statusJSON")) { + switch (d.hostInfo.statusJSON.status) { + case "up": + return "url(#icon-glow-up)"; + break; + case "down": + return "url(#icon-glow-down)"; + break; + case "unreachable": + return "url(#icon-glow-unreachable)"; + break; + default: + return null; + break; + } + } + else { + return null; + } + }; + + // Get the text filter + var getTextFilter = function(d) { + if ($scope.showIcons && + d.hostInfo.hasOwnProperty("iconInfo") && + d._children) { + return "url(#circular-markup-text-collapsed)"; + } + return null; + }; + + // Get the text stroke color + var getTextStrokeColor = function(d) { + if ($scope.showIcons && + d.hostInfo.hasOwnProperty("iconInfo") && + d._children) { + return "white"; + } + return null; + }; + + // Update the node's status + var updateNode = function(domNode) { + + var duration = 750; + + var selection = d3.select(domNode); + var data = selection.datum(); + var hostStatus = getHostStatus(data); + var serviceCount = getServiceCount(data); + + switch($scope.layout) { + case layouts.UserSupplied.index: + case layouts.DepthLayers.index: + case layouts.DepthLayersVertical.index: + case layouts.CollapsedTree.index: + case layouts.CollapsedTreeVertical.index: + case layouts.BalancedTree.index: + case layouts.BalancedTreeVertical.index: + case layouts.CircularBalloon.index: + case layouts.Force.index: + selection.select("circle") + .transition() + .duration(duration) + .attr({ + r: function() { + return $scope.nodeScale(serviceCount) + + $scope.swellRadius; + } + }) + .style({ + stroke: function() { + return getNodeStroke(hostStatus, + selection.datum().collapsed); + }, + fill: function() { + return getNodeFill(hostStatus, false); + } + }) + .transition() + .duration(duration) + .attr({ + r: $scope.nodeScale(serviceCount) + }); + + selection.select("image") + .style({ + filter: function(d) { + return getGlowFilter(d); + } + }); + + selection.select("text") + .each(function() { + setTextAttrs(data, this); + }) + .style({ + filter: function(d) { + return getTextFilter(d); + }, + stroke: function(d) { + return getTextStrokeColor(d); + } + }); + break; + case layouts.CircularMarkup.index: + selection + .transition() + .duration(duration) + .style({ + fill: function() { + return getNodeFill(hostStatus, true); + }, + "fill-opacity": 1, + "stroke-opacity": 1 + }) + .attrTween("d", arcTween) + .transition() + .duration(duration) + .style({ + fill: function() { + return getNodeFill(hostStatus, false); + } + }); + break; + } + }; + + // What to do when getAllStatus succeeds + var onGetAllStatusSuccess = function(json, since) { + + // Record the time of the last update + $scope.lastUpdate = json.result.query_time; + + // Check whether Nagios has restarted. If so + // re-read the host list + if (json.result.program_start > + $scope.lastNagiosStart) { + getHostList(); + } + else { + // Iterate over all hosts and update their status + for (var host in json.data.hostlist) { + if(!$scope.hostList[host].hasOwnProperty("statusJSON") || + ($scope.hostList[host].statusJSON.last_check < + json.data.hostlist[host].last_check)) { + $scope.hostList[host].statusJSON = + json.data.hostlist[host]; + if($scope.hostList[host].hasOwnProperty("g")) { + $scope.hostList[host].g.forEach(function(e, i, a) { + updateNode(e); + }); + } + } + } + + // Send the request for service status + getServiceStatus(since); + + // Schedule an update + statusTimeout = setTimeout(function() { + var newSince = (json.result.last_data_update / 1000) - + $scope.updateStatusInterval; + getAllStatus(newSince) }, + $scope.updateStatusInterval); + } + }; + + // Get status of all hosts and their services + var getAllStatus = function(since) { + + if ($scope.showIcons && $scope.iconsLoading > 0) { + setTimeout(function() { + getAllStatus() + }, 10); + return; + } + + var parameters = { + query: "hostlist", + formatoptions: "enumerate bitmask", + details: true, + hosttimefield: "lastcheck", + starttime: since, + endtime: "-0" + }; + + var getConfig = { + params: parameters, + withCredentials: true + }; + + // Send the request for host status + statusTimeout = null; + $http.get($scope.cgiurl + "statusjson.cgi", getConfig) + .error(function(err) { + console.warn(err); + + // Schedule an update + statusTimeout = setTimeout(function() { getAllStatus(since) }, + $scope.updateStatusInterval); + }) + .success(function(json) { + onGetAllStatusSuccess(json, since); + }) + }; + + // What to do when the getting the service status is successful + var onGetServiceStatusSuccess = function(json) { + var serviceCountUpdated = false; + + // Record the time of the last update + $scope.lastUpdate = json.result.query_time; + + for (var host in json.data.servicelist) { + var serviceStatUpdated = false; + if (!$scope.hostList[host].hasOwnProperty("serviceStatusJSON")) { + $scope.hostList[host].serviceCount = + Object.keys(json.data.servicelist[host]).length; + serviceCountUpdated = true; + $scope.hostList[host].serviceStatusJSON = new Object; + // Since this is the first time we have a + // service count if we have the host status, + // update the node(s). + if ($scope.hostList[host].hasOwnProperty("statusJSON")) { + switch ($scope.layout) { + case layouts.UserSupplied.index: + case layouts.DepthLayers.index: + case layouts.DepthLayersVertical.index: + case layouts.CollapsedTree.index: + case layouts.CollapsedTreeVertical.index: + case layouts.BalancedTree.index: + case layouts.BalancedTreeVertical.index: + case layouts.CircularBalloon.index: + case layouts.Force.index: + if($scope.hostList[host].hasOwnProperty("g")) { + $scope.hostList[host].g.forEach(function(e, i, a) { + updateNode(e); + }); + } + break; + } + } + } + else if (Object.keys($scope.hostList[host].serviceStatusJSON).length + < Object.keys(json.data.servicelist[host]).length) { + $scope.hostList[host].serviceCount = + Object.keys(json.data.servicelist[host]).length; + serviceCountUpdated = true; + } + for (service in json.data.servicelist[host]) { + if ($scope.hostList[host].serviceStatusJSON[service] != json.data.servicelist[host][service]) + serviceStatUpdated = true; + $scope.hostList[host].serviceStatusJSON[service] = + json.data.servicelist[host][service]; + } + if (serviceStatUpdated) { + $scope.hostList[host].g.forEach(function(e, i, a) { + updateNode(e); + }); + } + } + if (serviceCountUpdated) { + switch ($scope.layout) { + case layouts.CircularMarkup.index: + updateMap($scope.hostTree); + break; + } + } + }; + + // Get status of all hosts' services + var getServiceStatus = function(since) { + + var parameters = { + query: "servicelist", + formatoptions: "enumerate bitmask", + servicetimefield: "lastcheck", + starttime: since, + endtime: "-0" + }; + + var getConfig = { + params: parameters, + withCredentials: true + }; + + // Send the request for service status + $http.get($scope.cgiurl + "statusjson.cgi", getConfig) + .error(function(err) { + console.warn(err); + }) + .success(function(json) { + onGetServiceStatusSuccess(json); + }); + }; + + // Get an object attribute in a generic way that checks for + // the existence of all attributes in the hierarchy + var getObjAttr = function(d, attrs, nilval) { + + if(d.hasOwnProperty("hostInfo")) { + var obj = d.hostInfo; + for(var i = 0; i < attrs.length; i++) { + if(!obj.hasOwnProperty(attrs[i])) { + return nilval; + } + obj = obj[attrs[i]]; + } + return obj; + } + return nilval; + }; + + // Determine how long an object has been in it's + // current state + var getStateDuration = function(d) { + var now = new Date; + var duration; + var last_state_change = getObjAttr(d, + ["statusJSON", "last_state_change"], null); + var program_start = getObjAttr(d, + ["statusJSON", "result", "program_start"], + null); + if(last_state_change == null) { + return "unknown"; + } + else if(last_state_change == 0) { + duration = now.getTime() - program_start; + } + else { + duration = now.getTime() - last_state_change; + } + return duration; + }; + + // Get the display value for a state time + var getStateTime = function(time) { + var when = new Date(time); + if(when.getTime() == 0) { + return "unknown"; + } + else { + return when; + } + }; + + // Get the list of parent hosts + var getParentHosts = function(d) { + var parents = getObjAttr(d, + ["objectJSON", "parent_hosts"], null); + if(parents == null) { + return "unknown"; + } + else if(parents.length == 0) { + return "None (This is a root host)"; + } + else { + return parents.join(", "); + } + }; + + // Get the number of child hosts + var getChildHosts = function(d) { + var children = getObjAttr(d, + ["objectJSON", "child_hosts"], null); + if(children == null) { + return "unknown"; + } + else { + return children.length; + } + }; + + // Get a summary of the host's service states + var getServiceSummary = function(d) { + var states = ["ok", "warning", "unknown", "critical", + "pending"]; + var stateCounts = {}; + if(d.hostInfo.hasOwnProperty("serviceStatusJSON")) { + for (var service in d.hostInfo.serviceStatusJSON) { + var state = d.hostInfo.serviceStatusJSON[service]; + if(!stateCounts.hasOwnProperty(state)) { + stateCounts[state] = 0; + } + stateCounts[state]++; + } + } + return stateCounts; + }; + + // Set the popup contents + var setPopupContents = function(popup, d) { + + $scope.popupContents.hostname = getObjAttr(d, + ["objectJSON", "name"], "unknown"); + if($scope.popupContents.hostname == nagiosProcessName) { + var now = new Date; + $scope.popupContents.alias = nagiosProcessName; + $scope.popupContents.address = window.location.host; + $scope.popupContents.state = "up"; + $scope.popupContents.duration = now.getTime() - $scope.lastNagiosStart; + $scope.popupContents.lastcheck = $scope.lastUpdate; + $scope.popupContents.lastchange = $scope.lastNagiosStart; + $scope.popupContents.parents = ""; + $scope.popupContents.children = ""; + $scope.popupContents.services = null; + } else { + $scope.popupContents.alias = getObjAttr(d, + ["objectJSON", "alias"], "unknown"); + $scope.popupContents.address = getObjAttr(d, + ["objectJSON", "address"], "unknown"); + $scope.popupContents.state = getObjAttr(d, + ["statusJSON", "status"], "pending"); + $scope.popupContents.duration = getStateDuration(d); + $scope.popupContents.lastcheck = + getStateTime(getObjAttr(d, + ["statusJSON", "last_check"], 0)); + $scope.popupContents.lastchange = + getStateTime(getObjAttr(d, + ["statusJSON", "last_state_change"], 0)); + $scope.popupContents.parents = getParentHosts(d); + $scope.popupContents.children = getChildHosts(d); + $scope.popupContents.services = getServiceSummary(d); + } + }; + + // Update the map + var updateMap = function(source, reparent) { + reparent = reparent || false; + switch($scope.layout) { + case layouts.UserSupplied.index: + updateUserSuppliedMap(source); + break; + case layouts.DepthLayers.index: + case layouts.DepthLayersVertical.index: + case layouts.CollapsedTree.index: + case layouts.CollapsedTreeVertical.index: + case layouts.BalancedTree.index: + case layouts.BalancedTreeVertical.index: + case layouts.CircularBalloon.index: + $scope.updateDuration = 500; + updateTreeMap(source); + break; + case layouts.CircularMarkup.index: + $scope.updateDuration = 750; + updatePartitionMap(source, reparent); + break; + case layouts.Force.index: + updateForceMap(source); + break; + } + }; + + // Update all descendants of a node when collapsing the node + var updateDescendantsOnCollapse = function(root, x, y, + member) { + + // Default member to _children + member = member || "_children"; + + if(root.hasOwnProperty(member) && root[member] != + null) { + root[member].forEach(function(e, i, a) { + e.x = x; + e.dx = 0; + updateDescendantsOnCollapse(e, x, y, + "children"); + }); + } + }; + + // Update all descendants of a node when expanding the node + var updateDescendantsOnExpand = function(root, x, y, + member) { + + // Default member to _children + member = member || "_children"; + + if(root.hasOwnProperty(member) && root[member] != + null) { + root[member].forEach(function(e, i, a) { + e.saveArc.x = x; + e.saveArc.dx = 0; + e.saveArc.y = y; + e.saveArc.dy = 0; + e.saveLabel.x = x; + e.saveLabel.dx = 0; + e.saveLabel.y = y; + e.saveLabel.dy = 0; + updateDescendantsOnExpand(e, x, y, "children"); + }); + } + }; + + // Update the layout information for nodes which are/were + // children of collapsed nodes + var updateToggledNodes = function(root, updater) { + + if(root.collapsed) { + if(root.depth == 0) { + updater(root, 0, 0); + } + else { + updater(root, root.x + root.dx / 2, + root.y + root.dy / 2); + } + } + else if(root.hasOwnProperty("children")) { + root.children.forEach(function(e, i, a) { + updateToggledNodes(e, updater); + }); + } + }; + + // The on-click function for partition maps + var onClickPartition = function(d) { + + var evt = d3.event; + + // If something else (like a pan) is occurring, + // ignore the click + if(d3.event.defaultPrevented) return; + + // Hide the popup + $scope.displayPopup = false; + $scope.$apply("displayPopup"); + + if(evt.shiftKey) { + + // Record the new root + $scope.root = d.hostInfo.name; + $scope.$apply('root'); + + // A shift-click indicates a reparenting + // of the tree + if(d.collapsed) { + // If the node click is collapsed, + // expand it so the tree will have some + // depth after reparenting + toggleNode(d); + } + // Collapse the root node for good animation + toggleNode($scope.hostTree); + updateMap($scope.hostTree, true); + // Waiting until the updating is done... + setTimeout(function() { + // Re-expand the root node so the + // reparenting will occur correctly + toggleNode($scope.hostTree); + // Reparent the tree and redisplay the map + reparentTree(d); + updateMap($scope.hostTree, true); + }, $scope.updateDuration + 50); + } + else { + // A click indicates collapsing or + // expanding the node + toggleNode(d); + updateMap($scope.hostTree); + } + }; + + // Recalculate the values of the partition + var recalculatePartitionValues = function(node) { + + if(node.hasOwnProperty("children") && + node.children != null) { + node.children.forEach(function(e) { + recalculatePartitionValues(e); + }); + node.value = node.children.reduce(function(a, b) { + return a + b.value; + }, 0); + } + else { + node.value = getPartitionNodeValue(node); + } + }; + + // Recalculate the layout of the partition + var recalculatePartitionLayout = function(node, index) { + + index = index || 0; + + if(node.depth > 0) { + if(index == 0) { + node.x = node.parent.x; + } + else { + node.x = node.parent.children[index - 1].x + + node.parent.children[index - 1].dx; + } + node.dx = (node.value / node.parent.value) * + node.parent.dx + } + if(node.hasOwnProperty("children") && + node.children != null) { + node.children.forEach(function(e, i) { + recalculatePartitionLayout(e, i); + }); + } + }; + + // Text filter for labels + var textFilter = function(d) { + return d.collapsed ? + "url(#circular-markup-text-collapsed)" : + "url(#circular-markup-text)"; + } + + var addPartitionMapTextGroupContents = function(d, node) { + var selection = d3.select(node); + + // Append the label + if($scope.showText) { + selection.append("text") + .each(function(d) { + setTextAttrs(d, this); + }) + .style({ + "fill-opacity": 1e-6, + fill: "white", + filter: function(d) { + return textFilter(d); + } + }) + .text(function(d) { + return d.hostInfo.objectJSON.name; + }); + } + + // Display the node icon if it has one + if($scope.showIcons) { + var image = d.hostInfo.objectJSON.icon_image; + if (image != "" && image != undefined) { + var iconInfo = d.hostInfo.iconInfo; + selection.append("image") + .attr({ + "xlink:href": $scope.iconurl + image, + width: iconInfo.width, + height: iconInfo.height, + x: -(iconInfo.width / 2), + y: -((iconInfo.height + + layouts.CircularMarkup.textPadding + + $scope.fontSize) / 2), + transform: function() { + var rotateAngle = (d.x + d.dx / 2) * + 180 / Math.PI + + layouts.CircularBalloon.rotation; + return "rotate(" + -rotateAngle + ")"; + } + }) + .style({ + filter: function() { + return getGlowFilter(d); + } + }); + } + } + }; + + // Update the map for partition displays + var updatePartitionMap = function(source, reparent) { + + // The svg element that holds it all + var mapsvg = d3.select("svg#map g#container"); + + // The data for the map + var mapdata = $scope.partition.nodes(source); + + if(reparent) { + if($scope.hostTree.collapsed) { + // If this is a reparent operation and + // we're in the collapse phase, shrink + // the root node to nothing + $scope.hostTree.x = 0; + $scope.hostTree.dx = 0; + $scope.hostTree.y = 0; + $scope.hostTree.dy = 0; + } + else { + // Calculate the total value of the 1st level + // children to determine whether we have + // the bug below + var value = $scope.hostTree.children.reduce(function(a, b) { + return a + b.value; + }, 0); + if(value == 2 * $scope.hostTree.value) { + // This appears to be a bug in the + // d3 library where the sum of the + // values of the children of the root + // node is twice what it should be. + // Work around the bug by manually + // adjusting the values. + recalculatePartitionValues($scope.hostTree); + recalculatePartitionLayout($scope.hostTree); + } + } + } + + // Update the data for the paths + var path = mapsvg + .select("g#paths") + .selectAll("path") + .data(mapdata, function(d) { + return d.id || (d.id = ++$scope.nodeID); + }); + + // Update the data for the labels + var labelGroup = mapsvg + .selectAll("g.label") + .data(mapdata, function(d) { + return d.id || (d.id = ++$scope.nodeID); + }); + + // Traverse the data, artificially setting the layout + //for collapsed children + updateToggledNodes($scope.hostTree, + updateDescendantsOnCollapse); + + var pathEnter = path.enter() + .append("path") + .attr({ + d: function(d) { + return $scope.arc({x: 0, dx: 0, y: d.y, + dy: d.dy}); + } + }) + .style({ + "fill-opacity": 1e-6, + "stroke-opacity": 1e-6, + stroke: "#fff", + fill: function(d) { + var hostStatus = "pending"; + if(d.hasOwnProperty("hostInfo") && + d.hostInfo.hasOwnProperty("statusJSON")) { + hostStatus = d.hostInfo.statusJSON.status; + } + return getNodeFill(hostStatus, false); + } + }) + .on("click", function(d) { + onClickPartition(d); + }) + .each(function(d) { + // Traverse each node, saving a pointer + // to the node in the hostList to + // facilitate updating later + if(d.hasOwnProperty("hostInfo")) { + if(!d.hostInfo.hasOwnProperty("g")) { + d.hostInfo.g = new Array; + } + d.hostInfo.g.push(this); + } + }); + + if ($scope.showPopups) { + pathEnter + .on("mouseover", function(d, i) { + if($scope.showPopups && + d.hasOwnProperty("hostInfo")) { + displayPopup(d); + } + }) + .on("mouseout", function(d, i) { + $scope.displayPopup = false; + $scope.$apply("displayPopup"); + }); + } + + labelGroup.enter() + .append("g") + .attr({ + class: "label", + transform: function(d) { + return "translate(" + + $scope.arc.centroid({x: 0, + dx: 1e-6, y: d.y, dy: d.dy}) + + ")"; + } + }) + .each(function(d) { + addPartitionMapTextGroupContents(d, this); + }); + + // Update paths on changes + path.transition() + .duration($scope.updateDuration) + .style({ + "fill-opacity": 1, + "stroke-opacity": 1, + fill: function(d) { + var hostStatus = "pending"; + if(d.hasOwnProperty("hostInfo") && + d.hostInfo.hasOwnProperty("statusJSON")) { + hostStatus = + d.hostInfo.statusJSON.status; + } + return getNodeFill(hostStatus, false); + } + }) + .attrTween("d", arcTween); + + // Update label groups on change + labelGroup + .transition() + .duration($scope.updateDuration) + .attrTween("transform", labelGroupTween); + + if($scope.showText) { + labelGroup + .selectAll("text") + .style({ + "fill-opacity": 1, + filter: function(d) { + return textFilter(d); + } + }) + .each(function(d) { + setTextAttrs(d, this); + }); + } + + if($scope.showIcons) { + labelGroup + .selectAll("image") + .attr({ + transform: function(d) { + var rotateAngle = (d.x + d.dx / 2) * 180 / Math.PI + + layouts.CircularBalloon.rotation; + return "rotate(" + -rotateAngle + ")"; + } + }); + } + + // Remove paths when necessary + path.exit() + .transition() + .duration($scope.updateDuration) + .style({ + "fill-opacity": 1e-6, + "stroke-opacity": 1e-6 + }) + .attrTween("d", arcTween) + .remove(); + + // Remove labels when necessary + if($scope.showText) { + var labelGroupExit = labelGroup.exit(); + + labelGroupExit.each(function(d) { + var group = d3.select(this); + + group.select("text") + .transition() + .duration($scope.updateDuration / 2) + .style({ + "fill-opacity": 1e-6 + }); + + group.select("image") + .transition() + .duration($scope.updateDuration) + .style({ + "fill-opacity": 1e-6 + }); + + }) + .transition() + .duration($scope.updateDuration) + .attrTween("transform", labelGroupTween) + .remove(); + } + }; + + // Traverse the tree, building a list of nodes at each depth + var updateDepthList = function(node) { + + if($scope.depthList[node.depth] == null) { + $scope.depthList[node.depth] = new Array; + } + $scope.depthList[node.depth].push(node); + + if(node.hasOwnProperty("children") && + node.children != null) { + node.children.forEach(function(e) { + updateDepthList(e); + }); + } + }; + + // Calculate the layout for the collapsed tree + var calculateCollapsedTreeLayout = function(root) { + + // First get the list of nodes at each depth + $scope.depthList = new Array; + updateDepthList(root); + + // Then determine the widest layer + var maxWidth = $scope.depthList.reduce(function(a, b) { + return a > b.length ? a : b.length; + }, 0); + + // Determine the spacing of nodes based on the max width + var treeSize = getTreeSize(); + var spacing = treeSize[0] / maxWidth; + + // Re-calculate the layout based on the above + $scope.depthList.forEach(function(layer, depth) { + layer.forEach(function(node, index) { + // Calculate the location index: the + // "index distance" from the center node + var locationIndex = + (index - (layer.length - 1) / 2); + node.x = (treeSize[0] / 2) + + (locationIndex * spacing); + }); + }); + }; + + // The on-click function for trees + var onClickTree = function(d) { + + var evt = d3.event; + var updateNode = d; + + // If something else (like a pan) is occurring, + // ignore the click + if(d3.event.defaultPrevented) return; + + // Hide the popup + $scope.displayPopup = false; + $scope.$apply("displayPopup"); + + if(evt.shiftKey) { + // Record the new root + $scope.root = d.hostInfo.name; + $scope.$apply('root'); + + switch($scope.layout) { + case layouts.DepthLayers.index: + case layouts.DepthLayersVertical.index: + // Expand the children of the focal point + $scope.focalPoint.children.forEach(function(e) { + if(e.collapsed) { + toggleNode(e); + } + }); + // If the focal point is not the root node, + // restore all children of it's parent + if(!($scope.focalPoint === $scope.hostTree)) { + $scope.focalPoint.parent.children = + $scope.focalPoint.parent._children; + delete $scope.focalPoint.parent._children; + $scope.focalPoint.parent.collapsed = false; + } + break; + default: + if(d.collapsed) { + // If the node click is collapsed, + // expand it so the tree will have + // some depth after reparenting + toggleNode(d); + } + break; + } + reparentTree(d); + } + else { + switch($scope.layout) { + case layouts.DepthLayers.index: + case layouts.DepthLayersVertical.index: + if((d === $scope.focalPoint) || + !(d.hasOwnProperty("children") || + d.hasOwnProperty("_children"))) { + // Nothing to see here, move on + return; + } + // Restore all the children of the current focal + // point and it's parent (if it is not the root + // of the tree) + $scope.focalPoint.children.forEach(function(e) { + if(e.collapsed) { + toggleNode(e); + } + }); + if(!($scope.focalPoint === $scope.hostTree)) { + $scope.focalPoint.parent.children = + $scope.focalPoint.parent._children; + $scope.focalPoint.parent._children = null; + $scope.focalPoint.parent.collapsed = false; + } + // Set the new focal point + $scope.focalPoint = d; + updateNode = (d === $scope.hostTree) ? d : + d.parent; + break; + default: + toggleNode(d); + break; + } + } + updateMap(updateNode); + }; + + // Add a node group to the tree map + var addTreeMapNodeGroupContents = function(d, node) { + var selection = d3.select(node); + + // Display the circle if the node has no icon or + // icons are suppressed + if(!$scope.showIcons || + d.hostInfo.objectJSON.icon_image == "") { + selection.append("circle") + .attr({ + r: 1e-6 + }); + } + + // Display the node icon if it has one + if($scope.showIcons) { + var image = d.hostInfo.objectJSON.icon_image; + if (image != "" && image != undefined) { + var iconInfo = d.hostInfo.iconInfo; + var rotateAngle = null; + if ($scope.layout == layouts.CircularBalloon.index) { + rotateAngle = d.x + + layouts.CircularBalloon.rotation; + } + selection.append("image") + .attr({ + "xlink:href": $scope.iconurl + image, + width: iconInfo.width, + height: iconInfo.height, + x: -(iconInfo.width / 2), + y: -(iconInfo.height / 2), + transform: function() { + return "rotate(" + -rotateAngle + ")"; + } + }) + .style({ + filter: function() { + return getGlowFilter(d); + } + }); + } + } + + // Label the nodes with their host names + if($scope.showText) { + selection.append("text") + .each(function(d) { + setTextAttrs(d, this); + }) + .style({ + "fill-opacity": 1e-6 + }) + .text(function(d) { + return d.hostInfo.objectJSON.name; + }); + } + + // Register event handlers for showing the popups + if($scope.showPopups) { + selection + .on("mouseover", function(d, i) { + if(d.hasOwnProperty("hostInfo")) { + displayPopup(d); + } + }) + .on("mouseout", function(d, i) { + $scope.displayPopup = false; + $scope.$apply("displayPopup"); + }); + } + + }; + + // Update the tree map + var updateTreeMap = function(source) { + + var textAttrs; + + // The svg element that holds it all + var mapsvg = d3.select("svg#map g#container"); + + // Build the nodes from the data + var nodes; + switch($scope.layout) { + case layouts.DepthLayers.index: + case layouts.DepthLayersVertical.index: + // If this is a depth layer layout, first update the + // tree based on the current focused node, + updateDepthLayerTree(); + // then build the nodes from the data + var root = ($scope.focalPoint === $scope.hostTree) ? + $scope.hostTree : $scope.focalPoint.parent; + nodes = $scope.tree.nodes(root).reverse(); + break; + case layouts.CollapsedTree.index: + case layouts.CollapsedTreeVertical.index: + // If this is a collapsed tree layout, + // first build the nodes from the data, + nodes = $scope.tree.nodes($scope.hostTree).reverse(); + // then re-calculate the positions of the nodes + calculateCollapsedTreeLayout($scope.hostTree); + break; + default: + nodes = $scope.tree.nodes($scope.hostTree).reverse(); + break; + } + + // ...and the links from the nodes + var links = $scope.tree.links(nodes); + + // Create the groups to contain the nodes + var node = mapsvg.selectAll(".node") + .data(nodes, function(d) { + return d.id || (d.id = ++$scope.nodeID); + }); + + if($scope.showLinks) { + // Create the paths for the links + var link = mapsvg + .select("g#links") + .selectAll(".link") + .data(links, function(d) { return d.target.id; }); + + // Enter any new links at the parent's + // previous position. + link.enter() + .append("path") + .attr({ + class: "link", + d: function(d) { + var o = { + x: (source.hasOwnProperty("xOld") ? + source.xOld : source.x) * + $scope.zoom.scale(), + y: (source.hasOwnProperty("yOld") ? + source.yOld : source.y) * + $scope.zoom.scale() + }; + return $scope.diagonal({source: o, + target: o}); + } + }) + .transition() + .duration($scope.updateDuration) + .attr({ + d: $scope.diagonal + }); + + // Transition links to their new position. + link.transition() + .duration($scope.updateDuration) + .attr({ + d: $scope.diagonal + }); + + // Transition exiting nodes to the parent's + // new position. + link.exit().transition() + .duration($scope.updateDuration) + .attr({ + d: function(d) { + var o = { + x: source.x * $scope.zoom.scale(), + y: source.y * $scope.zoom.scale() + }; + return $scope.diagonal({source: o, + target: o}); + } + }) + .remove(); + } + + // Enter any new nodes at the parent's + // previous position. + var nodeEnter = node.enter() + .append("g") + .attr({ + class: "node", + transform: function(d) { + return getNodeTransform(source); + } + }) + .on("click", function(d) { + onClickTree(d); + }) + .each(function(d) { + // Traverse each node, saving a pointer to + // the node in the hostList to facilitate + // updating later + if(d.hasOwnProperty("hostInfo")) { + if(!d.hostInfo.hasOwnProperty("g")) { + d.hostInfo.g = new Array; + } + d.hostInfo.g.push(this); + } + addTreeMapNodeGroupContents(d, this); + }); + + // Move the nodes to their final destination + var nodeUpdate = node.transition() + .duration($scope.updateDuration) + .attr({ + transform: function(d) { + return getNodeTransform(d); + } + }); + + // Update the node's circle size + nodeUpdate.select("circle") + .attr({ + r: function(d) { + var serviceCount = 0; + if(d.hasOwnProperty("hostInfo") && + d.hostInfo.hasOwnProperty("serviceCount")) { + serviceCount = d.hostInfo.serviceCount; + } + return $scope.nodeScale(serviceCount); + } + }) + .style({ + stroke: function(d) { + var hostStatus = "pending"; + if(d.hasOwnProperty("hostInfo") && + d.hostInfo.hasOwnProperty("statusJSON")) { + hostStatus = + d.hostInfo.statusJSON.status; + } + return getNodeStroke(hostStatus, + d.collapsed); + }, + fill: function(d) { + var hostStatus = "pending"; + if(d.hasOwnProperty("hostInfo") && + d.hostInfo.hasOwnProperty("statusJSON")) { + hostStatus = d.hostInfo.statusJSON.status; + } + return getNodeFill(hostStatus, false); + }, + }); + + // Update the images' filters + nodeUpdate.select("image") + .style({ + filter: function(d) { + return getGlowFilter(d); + } + }); + + // Update the text's opacity + nodeUpdate.select("text") + .each(function(d) { + setTextAttrs(d, this); + }) + .style({ + "fill-opacity": 1, + filter: function(d) { + return getTextFilter(d); + }, + stroke: function(d) { + return getTextStrokeColor(d); + } + }); + + // Transition exiting nodes to the parent's + // new position. + var nodeExit = node.exit().transition() + .duration($scope.updateDuration) + .attr({ + transform: function(d) { + return getNodeTransform(source); + } + }) + .remove(); + + nodeExit.select("circle") + .attr({ + r: 1e-6 + }); + + nodeExit.select("text") + .style({ + "fill-opacity": 1e-6 + }); + + // Update all nodes associated with the source + if(source.hasOwnProperty("hostInfo") && + source.hostInfo.hasOwnProperty("g")) { + source.hostInfo.g.forEach(function(e, i, a) { + updateNode(e); + }); + } + + // Save the old positions for the next transition. + nodes.forEach(function(e) { + e.xOld = e.x; + e.yOld = e.y; + }); + }; + + // Update the tree for the depth layer layout + var updateDepthLayerTree = function() { + + // In a depth layer layout, the focal point node is the + // center of the universe; show only it, it's children + // and it's parent (if the focal point node is not the + // root node). + if(!($scope.focalPoint === $scope.hostTree)) { + // For all cases except where the focal point is the + // root node make the focal point the only child of + // it's parent + $scope.focalPoint.parent._children = + $scope.focalPoint.parent.children; + $scope.focalPoint.parent.children = new Array; + $scope.focalPoint.parent.children.push($scope.focalPoint); + $scope.focalPoint.parent.collapsed = true; + } + // Collapse all the children of the focal point + if($scope.focalPoint.hasOwnProperty("children") && + $scope.focalPoint.children != null) { + $scope.focalPoint.children.forEach(function(e) { + if(!e.collapsed && + e.hasOwnProperty("children") && + (e.children.length > 0)) { + toggleNode(e); + } + }); + } + }; + + var addUserSuppliedNodeGroupContents = function(d, node) { + var selection = d3.select(node); + + // Display the circle if the node has no icon or + // icons are suppressed + if(!$scope.showIcons || + d.hostInfo.objectJSON.icon_image == "") { + selection.append("circle") + .attr({ + r: 1e-6 + }); + } + + // Display the node icon if it has one + if($scope.showIcons) { + var image = d.hostInfo.objectJSON.icon_image; + if (image != "" && image != undefined) { + var iconInfo = d.hostInfo.iconInfo + selection.append("image") + .attr({ + "xlink:href": $scope.iconurl + image, + width: iconInfo.width, + height: iconInfo.height, + x: -(iconInfo.width / 2), + y: -(iconInfo.height / 2), + }) + .style({ + filter: function() { + return getGlowFilter(d); + } + }); + } + } + + // Label the nodes with their host names + if($scope.showText) { + selection.append("text") + .each(function(d) { + setTextAttrs(d, this); + }) + .text(function(d) { + return d.hostInfo.objectJSON.name; + }); + } + + // Register event handlers for showing the popups + if($scope.showPopups) { + selection + .on("mouseover", function(d, i) { + if(d.hasOwnProperty("hostInfo")) { + displayPopup(d); + } + }) + .on("mouseout", function(d, i) { + $scope.displayPopup = false; + $scope.$apply("displayPopup"); + }); + } + }; + + // Update the map that uses configuration-specified + // coordinates + var updateUserSuppliedMap = function(source) { + + // Update the scales + calculateUserSuppliedDimensions(); + userSuppliedLayout.xScale + .domain([userSuppliedLayout.dimensions.upperLeft.x, + userSuppliedLayout.dimensions.lowerRight.x]); + userSuppliedLayout.yScale + .domain([userSuppliedLayout.dimensions.upperLeft.y, + userSuppliedLayout.dimensions.lowerRight.y]); + + // The svg element that holds it all + var mapsvg = d3.select("svg#map g#container"); + + // Convert the host list into an array + var mapdata = new Array; + for(host in $scope.hostList) { + if(host != null) { + var tmp = new Object; + tmp.hostInfo = $scope.hostList[host]; + mapdata.push(tmp); + } + } + + // Update the data for the nodes + var node = mapsvg + .selectAll("g.node") + .data(mapdata); + + var nodeEnter = node.enter() + .append("g") + .attr({ + class: "node", + transform: function(d) { + return getNodeTransform(d); + } + }) + .each(function(d) { + // Traverse each node, saving a pointer + // to the node in the hostList to + // facilitate updating later + if(d.hasOwnProperty("hostInfo")) { + if(!d.hostInfo.hasOwnProperty("g")) { + d.hostInfo.g = new Array; + } + d.hostInfo.g.push(this); + } + addUserSuppliedNodeGroupContents(d, this); + }); + }; + + // Tick function for force layout + var onForceTick = function(source) { + + if($scope.showLinks) { + forceLayout.link + .attr({ + x1: function(d) { + return $scope.xZoomScale(d.source.x); + }, + y1: function(d) { + return $scope.yZoomScale(d.source.y); + }, + x2: function(d) { + return $scope.xZoomScale(d.target.x); + }, + y2: function(d) { + return $scope.yZoomScale(d.target.y); + } + }); + } + + forceLayout.node + .attr({ + transform: function(d) { + return "translate(" + + $scope.xZoomScale(d.x) + ", " + + $scope.yZoomScale(d.y) + ")"; + } + }); + }; + + // Flatten the map + var flattenMap = function(root) { + var nodes = [], i = 0; + + function recurse(node, depth) { + if(node.children) node.children.forEach(function(e) { + recurse(e, depth + 1); + }); + if(!node.id) node.id = ++i; + node.depth = depth; + nodes.push(node); + } + + recurse(root, 0); + return nodes; + }; + + // Handle a click on a node in the force tree + var onClickForce = function(d) { + + // Hide the popup + $scope.displayPopup = false; + $scope.$apply("displayPopup"); + + // Note: reparenting the tree is not implemented + // because the map doesn't appear any different + // after reparenting. However, reparenting would + // affect what is collapsed/expanded when an + // interior node is click, so it eventually may + // make sense. + toggleNode(d); + updateMap(d); + }; + + // Add the components to the force map node group + var addForceMapNodeGroupContents = function(d, node) { + var selection = d3.select(node); + + if(!$scope.showIcons || + d.hostInfo.objectJSON.icon_image == "") { + selection.append("circle") + .attr({ + r: $scope.minRadius + }); + } + + // Display the node icon if it has one + if ($scope.showIcons) { + var image = d.hostInfo.objectJSON.icon_image; + if (image != "" && image != undefined) { + var iconInfo = d.hostInfo.iconInfo; + var rotateAngle = null; + if ($scope.layout == layouts.CircularBalloon.index) { + rotateAngle = d.x + + layouts.CircularBalloon.rotation; + } + selection.append("image") + .attr({ + "xlink:href": $scope.iconurl + image, + width: iconInfo.width, + height: iconInfo.height, + x: -(iconInfo.width / 2), + y: -(iconInfo.height / 2), + transform: function() { + return "rotate(" + -rotateAngle + ")"; + } + }) + .style({ + filter: function() { + return getGlowFilter(d); + } + }); + } + } + + if ($scope.showText) { + selection.append("text") + .each(function(d) { + setTextAttrs(d, this); + }) + .text(function(d) { + return d.hostInfo.objectJSON.name; + }) + .style({ + filter: function(d) { + return getTextFilter(d); + }, + stroke: function(d) { + return getTextStrokeColor(d); + } + }); + } + + if ($scope.showPopups) { + selection + .on("click", function(d) { + onClickForce(d); + }) + .on("mouseover", function(d) { + if($scope.showPopups) { + if(d.hasOwnProperty("hostInfo")) { + displayPopup(d); + } + } + }) + .on("mouseout", function(d) { + $scope.displayPopup = false; + $scope.$apply("displayPopup"); + }); + } + + }; + + // Update the force map + var updateForceMap = function(source) { + + // How long must we wait + var duration = 750; + + // The svg element that holds it all + var mapsvg = d3.select("svg#map g#container"); + + // Build the nodes from the data + var nodes = flattenMap($scope.hostTree); + + // ...and the links from the nodes + var links = d3.layout.tree().links(nodes); + + // Calculate the force parameters + var maxDepth = nodes.reduce(function(a, b) { + return a > b.depth ? a : b.depth; + }, 0); + var diameter = Math.min($scope.svgHeight - + 2 * layouts.Force.outsidePadding, + $scope.svgWidth - + 2 * layouts.Force.outsidePadding); + var distance = diameter / (maxDepth * 2); + var charge = -30 * (Math.pow(distance, 1.2) / 20); + + // Restart the force layout. + $scope.force + .linkDistance(distance) + .charge(charge) + .nodes(nodes) + .links(links) + .start(); + + if($scope.showLinks) { + // Create the lines for the links + forceLayout.link = mapsvg.select("g#links") + .selectAll(".link") + .data(links, function(d) { return d.target.id; }); + + // Create new links + forceLayout.link.enter() + .append("line") + .attr({ + class: "link", + x1: function(d) { + return $scope.xZoomScale(d.source.x); + }, + y1: function(d) { + return $scope.yZoomScale(d.source.y); + }, + x2: function(d) { + return $scope.xZoomScale(d.target.x); + }, + y2: function(d) { + return $scope.yZoomScale(d.target.y); + } + }); + + // Remove any old links. + forceLayout.link.exit().remove(); + } + + // Create the nodes from the data + forceLayout.node = mapsvg.selectAll("g.node") + .data(nodes, function(d) { return d.id; }); + + // Exit any old nodes. + forceLayout.node.exit().remove(); + + // Create any new nodes + var nodeEnter = forceLayout.node.enter() + .append("g") + .attr({ + class: "node", + transform: function(d) { + return "translate(" + + $scope.xZoomScale(d.x) + ", " + + $scope.yZoomScale(d.y) + ")"; + } + }) + .each(function(d) { + // Traverse each node, saving a pointer + // to the node in the hostList to + // facilitate updating later + if(d.hasOwnProperty("hostInfo")) { + if(!d.hostInfo.hasOwnProperty("g")) { + d.hostInfo.g = new Array; + } + d.hostInfo.g.push(this); + } + addForceMapNodeGroupContents(d, this); + }) + .call($scope.force.drag); + + // Update existing nodes + forceLayout.node + .select("circle") + .transition() + .duration(duration) + .attr({ + r: function(d) { + return $scope.nodeScale(getServiceCount(d)); + } + }) + .style({ + stroke: function(d) { + return getNodeStroke(getHostStatus(d), + d.collapsed); + }, + fill: function(d) { + return getNodeFill(getHostStatus(d), false); + } + }); + + forceLayout.node + .select("text") + .style({ + filter: function(d) { + return getTextFilter(d); + }, + stroke: function(d) { + return getTextStrokeColor(d); + } + }); + }; + + // Create the value function + var getPartitionNodeValue = function(d) { + + if(d.hasOwnProperty("hostInfo") && + d.hostInfo.hasOwnProperty("serviceCount")) { + return d.hostInfo.serviceCount == 0 ? 1 : + d.hostInfo.serviceCount; + } + else { + return 1; + } + }; + + // Calculate the dimensions for the user supplied layout + var calculateUserSuppliedDimensions = function() { + + switch ($scope.dimensions) { + case "auto": + // Create a temporary array with pointers + // to the object JSON data + ojdata = new Array; + for(var host in $scope.hostList) { + if(host != null) { + ojdata.push($scope.hostList[host].objectJSON); + } + } + // Determine dimensions based on included objects + userSuppliedLayout.dimensions.upperLeft.x = + ojdata[0].x_2d; + userSuppliedLayout.dimensions.upperLeft.x = + ojdata.reduce(function(a, b) { + return a < b.x_2d ? a : b.x_2d; + }); + userSuppliedLayout.dimensions.upperLeft.y = + ojdata[0].y_2d; + userSuppliedLayout.dimensions.upperLeft.y = + ojdata.reduce(function(a, b) { + return a < b.y_2d ? a : b.y_2d; + }); + userSuppliedLayout.dimensions.lowerRight.x = + ojdata[0].x_2d; + userSuppliedLayout.dimensions.lowerRight.x = + ojdata.reduce(function(a, b) { + return a > b.x_2d ? a : b.x_2d; + }); + userSuppliedLayout.dimensions.lowerRight.y = + ojdata[0].y_2d; + userSuppliedLayout.dimensions.lowerRight.y = + ojdata.reduce(function(a, b) { + return a > b.y_2d ? a : b.y_2d; + }); + break; + case "fixed": + userSuppliedLayout.dimensions.upperLeft.x = 0; + userSuppliedLayout.dimensions.upperLeft.y = 0; + userSuppliedLayout.dimensions.lowerRight.x = + $scope.svgWidth; + userSuppliedLayout.dimensions.lowerRight.y = + $scope.svgHeight; + break; + case "user": + userSuppliedLayout.dimensions.upperLeft.x = + $scope.ulx; + userSuppliedLayout.dimensions.upperLeft.y = + $scope.uly; + userSuppliedLayout.dimensions.lowerRight.x = + $scope.lrx; + userSuppliedLayout.dimensions.lowerRight.y = + $scope.lry; + break; + } + }; + + // What to do when the resize handle is dragged + var onResizeDrag = function() { + + // Get the drag event + var event = d3.event; + + // Resize the div + $scope.svgWidth = event.x; + $scope.svgHeight = event.y; + + // Propagate changes to parent scope (so, for example, + // menu icon is redrown immediately). Note that it + // doesn't seem to matter what we apply, so the + // empty string is applied to decouple this directive + // from it's parent's scope. + $scope.$parent.$apply(""); + + updateOnResize(this); + }; + + var updateOnResize = function(resizeHandle) { + d3.select("div#mapsvg") + .style({ + height: function() { + return $scope.svgHeight + "px"; + }, + width: function() { + return $scope.svgWidth + "px"; + } + }) + $scope.diameter = Math.min($scope.svgHeight, + $scope.svgWidth); + + // Update the scales + switch($scope.layout) { + case layouts.UserSupplied.index: + switch($scope.dimensions) { + case "auto": + userSuppliedLayout.xScale.range([0 + + layouts.UserSupplied.padding.left, + $scope.svgWidth - + layouts.UserSupplied.padding.right]); + userSuppliedLayout.yScale.range([0 + + layouts.UserSupplied.padding.top, + $scope.svgHeight - + layouts.UserSupplied.padding.bottom]); + break; + case "fixed": + userSuppliedLayout.dimensions.lowerRight.x = + $scope.svgWidth; + userSuppliedLayout.dimensions.lowerRight.y = + $scope.svgHeight; + // no break; + case "user": + userSuppliedLayout.xScale.range([0, + $scope.svgWidth]); + userSuppliedLayout.yScale.range([0, + $scope.svgHeight]); + break; + } + break; + } + + // Resize the svg + d3.select("svg#map") + .style({ + height: $scope.svgHeight, + width: $scope.svgWidth + }) + + // Update the container transform + d3.select("svg#map g#container") + .attr({ + transform: function() { + return getContainerTransform(); + } + }); + + // Update the appropriate layout + switch($scope.layout) { + case layouts.DepthLayers.index: + case layouts.DepthLayersVertical.index: + case layouts.CollapsedTree.index: + case layouts.CollapsedTreeVertical.index: + case layouts.BalancedTree.index: + case layouts.BalancedTreeVertical.index: + case layouts.CircularBalloon.index: + // Update the tree size + $scope.tree.size(getTreeSize()) + break; + case layouts.CircularMarkup.index: + // Update the partition size + var radius = $scope.diameter / 2 - + layouts.CircularMarkup.padding; + var exponent = layouts.CircularMarkup.radialExponent; + $scope.partition.size([2 * Math.PI, + Math.pow(radius, exponent)]); + break; + case layouts.Force.index: + $scope.force.size([$scope.svgWidth - + 2 * layouts.Force.outsidePadding, + $scope.svgHeight - + 2 * layouts.Force.outsidePadding]); + break; + } + + // Move the resize handle + if($scope.allowResize) { + d3.select(resizeHandle) + .attr({ + transform: function() { + x = $scope.svgWidth - + ($scope.handleWidth + + $scope.handlePadding); + y = $scope.svgHeight - + ($scope.handleHeight + + $scope.handlePadding); + return "translate(" + x + ", " + + y + ")"; + } + }); + } + + // Update the contents + switch($scope.layout) { + case layouts.UserSupplied.index: + d3.selectAll("g.node circle") + .attr({ + transform: function(d) { + return getNodeTransform(d); + } + }); + d3.selectAll("g.node text") + .each(function(d) { + setTextAttrs(d, this); + }); + break; + case layouts.DepthLayers.index: + case layouts.DepthLayersVertical.index: + case layouts.CollapsedTree.index: + case layouts.CollapsedTreeVertical.index: + case layouts.BalancedTree.index: + case layouts.BalancedTreeVertical.index: + case layouts.CircularBalloon.index: + $scope.updateDuration = 0; + updateTreeMap($scope.hostTree); + break; + case layouts.CircularMarkup.index: + $scope.updateDuration = 0; + updatePartitionMap($scope.hostTree); + break; + case layouts.Force.index: + updateForceMap($scope.hostTree); + break; + } + }; + + // Set up the resize function + setupResize = function() { + + // Create the drag behavior + var drag = d3.behavior.drag() + .origin(function() { + return { x: $scope.svgWidth, + y: $scope.svgHeight }; + }) + .on("dragstart", function() { + // silence other listeners + d3.event.sourceEvent.stopPropagation(); + }) + .on("drag", onResizeDrag); + + // Create the resize handle + d3.select("svg#map") + .append("g") + .attr({ + id: "resize-handle", + transform: function() { + x = $scope.svgWidth - ($scope.handleWidth + + $scope.handlePadding); + y = $scope.svgHeight - + ($scope.handleHeight + + $scope.handlePadding); + return "translate(" + x + ", " + y + ")"; + } + }) + .call(drag) + .append("path") + .attr({ + d: function() { + return "M 0 " + $scope.handleHeight + + " L " + $scope.handleWidth + " " + + $scope.handleHeight + " L " + + $scope.handleWidth + " " + 0 + + " L " + 0 + " " + + $scope.handleHeight; + }, + stroke: "black", + fill: "black" + }); + }; + + // Get the node container transform + getContainerTransform = function() { + + switch($scope.layout) { + case layouts.UserSupplied.index: + case layouts.Force.index: + return null; + break; + case layouts.DepthLayers.index: + return "translate(0, " + + layouts.DepthLayers.topPadding + ")"; + break; + case layouts.DepthLayersVertical.index: + return "translate(" + + layouts.DepthLayersVertical.leftPadding + + ", 0)"; + break; + case layouts.CollapsedTree.index: + return "translate(0, " + + layouts.CollapsedTree.topPadding + + ")"; + break; + case layouts.CollapsedTreeVertical.index: + return "translate(" + + layouts.CollapsedTreeVertical.leftPadding + + ", 0)"; + break; + case layouts.BalancedTree.index: + return "translate(0, " + + layouts.BalancedTree.topPadding + ")"; + break; + case layouts.BalancedTreeVertical.index: + return "translate(" + + layouts.BalancedTreeVertical.leftPadding + + ", 0)"; + break; + case layouts.CircularBalloon.index: + case layouts.CircularMarkup.index: + var zoomTranslate = $scope.zoom.translate(); + var zoomScale = $scope.zoom.scale(); + var translate = [zoomTranslate[0] + + ($scope.svgWidth / 2) * zoomScale, + zoomTranslate[1] + + ($scope.svgHeight / 2) * zoomScale]; + return "transform", "translate(" + translate + + ") scale(" + zoomScale + ")"; + break; + default: + return null; + break; + } + }; + + // Display the map + var displayMap = function() { + + displayMapDone = false; + + // Update the scales + switch($scope.layout) { + case layouts.UserSupplied.index: + switch($scope.dimensions) { + case "auto": + userSuppliedLayout.xScale + .range([0 + + layouts.UserSupplied.padding.left, + $scope.svgWidth - + layouts.UserSupplied.padding.right]); + userSuppliedLayout.yScale + .range([0 + + layouts.UserSupplied.padding.top, + $scope.svgHeight - + layouts.UserSupplied.padding.bottom]); + break; + case "fixed": + case "user": + userSuppliedLayout.xScale + .range([0, $scope.svgWidth]); + userSuppliedLayout.yScale + .range([0, $scope.svgHeight]); + break; + } + break; + } + + // Resize the svg + d3.select("svg#map") + .style({ + height: $scope.svgHeight, + width: $scope.svgWidth + }); + + var container = d3.select("g#container"); + + // Build the appropriate layout + switch($scope.layout) { + case layouts.DepthLayers.index: + case layouts.DepthLayersVertical.index: + case layouts.CollapsedTree.index: + case layouts.CollapsedTreeVertical.index: + case layouts.BalancedTree.index: + case layouts.BalancedTreeVertical.index: + case layouts.CircularBalloon.index: + // Append a group for the links + container.append("g") + .attr({ + id: "links" + }); + + // Build the tree + var treeSize = getTreeSize(); + $scope.tree = d3.layout.tree() + .size(treeSize) + .separation(function(a, b) { + switch($scope.layout) { + case layouts.DepthLayers.index: + case layouts.DepthLayersVertical.index: + case layouts.CollapsedTree.index: + case layouts.CollapsedTreeVertical.index: + case layouts.BalancedTree.index: + case layouts.BalancedTreeVertical.index: + return a.parent == b.parent ? 1 : 2; + break; + case layouts.CircularBalloon.index: + var d = a.depth > 0 ? a.depth : b.depth, sep; + if (d <= 0) + d = 1; + sep = (a.parent == b.parent ? 1 : 2) / d; + return sep; + break; + } + }); + break; + case layouts.CircularMarkup.index: + // Append a group for the links + container.append("g") + .attr({ + id: "paths" + }); + + // Build the partition + var radius = $scope.diameter / 2 - + layouts.CircularMarkup.padding; + var exponent = layouts.CircularMarkup.radialExponent; + $scope.partition = d3.layout.partition() +// .sort(cmpHostName) + .size([2 * Math.PI, Math.pow(radius, exponent)]) + .value(getPartitionNodeValue); + break; + case layouts.Force.index: + // Append a group for the links + container.append("g") + .attr({ + id: "links" + }); + + // Build the layout + $scope.force = d3.layout.force() + .size([$scope.svgWidth - + 2 * layouts.Force.outsidePadding, + $scope.svgHeight - + 2 * layouts.Force.outsidePadding]) + .on("tick", onForceTick); + break; + } + + // Create the diagonal that will be used to + // connect the nodes + switch($scope.layout) { + case layouts.DepthLayers.index: + case layouts.CollapsedTree.index: + case layouts.BalancedTree.index: + $scope.diagonal = d3.svg.diagonal() + .projection(function(d) { + return [$scope.xZoomScale(d.x), + $scope.yZoomScale(d.y)]; + }); + break; + case layouts.DepthLayersVertical.index: + case layouts.CollapsedTreeVertical.index: + case layouts.BalancedTreeVertical.index: + $scope.diagonal = d3.svg.diagonal() + .projection(function(d) { + return [$scope.xZoomScale(d.y), + $scope.yZoomScale(d.x)]; + }); + break; + case layouts.CircularBalloon.index: + $scope.diagonal = d3.svg.diagonal.radial() + .projection(function(d) { + var angle = 0; + if(!isNaN(d.x)) { + angle = d.x + + layouts.CircularBalloon.rotation + + 90; + } + return [d.y * $scope.zoom.scale(), + ((angle / 180) * Math.PI)]; + }); + break; + } + + // Create the arc this will be used to display the nodes + switch($scope.layout) { + case layouts.CircularMarkup.index: + $scope.arc = d3.svg.arc() + .startAngle(function(d) { return d.x; }) + .endAngle(function(d) { return d.x + d.dx; }) + .innerRadius(function(d) { + return Math.pow(d.y, (1 / exponent)); + }) + .outerRadius(function(d) { + return Math.pow(d.y + d.dy, (1 / exponent)); + }); + break; + } + + // Set the focal point to the root + $scope.focalPoint = $scope.hostTree; + + // Signal the fact that displayMap() is done + displayMapDone = true; + }; + + // Activities that take place only on + // directive instantiation + var onDirectiveInstantiation = function() { + + // Create the zoom behavior + $scope.xZoomScale = d3.scale.linear(); + $scope.yZoomScale = d3.scale.linear(); + $scope.zoom = d3.behavior.zoom() + .scaleExtent([1 / $scope.maxzoom, $scope.maxzoom]) + .x($scope.xZoomScale) + .y($scope.yZoomScale) + .on("zoomstart", onZoomStart) + .on("zoom", onZoom); + + // Set up the div containing the map and + // attach the zoom behavior to the it + d3.select("div#mapsvg") + .style({ + "z-index": $scope.mapZIndex, + height: function() { + return $scope.svgHeight + "px"; + }, + width: function() { + return $scope.svgWidth + "px"; + } + }) + .call($scope.zoom); + + // Set up the resize function + if($scope.allowResize) { + setupResize(); + } + + // Create a container group + d3.select("svg#map") + .append("g") + .attr({ + id: "container", + transform: function() { + return getContainerTransform(); + } + }); + + // Create scale to size nodes based on + // number of services + $scope.nodeScale = d3.scale.linear() + .domain([0, $scope.maxRadiusCount]) + .range([$scope.minRadius, $scope.maxRadius]) + .clamp(true); + + }; + + onDirectiveInstantiation(); + } + }; + }); diff --git a/html/js/map-form.js b/html/js/map-form.js new file mode 100644 index 0000000..7a26ea4 --- /dev/null +++ b/html/js/map-form.js @@ -0,0 +1,68 @@ +angular.module("mapApp") + .controller("mapFormCtrl", function($scope, $modalInstance, $http, + nagiosProcessName, params) { + + $scope.params = params; + $scope.hostlist = []; + $scope.nodelist = []; + + $scope.apply = function () { + $modalInstance.close($scope.params); + }; + + $scope.cancel = function () { + $modalInstance.dismiss('cancel'); + }; + + $scope.showDimensions = function() { + return $scope.params.layout == 0; + }; + + $scope.showCoordinates = function() { + return $scope.params.layout == 0 && + $scope.params.dimensions == "user"; + }; + + $scope.showTimeperiod = function() { + switch ($scope.params.reporttype) { + case "": + return false; + break; + case "hosts": + return $scope.params.host != ""; + break; + case "services": + return $scope.params.host != "" && + $scope.params.service != ""; + break; + } + }; + + $scope.disableApply = function() { + return $scope.hostlist.length == 0; + } + + var getHostList = function() { + var url = $scope.params.cgiurl + + "/objectjson.cgi?query=hostlist"; + $http.get(url, { withCredentials: true}) + .success(function(results) { + $scope.hostlist = results.data.hostlist; + $scope.nodelist = []; + $scope.nodelist.push(nagiosProcessName); + for (var i = 0; i < $scope.hostlist.length; i++) { + $scope.nodelist.push($scope.hostlist[i]); + } + }) + .error(function(err) { + $scope.nodelist = []; + console.log(err); + }); + }; + + $scope.onBlurCgiurl = function(evt) { + getHostList(); + }; + + getHostList(); + }); diff --git a/html/js/map.js b/html/js/map.js new file mode 100644 index 0000000..00cfea3 --- /dev/null +++ b/html/js/map.js @@ -0,0 +1,220 @@ +angular.module("mapApp", ["ui.bootstrap", "ui.utils", "nagiosDecorations", + "nagiosTime"]) + + .constant("nagiosProcessName", "Nagios Process") + + // Layout options + .constant("layouts", { + UserSupplied: { + index: 0, + textAlignment: "below", + padding: { + top: 25, + right: 25, + bottom: 25, + left: 25, + }, + textPadding: { + above: 4, + right: 4, + left: 4, + below: 11 + }, + dimensionType: "fixed" + }, + DepthLayers: { + index: 1, + topPadding: 100, + bottomPadding: 100, + dyText: 4 + }, + CollapsedTree: { + index: 2, + topPadding: 100, + bottomPadding: 100, + dyText: 4 + }, + BalancedTree: { + index: 3, + topPadding: 100, + bottomPadding: 100, + dyText: 4 + }, + Circular: { + index: 4 + }, + CircularMarkup: { + index: 5, + radialExponent: 1.2, + padding: 20, + textPadding: 4 + }, + CircularBalloon: { + index: 6, + outsidePadding: 60, + rotation: -90, + textPadding: 4, + dyText: ".31em" + }, + BalancedTreeVertical: { + index: 7, + leftPadding: 100, + rightPadding: 100, + dxText: 4, + dyText: 3 + }, + CollapsedTreeVertical: { + index: 8, + leftPadding: 100, + rightPadding: 100, + dxText: 4, + dyText: 3 + }, + DepthLayersVertical: { + index: 9, + leftPadding: 100, + rightPadding: 100, + dxText: 4, + dyText: 3 + }, + Force: { + index: 10, + outsidePadding: 60, + textPadding: 4 + } + }) + + .config(function($locationProvider) { + $locationProvider.html5Mode({ + enabled: true, + requireBase: false + }); + }) + + .controller("mapCtrl", function($scope, $location, $modal, $http, + nagiosTimeService, nagiosProcessName, layouts, $window) { + $scope.search = $location.search(); + + // URL parameters + $scope.params = { + cgiurl: $scope.search.cgiurl ? $scope.search.cgiurl : + $location.absUrl().replace(/map\.php.*$/, "cgi-bin/"), + layout: map_layout, + dimensions: $scope.search.dimensions ? + $scope.search.dimensions : "", + ulx: $scope.search.ulx ? parseInt($scope.search.ulx) : 0, + uly: $scope.search.uly ? parseInt($scope.search.uly) : 0, + lrx: $scope.search.lrx ? parseInt($scope.search.lrx) : 0, + lry: $scope.search.lry ? parseInt($scope.search.lry) : 0, + root: $scope.search.root ? $scope.search.root : + nagiosProcessName, + maxzoom: $scope.search.maxzoom ? + parseInt($scope.search.maxzoom) : 10, + nolinks: $scope.search.nolinks ? true : false, + notext: $scope.search.notext ? true : false, + nopopups: $scope.search.nopopups ? true : false, + nomenu: $scope.search.nomenu ? true : false, + noresize: $scope.search.noresize ? true : false, + noicons: $scope.search.noicons ? true : false, + iconurl: $scope.search.iconurl ? $scope.search.iconurl : + $location.absUrl().replace(/map\.php.*$/, "images/logos/"), + }; + + var rightPadding = 1; + var bottomPadding = 4; + + $scope.svgWidth = $window.innerWidth - rightPadding; + $scope.svgHeight = $window.innerHeight - bottomPadding; + + // Application state variables + $scope.formDisplayed = false; + $scope.reload = 0; + + // Decoration-related variables + $scope.lastUpdate = "none"; + + // Determine whether we believe we have sufficient information to + // build the map. If we don't have a valid URL for the JSON CGIs + // we won't know that until we try to fetch the list of hosts, so + // we can't know that now. + $scope.canBuildMap = function() { + document.body.className = ""; + if ($scope.params.layout == layouts.UserSupplied.index) { + switch ($scope.params.dimensions) { + case "fixed": + case "auto": + document.body.className = "hasBgImage"; + return true; + break; + case "user": + if ($scope.params.ulx >= $scope.params.lrx || + $scope.params.uly >= $scope.params.lry) { + return false; + } + else { + document.body.className = "hasBgImage"; + return true; + } + break; + default: + return false; + break; + } + } + else { + return true; + } + }; + + angular.element($window).bind("resize", function() { + $scope.svgWidth = $window.innerWidth - rightPadding; + $scope.svgHeight = $window.innerHeight - bottomPadding; + $scope.$apply("svgWidth"); + $scope.$apply("svgHeight"); + }); + + $scope.displayForm = function(size) { + $scope.formDisplayed = true; + var modalInstance = $modal.open({ + templateUrl: 'map-form.html', + controller: 'mapFormCtrl', + size: size, + resolve: { + params: function () { + return $scope.params; + } + } + }); + + modalInstance.result.then(function(params) { + $scope.formDisplayed = false; + $scope.params = params; + $scope.reload++; + }, + function(reason) { + $scope.formDisplayed = false; + }); + } + + // Style the menu button + $scope.menuButtonStyle = function() { + return { + left: ($scope.svgWidth - 30) + "px", + top: "5px" + }; + }; + + $scope.infoBoxTitle = function() { + if ($scope.params.root == nagiosProcessName) { + return "Network Map for All Hosts"; + } + else { + return "Network Map for Host " + $scope.params.root; + } + }; + + if (!$scope.canBuildMap()) { + $scope.displayForm(); + } + + }) diff --git a/html/js/nag_funcs.js b/html/js/nag_funcs.js new file mode 100644 index 0000000..78f2d18 --- /dev/null +++ b/html/js/nag_funcs.js @@ -0,0 +1,274 @@ +/***************************************************************************** +* Filename: nag_funcs.js +* Description: contains objects and functions used in the Nagios(R) Core(SM) +* website. +* Requires: jquery, nag_funcs.css +* Contents: oreo, vidbox +* License: This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* version 2 as published by the Free Software Foundation. +*****************************************************************************/ + +/* -------------------------------------------------------------------------- +* Object: oreo +* Description: An object to get and set cookies +* Arguments: optional parameters: +* { domain:"mydomain.com", path:"some/path" } +* --------------------------------------------------------------------------*/ +oreo = function(parms) +{ + this.parms = parms || {}; + this.cookies = {}; + this.init(); +} + +/* -------------------------------------------------------------------------- +* Object: oreo +* Function: init +* Description: Gets and stores current document cookies +* Arguments: none +* --------------------------------------------------------------------------*/ +oreo.prototype.init = function() +{ + var i, cookie, name, value, list = new Array(); + list = document.cookie.split(";"); + + i = list.length; + while (i--) { + cookie = list[i]; + cookie = cookie.split("="); + name = decodeURIComponent(cookie[0].replace(/^ (.*)/, "$1")); + value = decodeURIComponent(cookie[1]); + this.cookies[name] = value; + } +} + +/* -------------------------------------------------------------------------- +* Object: oreo +* Function: get +* Description: Gets the value of a cookie +* Arguments: Name of the cookie +* Returns: The value of the cookie, null +* --------------------------------------------------------------------------*/ +oreo.prototype.get = function(name) +{ + if (!name || !this.cookies[name]) + return null; + if (typeof this.cookies[name] == "undefined") + return null; + return this.cookies[name]; +} + +/* -------------------------------------------------------------------------- +* Object: oreo +* Function: set +* Description: Sets a cookie and adds or removes it from this.cookies +* Arguments: { name:"name", value:"value" [, expires:"exp-value", +* domain:"domain.com", path:"some/path"] } +* Notes: parms.name and parms.value are required. The other parms.xxx +* entries are optional. +* +* parms.expires must be a number as follows: +* -1 = Never expire +* 0 = Expire it now +* 1 - ??? = Number of seconds until it expires +* +* Passing conflicting arguments for value and expires: +* Value Expires Result +* ------------- ---------- -------------------------- +* "some string" 0 Expire / remove it +* "" -1 or > 0 Sets an empty cookie +* "" unset Sets an empty cookie +* null 0 Expire / remove it +* null unset Expire / remove it +* null -1 or > 0 Sets an empty cookie +* unset any Expire / remove it +* +* parms.domain and/or parms.path will override domain and/or +* path in the constructor. +* +* Returns: Nothing +* --------------------------------------------------------------------------*/ +oreo.prototype.set = function(parms) +{ + var cookie, name, value, exp, dom, path, dt = null; + + if (!parms || !parms.name) + return; + + name = parms.name; + value = parms.value; + exp = parms.expires; + dom = parms.domain || this.parms.domain || null; + path = parms.path || this.parms.path || null; + + if (typeof value == "undefined") { + value = ""; + exp = 0; + } else if (value == null) { + if (typeof exp != "number" || (typeof exp == "number" && exp == 0)) { + exp = 0; + value = ""; + } + } else if (typeof exp == "number" && exp == 0) { + value == ""; + } + + if (typeof exp == "number") { + dt = new Date(); + if (exp < 0) + dt.setTime(dt.getTime() + 315360000 * 1000); + else if (exp > 0) + dt.setTime(dt.getTime() + exp * 1000); + else + dt.setTime(0); + + dt = dt.toUTCString(); + } + + if (exp == 0) + delete this.cookies[name]; + else + this.cookies[name] = value; + cookie = encodeURIComponent(name) + "=" + encodeURIComponent(value); + if (dt) + cookie += "; expires=" + dt; + if (dom) + cookie += "; domain=" + encodeURIComponent(dom); + if (path) + cookie += "; path=" + encodeURIComponent(path); + + document.cookie = cookie; +} + + +/* -------------------------------------------------------------------------- +* Object: vidbox +* Description: A video box for demo vids on the core website +* Arguments: Takes an optional "args" object which can have one or more +* of the following properties: +* args.pos - vertical (u=upper,l=lower,c=center) and +* horizontal (l=left,r=right,c=center) +* args.text - Text to display below the video +* args.vidid - Video ID for determining if the video box +* should not be created +* --------------------------------------------------------------------------*/ +vidbox = function(args) +{ + this.args = args || {}; + this.tab = null; + this.box = null; + this.frame = null; + this.cancel = null; + this.tab = null; + this.tabClose = null; + this.vidbox = null; + this.txtbox = null; + this.showing = false; + this.pos = args.pos || "lr"; + this.vidurl = args.vidurl || ""; + this.text = args.text || ""; + this.vidid = args.vidid || null; + this.cookie = null; + this.init(); +} + +vidbox.prototype.init = function() +{ + var cls1 = "vidboxContainer vidbox_" + this.pos, + cls2 = "vidboxTab vidboxTab_" + this.pos, + This = this, embed, txt; + + if (this.vidid) { + this.cookie = new oreo(); + txt = this.cookie.get(this.vidid); + if (txt == "no") + return; + } + + this.box = $("
    ", { 'class':cls1 }).appendTo($('body')); + + this.frame = $("
    ", { 'class':"vidboxFrame" }).appendTo($(this.box)); + if (this.vidid) { + this.cancel = $("
    Never show this again
    "). + appendTo($(this.frame)); + $(this.cancel).click(function(){This.cancelBox();}); + } + this.vidbox = $("
    ", { 'class':"vidFrame" }).appendTo($(this.frame)); + this.txtbox = $("
    ", { 'class':"textFrame" }).appendTo($(this.frame)); + + this.tab = $("
    ", { 'class':cls2 }).text("Page Tour").appendTo($('body')); + $(this.tab).click(function(){This.toggleFrame();}); + this.tabClose = $("
    ", { class:"vidboxTabClose", text:'x' } ); + this.tabClose.appendTo($(this.tab)); + + embed = $("'); + } + } + + // Get the daemon status JSON. + function getCoreStatus() { + setCoreStatusHTML('passiveonly', 'Checking process status...'); + + $.get('/statusjson.cgi?query=programstatus', function(d) { + d = d && d.data && d.data.programstatus || false; + if (d && d.nagios_pid) { + var pid = d.nagios_pid; + var daemon = d.daemon_mode ? 'Daemon' : 'Process'; + setCoreStatusHTML('enabled', daemon + ' running with PID ' + pid); + } else { + setCoreStatusHTML('disabled', 'Not running'); + } + }).fail(function() { + setCoreStatusHTML('disabled', 'Unable to get process status'); + }); + } + + function setCoreStatusHTML(image, text) { + $('#core-status').html(' ' + text); + } @@ -31,109 +132,116 @@ $this_version="3.5.1";
    - + +
    +
    -
    Nagios® Core
    -
    Version 3.5.1
    -
    August 30, 2013
    - - +
    Nagios® Core
    +
    Version
    +
    May 09, 2017
    +
    -
    Warning: Automatic Update Checks are Disabled!
    -
    Disabling update checks presents a possible security risk. Visit nagios.org to check for updates manually or enable update checks in your Nagios config file.
    +
    Warning: Automatic Update Checks are Disabled!
    +
    Disabling update checks presents a possible security risk. Visit nagios.org to check for updates manually or enable update checks in your Nagios config file.
    -
    A new version of Nagios Core is available!
    -
    Visit nagios.org to download Nagios .
    +
    A new version of Nagios Core is available!
    +
    Visit nagios.org to download Nagios .
    +
    +
    +
    +
    +
    +
    -
    -
    + + - -
    -
    +

    Quick Links

    -
    - - -
    -

    Latest News

    -
    -
    -
    + +
    +
    + +
    + +
    + +
    +

    Latest News

    +
    +
    +
    + +
    +

    Don't Miss...

    +
    +
    +
    + +
    + +
    -
    Copyright © 2010- Nagios Core Development Team and Community Contributors. Copyright © 1999-2009 Ethan Galstad. See the THANKS file for more information on contributors.
    -
    -Nagios Core is licensed under the GNU General Public License and is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. Nagios, Nagios Core and the Nagios logo are trademarks, servicemarks, registered trademarks or registered servicemarks owned by Nagios Enterprises, LLC. Use of the Nagios marks is governed by the trademark use restrictions. -
    -
    - - - - -SourceForge.net Logo -
    +
    + Copyright © 2010- Nagios Core Development Team and Community Contributors. Copyright © 1999-2009 Ethan Galstad. See the THANKS file for more information on contributors. +
    +
    + Nagios Core is licensed under the GNU General Public License and is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. Nagios, Nagios Core and the Nagios logo are trademarks, servicemarks, registered trademarks or registered servicemarks owned by Nagios Enterprises, LLC. Use of the Nagios marks is governed by the trademark use restrictions. +
    +
    + + SourceForge.net Logo +
    - diff --git a/html/map-directive.html b/html/map-directive.html new file mode 100644 index 0000000..c58f7a4 --- /dev/null +++ b/html/map-directive.html @@ -0,0 +1,48 @@ + + +
    + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/html/map-form.html b/html/map-form.html new file mode 100644 index 0000000..aa8473c --- /dev/null +++ b/html/map-form.html @@ -0,0 +1,116 @@ +
    + + + + diff --git a/html/map-links.html b/html/map-links.html new file mode 100644 index 0000000..fe9759e --- /dev/null +++ b/html/map-links.html @@ -0,0 +1,21 @@ +
    ' + option.type + ': ' + key + '
    + + + + + + diff --git a/html/map-popup.html b/html/map-popup.html new file mode 100644 index 0000000..2350edf --- /dev/null +++ b/html/map-popup.html @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    diff --git a/html/map.php b/html/map.php new file mode 100644 index 0000000..82ab2fd --- /dev/null +++ b/html/map.php @@ -0,0 +1,122 @@ + + + + + + + +\n"; + echo "\t\t\tbody.hasBgImage { background: url('$img');\n"; + echo "\t\t\n"; + } + + $layout = 6; + if (isset($cfg["default_statusmap_layout"])) { + $layout = $cfg["default_statusmap_layout"]; + if (is_numeric($layout)) + $layout = $layout + 0; + else + $layout = -1; + if ($layout > 10 || $layout < 0) + $layout = 6; + } + if ($layout == 4) + $layout = 6; +?> + + Nagios Map + + + + + + + + + + + + + + + + + + + + + + + + > + +
    +
    +
    +
    +
    +
    + + + + diff --git a/html/rss-corefeed.php b/html/rss-corefeed.php deleted file mode 100644 index fbf8215..0000000 --- a/html/rss-corefeed.php +++ /dev/null @@ -1,50 +0,0 @@ -"; - - foreach ($rss->items as $item){ - $x++; - if($x>3) - break; - //$href = $item['link']; - //$title = $item['title']; - $desc = $item['description']; - $html .="
  • {$item['description']}
  • "; - } - $html .=""; - - print $html; - } - else{ - $html = " - An error occurred while trying to fetch the Nagios Core feed. Stay on top of what's happening by visiting http://www.nagios.org/. - "; - print $html; - } - } - - -?> \ No newline at end of file diff --git a/html/rss-newsfeed.php b/html/rss-newsfeed.php deleted file mode 100644 index 52d7901..0000000 --- a/html/rss-newsfeed.php +++ /dev/null @@ -1,48 +0,0 @@ -\n"; - - foreach ($rss->items as $item){ - $x++; - if($x>3) - break; - $href = $item['link']; - $title = $item['title']; - $html .="
  • $title
  • "; - } - $html .=' -
  • More news...
  • - '; - - print $html; - } - else{ - $html = " - An error occurred while trying to fetch the latest Nagios news. Stay on top of what's happening by visiting http://www.nagios.org/news. - "; - print $html; - } - } - - -?> \ No newline at end of file diff --git a/html/side.php b/html/side.php index 436f7dc..97893b4 100644 --- a/html/side.php +++ b/html/side.php @@ -1,127 +1,123 @@ - -Nagios Core - +Nagios Core + + - - - - - - - - - - - + + diff --git a/html/spin/spin.js b/html/spin/spin.js new file mode 100644 index 0000000..a3812e2 --- /dev/null +++ b/html/spin/spin.js @@ -0,0 +1,349 @@ +/** + * Copyright (c) 2011-2014 Felix Gnass + * Licensed under the MIT license + */ +(function(root, factory) { + + /* CommonJS */ + if (typeof exports == 'object') module.exports = factory() + + /* AMD module */ + else if (typeof define == 'function' && define.amd) define(factory) + + /* Browser global */ + else root.Spinner = factory() +} +(this, function() { + "use strict"; + + var prefixes = ['webkit', 'Moz', 'ms', 'O'] /* Vendor prefixes */ + , animations = {} /* Animation rules keyed by their name */ + , useCssAnimations /* Whether to use CSS animations or setTimeout */ + + /** + * Utility function to create elements. If no tag name is given, + * a DIV is created. Optionally properties can be passed. + */ + function createEl(tag, prop) { + var el = document.createElement(tag || 'div') + , n + + for(n in prop) el[n] = prop[n] + return el + } + + /** + * Appends children and returns the parent. + */ + function ins(parent /* child1, child2, ...*/) { + for (var i=1, n=arguments.length; i>1) + 'px' + }) + } + + for (; i < o.lines; i++) { + seg = css(createEl(), { + position: 'absolute', + top: 1+~(o.width/2) + 'px', + transform: o.hwaccel ? 'translate3d(0,0,0)' : '', + opacity: o.opacity, + animation: useCssAnimations && addAnimation(o.opacity, o.trail, start + i * o.direction, o.lines) + ' ' + 1/o.speed + 's linear infinite' + }) + + if (o.shadow) ins(seg, css(fill('#000', '0 0 4px ' + '#000'), {top: 2+'px'})) + ins(el, ins(seg, fill(getColor(o.color, i), '0 0 1px rgba(0,0,0,.1)'))) + } + return el + }, + + /** + * Internal method that adjusts the opacity of a single line. + * Will be overwritten in VML fallback mode below. + */ + opacity: function(el, i, val) { + if (i < el.childNodes.length) el.childNodes[i].style.opacity = val + } + + }) + + + function initVML() { + + /* Utility function to create a VML tag */ + function vml(tag, attr) { + return createEl('<' + tag + ' xmlns="urn:schemas-microsoft.com:vml" class="spin-vml">', attr) + } + + // No CSS transforms but VML support, add a CSS rule for VML elements: + sheet.addRule('.spin-vml', 'behavior:url(#default#VML)') + + Spinner.prototype.lines = function(el, o) { + var r = o.length+o.width + , s = 2*r + + function grp() { + return css( + vml('group', { + coordsize: s + ' ' + s, + coordorigin: -r + ' ' + -r + }), + { width: s, height: s } + ) + } + + var margin = -(o.width+o.length)*2 + 'px' + , g = css(grp(), {position: 'absolute', top: margin, left: margin}) + , i + + function seg(i, dx, filter) { + ins(g, + ins(css(grp(), {rotation: 360 / o.lines * i + 'deg', left: ~~dx}), + ins(css(vml('roundrect', {arcsize: o.corners}), { + width: r, + height: o.width, + left: o.radius, + top: -o.width>>1, + filter: filter + }), + vml('fill', {color: getColor(o.color, i), opacity: o.opacity}), + vml('stroke', {opacity: 0}) // transparent stroke to fix color bleeding upon opacity change + ) + ) + ) + } + + if (o.shadow) + for (i = 1; i <= o.lines; i++) + seg(i, -2, 'progid:DXImageTransform.Microsoft.Blur(pixelradius=2,makeshadow=1,shadowopacity=.3)') + + for (i = 1; i <= o.lines; i++) seg(i) + return ins(el, g) + } + + Spinner.prototype.opacity = function(el, i, val, o) { + var c = el.firstChild + o = o.shadow && o.lines || 0 + if (c && i+o < c.childNodes.length) { + c = c.childNodes[i+o]; c = c && c.firstChild; c = c && c.firstChild + if (c) c.opacity = val + } + } + } + + var probe = css(createEl('group'), {behavior: 'url(#default#VML)'}) + + if (!vendor(probe, 'transform') && probe.adj) initVML() + else useCssAnimations = vendor(probe, 'animation') + + return Spinner + +})); diff --git a/html/spin/spin.min.js b/html/spin/spin.min.js new file mode 100644 index 0000000..ebfbb1a --- /dev/null +++ b/html/spin/spin.min.js @@ -0,0 +1,2 @@ +//fgnass.github.com/spin.js#v2.0.1 +!function(a,b){"object"==typeof exports?module.exports=b():"function"==typeof define&&define.amd?define(b):a.Spinner=b()}(this,function(){"use strict";function a(a,b){var c,d=document.createElement(a||"div");for(c in b)d[c]=b[c];return d}function b(a){for(var b=1,c=arguments.length;c>b;b++)a.appendChild(arguments[b]);return a}function c(a,b,c,d){var e=["opacity",b,~~(100*a),c,d].join("-"),f=.01+c/d*100,g=Math.max(1-(1-a)/b*(100-f),a),h=j.substring(0,j.indexOf("Animation")).toLowerCase(),i=h&&"-"+h+"-"||"";return l[e]||(m.insertRule("@"+i+"keyframes "+e+"{0%{opacity:"+g+"}"+f+"%{opacity:"+a+"}"+(f+.01)+"%{opacity:1}"+(f+b)%100+"%{opacity:"+a+"}100%{opacity:"+g+"}}",m.cssRules.length),l[e]=1),e}function d(a,b){var c,d,e=a.style;for(b=b.charAt(0).toUpperCase()+b.slice(1),d=0;d',c)}m.addRule(".spin-vml","behavior:url(#default#VML)"),h.prototype.lines=function(a,d){function f(){return e(c("group",{coordsize:k+" "+k,coordorigin:-j+" "+-j}),{width:k,height:k})}function h(a,h,i){b(m,b(e(f(),{rotation:360/d.lines*a+"deg",left:~~h}),b(e(c("roundrect",{arcsize:d.corners}),{width:j,height:d.width,left:d.radius,top:-d.width>>1,filter:i}),c("fill",{color:g(d.color,a),opacity:d.opacity}),c("stroke",{opacity:0}))))}var i,j=d.length+d.width,k=2*j,l=2*-(d.width+d.length)+"px",m=e(f(),{position:"absolute",top:l,left:l});if(d.shadow)for(i=1;i<=d.lines;i++)h(i,-2,"progid:DXImageTransform.Microsoft.Blur(pixelradius=2,makeshadow=1,shadowopacity=.3)");for(i=1;i<=d.lines;i++)h(i);return b(a,m)},h.prototype.opacity=function(a,b,c,d){var e=a.firstChild;d=d.shadow&&d.lines||0,e&&b+d>1)+"px"})}for(var i,k=0,l=(f.lines-1)*(1-f.direction)/2;k + + + + diff --git a/html/trends-graph.html b/html/trends-graph.html new file mode 100644 index 0000000..b08475b --- /dev/null +++ b/html/trends-graph.html @@ -0,0 +1,121 @@ + + +
    +
    +
    +
    +
    + + + + State History for Service '{{service}}' on + Host '{{host}}' + + + State History for Host '{{host}}' + + + {{startTime | date:'EEE MMM dd HH:mm:ss yyyy'}} to + {{endTime | date:'EEE MMM dd HH:mm:ss yyyy'}} + + + + + + + + + + + + + Up : + + + ({{availabilityStates.up.percentageTime * 100 | number: 3}}%) + {{availabilityStates.up.totalTime * 1000 | duration}} + + + Down : + + + ({{availabilityStates.down.percentageTime * 100 | number: 3}}%) + {{availabilityStates.down.totalTime * 1000 | duration}} + + + Unreachable : + + + ({{availabilityStates.unreachable.percentageTime * 100 | number: 3}}%) + {{availabilityStates.unreachable.totalTime * 1000 | duration}} + + + Indeterminate : + + + ({{availabilityStates.nodata.percentageTime * 100 | number: 3}}%) + {{availabilityStates.nodata.totalTime * 1000 | duration}} + + + + + Ok : + + + ({{availabilityStates.ok.percentageTime * 100 | number: 3}}%) + {{availabilityStates.ok.totalTime * 1000 | duration}} + + + Warning : + + + ({{availabilityStates.warning.percentageTime * 100 | number: 3}}%) + {{availabilityStates.warning.totalTime * 1000 | duration}} + + + Unknown : + + + ({{availabilityStates.unknown.percentageTime * 100 | number: 3}}%) + {{availabilityStates.unknown.totalTime * 1000 | duration}} + + + Critical : + + + ({{availabilityStates.critical.percentageTime * 100 | number: 3}}%) + {{availabilityStates.critical.totalTime * 1000 | duration}} + + + Indeterminate : + + + ({{availabilityStates.nodata.percentageTime * 100 | number: 3}}%) + {{availabilityStates.nodata.totalTime * 1000 | duration}} + + + +
    +
    diff --git a/html/trends-host-yaxis.html b/html/trends-host-yaxis.html new file mode 100644 index 0000000..90df1e6 --- /dev/null +++ b/html/trends-host-yaxis.html @@ -0,0 +1,20 @@ + + + Up + + + + Down + + + + Unreachable + + + + Indeterminate + diff --git a/html/trends-links.html b/html/trends-links.html new file mode 100644 index 0000000..8b91a77 --- /dev/null +++ b/html/trends-links.html @@ -0,0 +1,51 @@ + + + + + + + + + diff --git a/html/trends-service-yaxis.html b/html/trends-service-yaxis.html new file mode 100644 index 0000000..349f621 --- /dev/null +++ b/html/trends-service-yaxis.html @@ -0,0 +1,25 @@ + + + Ok + + + + Warning + + + + Unknown + + + + Critical + + + + Indeterminate + diff --git a/html/trends.html b/html/trends.html new file mode 100644 index 0000000..70eee2d --- /dev/null +++ b/html/trends.html @@ -0,0 +1,78 @@ + + + + + Nagios Trends + + + + + + + + + + + + + + + + + + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + + +
    +
    +
    + + diff --git a/include/Makefile b/include/Makefile index a11914d..85e0c37 100644 --- a/include/Makefile +++ b/include/Makefile @@ -1,7 +1,6 @@ ############################### # Makefile for Include Files # -# Last Modified: 10-18-2007 ############################### clean: diff --git a/include/archivejson.h b/include/archivejson.h new file mode 100644 index 0000000..f2711c4 --- /dev/null +++ b/include/archivejson.h @@ -0,0 +1,153 @@ +/************************************************************************** + * + * ARCHIVEJSON.H - Nagios CGI for returning JSON-formatted archive data + * + * Copyright (c) 2013 Nagios Enterprises, LLC + * Last Modified: 04-13-2013 + * + * License: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + *************************************************************************/ + +#ifndef ARCHIVEJSON_H_INCLUDED +#define ARCHIVEJSON_H_INCLUDED + +/* Structure containing CGI query string options and values */ +typedef struct archive_json_cgi_data_struct { + /* Format options for JSON output */ + unsigned format_options; + /* Query being requested */ + int query; + /* Index of starting object returned for list requests */ + int start; + /* Number of objects returned for list requests */ + int count; + /* Type(s) of object to be queried (host and/or service) */ + unsigned object_types; + /* Type of object to be queried (host and/or service) */ + int object_type; + /* State types to include in query results */ + unsigned state_types; + /* Host states to include in query results */ + unsigned host_states; + /* Service states to include in query results */ + unsigned service_states; + /* Host notification types to include in query results */ + unsigned host_notification_types; + /* Service notification types to include in query results */ + unsigned service_notification_types; + /* strftime format string for time_t values */ + char * strftime_format; + /* Name of host whose children should be returned if parenthost is + specified */ + char * parent_host_name; + /* Use the parent host field or search all hosts*/ + int use_parent_host; + /* Host whose children should be returned if use_parent_host is non-zero */ + host * parent_host; + /* Name of host whose parents should be returned if childhost is + specified */ + char * child_host_name; + /* Use the child host field or search all hosts*/ + int use_child_host; + /* Host whose parents should be returned if use_child_host is non-zero */ + host * child_host; + /* Name of host for which details should be returned */ + char * host_name; + /* Host whose host name is host_name */ + host * host; + /* Name of hostgroup for which details should be returned */ + char * hostgroup_name; + /* Hostgroup whose name is hostgroup_name */ + hostgroup * hostgroup; + /* Name of servicegroup for which details should be returned */ + char * servicegroup_name; + /* Servicegroup whose name is servicegroup_name */ + servicegroup * servicegroup; + /* Name of service for which details should be returned */ + char * service_description; + /* Service whose host name is host_name and whose description is + service_description*/ + service * service; + /* Name of contact for which details should be returned */ + char * contact_name; + /* Contact whose contact name is contact_name */ + contact * contact; + /* Name of contactgroup for which details should be returned */ + char * contactgroup_name; + /* Contactgroup whose name is contactgroup_name */ + contactgroup * contactgroup; + /* Notification method */ + char * notification_method; + /* Report timeperiod name */ + char * timeperiod_name; + /* Timeperiod whose name is timeperiod_name */ + timeperiod *timeperiod; + /* Assumed initial host state */ + int assumed_initial_host_state; + /* Assumed initial service state */ + int assumed_initial_service_state; + /* Assume initial state for host(s) or service(s) */ + int assume_initial_state; + /* Assume states are retained */ + int assume_state_retention; + /* Assume states during Nagios downtime */ + int assume_states_during_nagios_downtime; + /* Start time */ + time_t start_time; + /* End time */ + time_t end_time; + /* Number of backtrack archives to read */ + int backtracked_archives; + } archive_json_cgi_data; + +/* Object Type Information */ +#define ARCHIVE_QUERY_INVALID 0 +#define ARCHIVE_QUERY_HELP 1 +#define ARCHIVE_QUERY_ALERTCOUNT 2 +#define ARCHIVE_QUERY_ALERTLIST 3 +#define ARCHIVE_QUERY_NOTIFICATIONCOUNT 4 +#define ARCHIVE_QUERY_NOTIFICATIONLIST 5 +#define ARCHIVE_QUERY_STATECHANGELIST 6 +#define ARCHIVE_QUERY_AVAILABILITY 7 + +extern json_object *json_archive_alertcount(unsigned, time_t, time_t, int, + char *, char *, int, host *, int, host *, hostgroup *, servicegroup *, + contact *, contactgroup *, unsigned, unsigned, unsigned, au_log *); +extern json_object *json_archive_alertlist(unsigned, int, int, time_t, time_t, + int, char *, char *, int, host *, int, host *, hostgroup *, + servicegroup *, contact *, contactgroup *, unsigned, unsigned, + unsigned, au_log *); +extern void json_archive_alert_details(json_object *, unsigned, time_t, + au_log_alert *); + +extern json_object * json_archive_notificationcount(unsigned, time_t, time_t, + int, char *, char *, int, host *, int, host *, hostgroup *, + servicegroup *, char *, contactgroup *, unsigned, unsigned, char *, + au_log *); +extern json_object * json_archive_notificationlist(unsigned, int, int, time_t, + time_t, int, char *, char *, int, host *, int, host *, hostgroup *, + servicegroup *, char *, contactgroup *, unsigned, unsigned, char *, + au_log *); +extern void json_archive_notification_details(json_object *, unsigned, time_t, + au_log_notification *); + +extern json_object *json_archive_statechangelist(unsigned, int, int, time_t, + time_t, int, char *, char *, int, int, unsigned, au_log *); + +extern json_object *json_archive_availability(unsigned, time_t, time_t, time_t, + int, char *, char *, hostgroup *, servicegroup *, timeperiod *, int, + int, int, int, int, unsigned, au_log *); +#endif diff --git a/include/archiveutils.h b/include/archiveutils.h new file mode 100644 index 0000000..1bf4ac3 --- /dev/null +++ b/include/archiveutils.h @@ -0,0 +1,278 @@ +/************************************************************************** + * + * ARCHIVEUTILS.H - Utility information for Nagios CGI that read archives + * + * Copyright (c) 2013 Nagios Enterprises, LLC + * Last Modified: 06-30-2013 + * + * License: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + *************************************************************************/ + +#ifndef ARCHIVEUTILS_H_INCLUDED +#define ARCHIVEUTILS_H_INCLUDED + +#include "../include/jsonutils.h" + +/* Archive utilities object types */ +#define AU_OBJTYPE_NONE 0 +#define AU_OBJTYPE_HOST (1<<0) +#define AU_OBJTYPE_SERVICE (1<<1) +#define AU_OBJTYPE_HOSTGROUP (1<<2) +#define AU_OBJTYPE_SERVICEGROUP (1<<3) +#define AU_OBJTYPE_ALL (AU_OBJTYPE_HOST | AU_OBJTYPE_SERVICE) + +/* Archive utilities state types */ +#define AU_STATETYPE_HARD (1<<0) +#define AU_STATETYPE_SOFT (1<<1) +#define AU_STATETYPE_NO_DATA (1<<2) +#define AU_STATETYPE_ALL (AU_STATETYPE_HARD | AU_STATETYPE_SOFT) + +/* Archive utilities states */ +#define AU_STATE_NO_DATA 0 +#define AU_STATE_HOST_UP (1<<0) +#define AU_STATE_HOST_DOWN (1<<1) +#define AU_STATE_HOST_UNREACHABLE (1<<2) +#define AU_STATE_SERVICE_OK (1<<3) +#define AU_STATE_SERVICE_WARNING (1<<4) +#define AU_STATE_SERVICE_CRITICAL (1<<5) +#define AU_STATE_SERVICE_UNKNOWN (1<<6) +#define AU_STATE_PROGRAM_START (1<<7) /* Nagios program start */ +#define AU_STATE_PROGRAM_END (1<<8) /* Nagios program end */ +#define AU_STATE_DOWNTIME_START (1<<9) /* Downtime start */ +#define AU_STATE_DOWNTIME_END (1<<10) /* Downtime end */ +#define AU_STATE_CURRENT_STATE (1<<11) /* Host or service current state */ + +#define AU_STATE_HOST_ALL (AU_STATE_HOST_UP | \ + AU_STATE_HOST_DOWN | \ + AU_STATE_HOST_UNREACHABLE) +#define AU_STATE_SERVICE_ALL (AU_STATE_SERVICE_OK | \ + AU_STATE_SERVICE_WARNING | \ + AU_STATE_SERVICE_CRITICAL | \ + AU_STATE_SERVICE_UNKNOWN) +#define AU_STATE_ALL (AU_STATE_HOST_ALL | AU_STATE_SERVICE_ALL) + +/* Archive utilities log types */ +#define AU_LOGTYPE_ALERT (1<<0) +#define AU_LOGTYPE_STATE_INITIAL (1<<1) +#define AU_LOGTYPE_STATE_CURRENT (1<<2) +#define AU_LOGTYPE_NOTIFICATION (1<<3) +#define AU_LOGTYPE_DOWNTIME (1<<4) +#define AU_LOGTYPE_NAGIOS (1<<5) +#define AU_LOGTYPE_STATE (AU_LOGTYPE_STATE_INITIAL | \ + AU_LOGTYPE_STATE_CURRENT) +#define AU_LOGTYPE_ALL (AU_LOGTYPE_ALERT | \ + AU_LOGTYPE_STATE | \ + AU_LOGTYPE_NOTIFICATION | \ + AU_LOGTYPE_DOWNTIME | \ + AU_LOGTYPE_NAGIOS) + +/* Archive utilities notification types */ +#define AU_NOTIFICATION_NO_DATA 0 +#define AU_NOTIFICATION_HOST_DOWN (1<<0) +#define AU_NOTIFICATION_HOST_UNREACHABLE (1<<1) +#define AU_NOTIFICATION_HOST_RECOVERY (1<<2) +#define AU_NOTIFICATION_HOST_CUSTOM (1<<3) +#define AU_NOTIFICATION_HOST_ACK (1<<4) +#define AU_NOTIFICATION_HOST_FLAPPING_START (1<<5) +#define AU_NOTIFICATION_HOST_FLAPPING_STOP (1<<6) +#define AU_NOTIFICATION_SERVICE_CRITICAL (1<<7) +#define AU_NOTIFICATION_SERVICE_WARNING (1<<8) +#define AU_NOTIFICATION_SERVICE_RECOVERY (1<<9) +#define AU_NOTIFICATION_SERVICE_CUSTOM (1<<10) +#define AU_NOTIFICATION_SERVICE_ACK (1<<11) +#define AU_NOTIFICATION_SERVICE_FLAPPING_START (1<<12) +#define AU_NOTIFICATION_SERVICE_FLAPPING_STOP (1<<13) +#define AU_NOTIFICATION_SERVICE_UNKNOWN (1<<14) + +#define AU_NOTIFICATION_HOST_ALL (AU_NOTIFICATION_HOST_DOWN | \ + AU_NOTIFICATION_HOST_UNREACHABLE | \ + AU_NOTIFICATION_HOST_RECOVERY | \ + AU_NOTIFICATION_HOST_CUSTOM | \ + AU_NOTIFICATION_HOST_ACK | \ + AU_NOTIFICATION_HOST_FLAPPING_START | \ + AU_NOTIFICATION_HOST_FLAPPING_STOP) + +#define AU_NOTIFICATION_SERVICE_ALL (AU_NOTIFICATION_SERVICE_CRITICAL | \ + AU_NOTIFICATION_SERVICE_WARNING | \ + AU_NOTIFICATION_SERVICE_RECOVERY | \ + AU_NOTIFICATION_SERVICE_CUSTOM | \ + AU_NOTIFICATION_SERVICE_ACK | \ + AU_NOTIFICATION_SERVICE_FLAPPING_START | \ + AU_NOTIFICATION_SERVICE_FLAPPING_STOP | \ + AU_NOTIFICATION_SERVICE_UNKNOWN) + +#define AU_NOTFICATION_ALL (AU_NOTFICATION_HOST_ALL | \ + AU_NOTIFICATION_SERVICE_ALL) + +typedef struct au_array_struct { + char *label; + int size; + int count; + void **members; + int new; + } au_array; + +typedef struct au_node_struct { + void *data; + struct au_node_struct *next; + } au_node; + +typedef struct au_linked_list_struct { + char *label; + au_node *head; + au_node *last_new; + } au_linked_list; + +struct au_log_entry_struct; + +/* au_availability keeps the availability information for a given host or + service */ +typedef struct au_availability_struct { + unsigned long time_up; + unsigned long time_down; + unsigned long time_unreachable; + unsigned long time_ok; + unsigned long time_warning; + unsigned long time_unknown; + unsigned long time_critical; + + unsigned long scheduled_time_up; + unsigned long scheduled_time_down; + unsigned long scheduled_time_unreachable; + unsigned long scheduled_time_ok; + unsigned long scheduled_time_warning; + unsigned long scheduled_time_unknown; + unsigned long scheduled_time_critical; + unsigned long scheduled_time_indeterminate; + + unsigned long time_indeterminate_nodata; + unsigned long time_indeterminate_notrunning; + } au_availability; + +/* au_host keeps information about a single host and all log entries that + pertain to that host, including global events such as Nagios starts and + stops */ +typedef struct au_host_struct { + char *name; + host *hostp; + au_linked_list *log_entries; + au_availability *availability; + } au_host; + +/* au_service keeps information about a single service and all log entries + that pertain to that service, including global events such as Nagios + starts and stops */ +typedef struct au_service_struct { + char *host_name; + char *description; + service *servicep; + au_linked_list *log_entries; + au_availability *availability; + } au_service; + +typedef struct au_contact_struct { + char *name; + contact *contactp; + } au_contact; + +/* au_log_alert keeps information about alert and state type logs */ +typedef struct au_log_alert_struct { + int obj_type; /* AU_OBJTYPE_HOST or AU_OBJTYPE_SERVICE */ + void *object; /* au_host or au_service */ + int state_type; /* hard, soft, or no data */ + int state; /* any host or service state, or no data */ + char *plugin_output; + } au_log_alert; + +/* au_log_notification keeps information about notification logs */ +typedef struct au_log_notification_struct { + int obj_type; /* AU_OBJTYPE_HOST or AU_OBJTYPE_SERVICE */ + void *object; /* au_host or au_service */ + au_contact *contact; /* notification contact */ + int notification_type; + char *method; + char *message; /* informational method */ + } au_log_notification; + +/* au_log_downtime keeps information about downtime logs */ +typedef struct au_log_downtime_struct { + int obj_type; /* AU_OBJTYPE_HOST or AU_OBJTYPE_SERVICE */ + void *object; /* au_host or au_service */ + int downtime_type; /* AU_STATE_DOWNTIME_START or + AU_STATE_DOWNTIME_END */ + } au_log_downtime; + +/* au_log_nagios keeps information about Nagios starts and stops */ +typedef struct au_log_nagios_struct { + int type; /* AU_STATE_NAGIOS_START or + AU_STATE_NAGIOS_STOP */ + char *description; + } au_log_nagios; + +/* au_log_entry keeps information about each log entry */ +typedef struct au_log_entry_struct { + time_t timestamp; + int entry_type; /* AU_LOGTYPE_* */ + void *entry; /* au_log_alert *, au_log_notification *, + au_log_downtime *, or au_log_nagios * */ + } au_log_entry; + +typedef struct au_log_struct { + au_array *host_subjects; /* hosts to parse when specified + in the query */ + au_array *service_subjects; /* services to parse when specified + in the query */ + au_linked_list *entry_list; /* linked list of log entries */ + au_array *hosts; /* list of hosts and their log entries + discovered during parsing */ + au_array *services; /* list of services and the log + entries discovered during parsing */ + au_array *contacts; /* list of contacts associated with + notification logs */ + } au_log; + +/* External functions */ +extern au_log *au_init_log(void); +extern int read_archived_data(time_t, time_t, int, unsigned, unsigned, + unsigned, au_log *, time_t *); +extern int au_cmp_log_entries(const void *, const void *); +extern void au_free_log(au_log *); + +extern au_node *au_list_add_node(au_linked_list *, void *, + int(*)(const void *, const void *)); + +extern int au_add_alert_or_state_log(au_log *, time_t, int, int, void *, int, + int, char *); +extern au_log_alert *au_create_alert_or_state_log(int, void *, int, int, + char *); +extern void au_free_alert_log(au_log_alert *); + +extern au_host *au_add_host(au_array *, char *); +extern au_host *au_find_host(au_array *, char *); +extern au_service *au_add_service(au_array *, char *, char *); +extern au_service *au_find_service(au_array *, char *, char *); +extern au_array *au_init_array(char *); +extern void au_free_array(au_array *, void(*)(void *)); +extern int au_array_append_member(au_array *, void *); + +/* External variables */ +extern const string_value_mapping svm_au_object_types[]; +extern const string_value_mapping svm_au_state_types[]; +extern const string_value_mapping svm_au_states[]; +extern const string_value_mapping svm_au_log_types[]; +extern const string_value_mapping svm_au_notification_types[]; + +#endif diff --git a/include/broker.h b/include/broker.h index 64e3b39..22abe07 100644 --- a/include/broker.h +++ b/include/broker.h @@ -2,8 +2,6 @@ * * BROKER.H - Event broker includes for Nagios * - * Copyright (c) 2002-2006 Ethan Galstad (egalstad@nagios.org) - * Last Modified: 12-12-2006 * * License: * @@ -22,8 +20,8 @@ * *****************************************************************************/ -#ifndef _BROKER_H -#define _BROKER_H +#ifndef NAGIOS_BROKER_H_INCLUDED +#define NAGIOS_BROKER_H_INCLUDED #include "nagios.h" @@ -76,6 +74,7 @@ #define NEBTYPE_TIMEDEVENT_DELAY 203 /* NOT IMPLEMENTED */ #define NEBTYPE_TIMEDEVENT_SKIP 204 /* NOT IMPLEMENTED */ #define NEBTYPE_TIMEDEVENT_SLEEP 205 +#define NEBTYPE_TIMEDEVENT_END 206 #define NEBTYPE_LOG_DATA 300 #define NEBTYPE_LOG_ROTATION 301 @@ -179,7 +178,6 @@ /****** EVENT BROKER FUNCTIONS *************/ #ifdef USE_EVENT_BROKER -#include "compat.h" NAGIOS_BEGIN_DECL struct timeval get_broker_timestamp(struct timeval *); @@ -188,8 +186,8 @@ void broker_timed_event(int, int, int, timed_event *, struct timeval *); void broker_log_data(int, int, int, char *, unsigned long, time_t, struct timeval *); int broker_event_handler(int, int, int, int, void *, int, int, struct timeval, struct timeval, double, int, int, int, char *, char *, char *, struct timeval *); void broker_system_command(int, int, int, struct timeval, struct timeval, double, int, int, int, char *, char *, struct timeval *); -int broker_host_check(int, int, int, host *, int, int, int, struct timeval, struct timeval, char *, double, double, int, int, int, char *, char *, char *, char *, struct timeval *); -int broker_service_check(int, int, int, service *, int, struct timeval, struct timeval, char *, double, double, int, int, int, char *, struct timeval *); +int broker_host_check(int, int, int, host *, int, int, int, struct timeval, struct timeval, char *, double, double, int, int, int, char *, char *, char *, char *, struct timeval *, check_result *); +int broker_service_check(int, int, int, service *, int, struct timeval, struct timeval, char *, double, double, int, int, int, char *, struct timeval *, check_result *); void broker_comment_data(int, int, int, int, int, char *, char *, time_t, char *, char *, int, int, int, time_t, unsigned long, struct timeval *); void broker_downtime_data(int, int, int, int, char *, char *, time_t, char *, char *, time_t, time_t, int, unsigned long, unsigned long, unsigned long, struct timeval *); void broker_flapping_data(int, int, int, int, void *, double, double, double, struct timeval *); diff --git a/include/cgiauth.h b/include/cgiauth.h index 53ad9c9..3216e44 100644 --- a/include/cgiauth.h +++ b/include/cgiauth.h @@ -2,7 +2,6 @@ * * CGIAUTH.H - Authorization utilities header file * - * Last Modified: 11-24-2005 * * License: * @@ -21,9 +20,8 @@ * *****************************************************************************/ -#ifndef _AUTH_H -#define _AUTH_H -#include "compat.h" +#ifndef NAGIOS_CGIAUTH_H_INCLUDED +#define NAGIOS_CGIAUTH_H_INCLUDED #include "common.h" #include "objects.h" @@ -59,7 +57,7 @@ int is_authorized_for_service_commands(service *, authdata *); int is_authorized_for_hostgroup(hostgroup *, authdata *); int is_authorized_for_servicegroup(servicegroup *, authdata *); - + int is_authorized_for_hostgroup_commands(hostgroup *, authdata *); int is_authorized_for_servicegroup_commands(servicegroup *, authdata *); diff --git a/include/cgiutils.h b/include/cgiutils.h index fcf69ed..5a4b308 100644 --- a/include/cgiutils.h +++ b/include/cgiutils.h @@ -1,8 +1,6 @@ /************************************************************************ * * CGIUTILS.H - Header file for common CGI functions - * Copyright (c) 1999-2008 Ethan Galstad (egalstad@nagios.org) - * Last Modified: 10-15-2008 * * License: * @@ -20,9 +18,9 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ************************************************************************/ -#ifndef _CGIUTILS_H -#define _CGIUTILS_H -#include "compat.h" +#ifndef NAGIOS_CGIUTILS_H_INCLUDED +#define NAGIOS_CGIUTILS_H_INCLUDED +#include "lib/libnagios.h" #include "logging.h" #include "objects.h" #include "cgiauth.h" @@ -37,7 +35,12 @@ NAGIOS_BEGIN_DECL /******************************* CGI NAMES **********************************/ #define STATUS_CGI "status.cgi" +#ifdef LEGACY_GRAPHICAL_CGIS #define STATUSMAP_CGI "statusmap.cgi" +#else +#define STATUSMAP_CGI "../map.php" +#define LEGACY_STATUSMAP_CGI "statusmap.cgi" +#endif #define STATUSWORLD_CGI "statuswrl.cgi" #define COMMAND_CGI "cmd.cgi" #define EXTINFO_CGI "extinfo.cgi" @@ -46,12 +49,22 @@ NAGIOS_BEGIN_DECL #define HISTORY_CGI "history.cgi" #define CONFIG_CGI "config.cgi" #define OUTAGES_CGI "outages.cgi" +#ifdef LEGACY_GRAPHICAL_CGIS #define TRENDS_CGI "trends.cgi" +#else +#define TRENDS_CGI "../trends.html" +#define LEGACY_TRENDS_CGI "trends.cgi" +#endif #define AVAIL_CGI "avail.cgi" #define TAC_CGI "tac.cgi" #define STATUSWML_CGI "statuswml.cgi" #define TRACEROUTE_CGI "traceroute.cgi" +#ifdef LEGACY_GRAPHICAL_CGIS #define HISTOGRAM_CGI "histogram.cgi" +#else +#define HISTOGRAM_CGI "../histogram.html" +#define LEGACY_HISTOGRAM_CGI "histogram.cgi" +#endif #define CHECKSANITY_CGI "checksanity.cgi" #define MINISTATUS_CGI "ministatus.cgi" #define SUMMARY_CGI "summary.cgi" @@ -59,27 +72,29 @@ NAGIOS_BEGIN_DECL /**************************** STYLE SHEET NAMES ******************************/ -#define COMMON_CSS "common.css" +#define COMMON_CSS "common.css" -#define SHOWLOG_CSS "showlog.css" -#define STATUS_CSS "status.css" -#define STATUSMAP_CSS "statusmap.css" -#define COMMAND_CSS "cmd.css" -#define EXTINFO_CSS "extinfo.css" -#define NOTIFICATIONS_CSS "notifications.css" -#define HISTORY_CSS "history.css" -#define CONFIG_CSS "config.css" -#define OUTAGES_CSS "outages.css" -#define TRENDS_CSS "trends.css" -#define AVAIL_CSS "avail.css" -#define TAC_CSS "tac.css" -#define HISTOGRAM_CSS "histogram.css" -#define CHECKSANITY_CSS "checksanity.css" -#define MINISTATUS_CSS "ministatus.css" -#define SUMMARY_CSS "summary.css" +#define SHOWLOG_CSS "showlog.css" +#define STATUS_CSS "status.css" +#define STATUSMAP_CSS "statusmap.css" +#define COMMAND_CSS "cmd.css" +#define EXTINFO_CSS "extinfo.css" +#define NOTIFICATIONS_CSS "notifications.css" +#define HISTORY_CSS "history.css" +#define CONFIG_CSS "config.css" +#define OUTAGES_CSS "outages.css" +#define TRENDS_CSS "trends.css" +#define AVAIL_CSS "avail.css" +#define TAC_CSS "tac.css" +#define HISTOGRAM_CSS "histogram.css" +#define CHECKSANITY_CSS "checksanity.css" +#define MINISTATUS_CSS "ministatus.css" +#define SUMMARY_CSS "summary.css" +#define NAGFUNCS_CSS "nag_funcs.css" /********************************* JAVASCRIPT INCLUDES **********************/ -#define JQUERY_JS "jquery-1.7.1.min.js" +#define JQUERY_JS "jquery-1.7.1.min.js" +#define NAGFUNCS_JS "nag_funcs.js" /********************************* ICONS ************************************/ @@ -185,14 +200,6 @@ NAGIOS_BEGIN_DECL #define PREVIOUS_PAGE_ICON "b_prev2.png" - /************************** PLUGIN RETURN VALUES ****************************/ - -#define STATE_OK 0 -#define STATE_WARNING 1 -#define STATE_CRITICAL 2 -#define STATE_UNKNOWN 3 /* changed from -1 on 02/24/2001 */ - - /********************* EXTENDED INFO CGI DISPLAY TYPES *********************/ #define DISPLAY_PROCESS_INFO 0 @@ -232,6 +239,8 @@ NAGIOS_BEGIN_DECL #define NOTIFICATION_HOST_FLAP 4096 #define NOTIFICATION_SERVICE_CUSTOM 8192 #define NOTIFICATION_HOST_CUSTOM 16384 +#define NOTIFICATION_SERVICE_DOWNTIME 32768 +#define NOTIFICATION_HOST_DOWNTIME 65536 /********************** HOST AND SERVICE ALERT TYPES **********************/ @@ -433,15 +442,16 @@ typedef struct lifo_struct { /******************************** FUNCTIONS *******************************/ void reset_cgi_vars(void); +void cgi_init(void (*doc_header)(int), void (*doc_footer)(void), int object_options, int status_options); void free_memory(void); -char *get_cgi_config_location(void); /* gets location of the CGI config file to read */ -char *get_cmd_file_location(void); /* gets location of external command file to write to */ +const char *get_cgi_config_location(void); /* gets location of the CGI config file to read */ +const char *get_cmd_file_location(void); /* gets location of external command file to write to */ -int read_cgi_config_file(char *); -int read_main_config_file(char *); -int read_all_object_configuration_data(char *, int); -int read_all_status_data(char *, int); +int read_cgi_config_file(const char *); +int read_main_config_file(const char *); +int read_all_object_configuration_data(const char *, int); +int read_all_status_data(const char *, int); char *unescape_newlines(char *); void sanitize_plugin_output(char *); /* strips HTML and bad characters from plugin output */ @@ -450,9 +460,9 @@ void strip_html_brackets(char *); /* strips > and < from string */ void get_time_string(time_t *, char *, int, int); /* gets a date/time string */ void get_interval_time_string(double, char *, int); /* gets a time string for an interval of time */ -char *url_encode(char *); /* encodes a string in proper URL format */ +const char *url_encode(const char *); /* encodes a string in proper URL format */ char *html_encode(char *, int); /* encodes a string in HTML format (for what the user sees) */ -char *escape_string(char *); /* escape string for html form usage */ +char *escape_string(const char *); /* escape string for html form usage */ void get_log_archive_to_use(int, char *, int); /* determines the name of the log archive to use */ void determine_log_rotation_times(int); @@ -461,7 +471,7 @@ int determine_archive_to_use_from_time(time_t); void print_extra_hostgroup_url(char *, char *); void print_extra_servicegroup_url(char *, char *); -void display_info_table(char *, int, authdata *); +void display_info_table(const char *, int, authdata *); void display_nav_table(char *, int); void display_splunk_host_url(host *); @@ -469,15 +479,15 @@ void display_splunk_service_url(service *); void display_splunk_generic_url(char *, int); void strip_splunk_query_terms(char *); -void include_ssi_files(char *, int); /* include user-defined SSI footers/headers */ -void include_ssi_file(char *); /* include user-defined SSI footer/header */ +void include_ssi_files(const char *, int); /* include user-defined SSI footers/headers */ +void include_ssi_file(const char *); /* include user-defined SSI footer/header */ -void cgi_config_file_error(char *); -void main_config_file_error(char *); +void cgi_config_file_error(const char *); +void main_config_file_error(const char *); void object_data_error(void); void status_data_error(void); -void display_context_help(char *); /* displays context-sensitive help window */ +void display_context_help(const char *); /* displays context-sensitive help window */ int read_file_into_lifo(char *); /* LIFO functions */ void free_lifo_memory(void); diff --git a/include/comments.h b/include/comments.h index 9ea8fa3..91f337c 100644 --- a/include/comments.h +++ b/include/comments.h @@ -2,8 +2,6 @@ * * COMMENTS.H - Header file for comment functions * - * Copyright (c) 1999-2006 Ethan Galstad (egalstad@nagios.org) - * Last Modified: 12-26-2006 * * License: * @@ -23,9 +21,8 @@ *****************************************************************************/ -#ifndef _COMMENTS_H -#define _COMMENTS_H -#include "compat.h" +#ifndef NAGIOS_COMMENTS_H_INCLUDED +#define NAGIOS_COMMENTS_H_INCLUDED #include "common.h" #include "objects.h" @@ -61,7 +58,7 @@ NAGIOS_BEGIN_DECL /* COMMENT structure */ -typedef struct comment_struct { +typedef struct nagios_comment { int comment_type; int entry_type; unsigned long comment_id; @@ -74,14 +71,14 @@ typedef struct comment_struct { char *service_description; char *author; char *comment_data; - struct comment_struct *next; - struct comment_struct *nexthash; - } comment; + struct nagios_comment *next; + struct nagios_comment *nexthash; + } nagios_comment; +extern struct nagios_comment *comment_list; -#ifdef NSCORE -int initialize_comment_data(char *); /* initializes comment data */ -int cleanup_comment_data(char *); /* cleans up comment data */ +#ifndef NSCGI +int initialize_comment_data(void); /* initializes comment data */ int add_new_comment(int, int, char *, char *, time_t, char *, char *, int, int, int, time_t, unsigned long *); /* adds a new host or service comment */ int add_new_host_comment(int, char *, time_t, char *, char *, int, int, int, time_t, unsigned long *); /* adds a new host comment */ int add_new_service_comment(int, char *, char *, time_t, char *, char *, int, int, int, time_t, unsigned long *); /* adds a new service comment */ @@ -90,34 +87,29 @@ int delete_host_comment(unsigned long); /* deletes a int delete_service_comment(unsigned long); /* deletes a service comment */ int delete_all_comments(int, char *, char *); /* deletes all comments for a particular host or service */ int delete_all_host_comments(char *); /* deletes all comments for a specific host */ -int delete_host_acknowledgement_comments(host *); /* deletes all non-persistent ack comments for a specific host */ +int delete_host_acknowledgement_comments(struct host *); /* deletes all non-persistent ack comments for a specific host */ int delete_all_service_comments(char *, char *); /* deletes all comments for a specific service */ -int delete_service_acknowledgement_comments(service *); /* deletes all non-persistent ack comments for a specific service */ +int delete_service_acknowledgement_comments(struct service *); /* deletes all non-persistent ack comments for a specific service */ int check_for_expired_comment(unsigned long); /* expires a comment */ #endif -comment *find_comment(unsigned long, int); /* finds a specific comment */ -comment *find_service_comment(unsigned long); /* finds a specific service comment */ -comment *find_host_comment(unsigned long); /* finds a specific host comment */ +struct nagios_comment *find_comment(unsigned long, int); /* finds a specific comment */ +struct nagios_comment *find_service_comment(unsigned long); /* finds a specific service comment */ +struct nagios_comment *find_host_comment(unsigned long); /* finds a specific host comment */ -comment *get_first_comment_by_host(char *); -comment *get_next_comment_by_host(char *, comment *); +struct nagios_comment *get_first_comment_by_host(char *); +struct nagios_comment *get_next_comment_by_host(char *, struct nagios_comment *); int number_of_host_comments(char *); /* returns the number of comments associated with a particular host */ int number_of_service_comments(char *, char *); /* returns the number of comments associated with a particular service */ -/* If you are going to be adding a lot of comments in sequence, set - defer_comment_sorting to 1 before you start and then call - sort_comments afterwards. Things will go MUCH faster. */ - -extern int defer_comment_sorting; int add_comment(int, int, char *, char *, time_t, char *, char *, unsigned long, int, int, time_t, int); /* adds a comment (host or service) */ int sort_comments(void); int add_host_comment(int, char *, time_t, char *, char *, unsigned long, int, int, time_t, int); /* adds a host comment */ int add_service_comment(int, char *, char *, time_t, char *, char *, unsigned long, int, int, time_t, int); /* adds a service comment */ -int add_comment_to_hashlist(comment *); +int add_comment_to_hashlist(struct nagios_comment *); void free_comment_data(void); /* frees memory allocated to the comment list */ diff --git a/include/common.h b/include/common.h index 84fd102..c113b65 100644 --- a/include/common.h +++ b/include/common.h @@ -2,7 +2,6 @@ * * Nagios Common Header File * Written By: Ethan Galstad (egalstad@nagios.org) - * Last Modified: 10-22-2007 * * License: * @@ -20,33 +19,82 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ************************************************************************/ +#ifndef NAGIOS_COMMON_H_INCLUDED +#define NAGIOS_COMMON_H_INCLUDED + #include "shared.h" -#define PROGRAM_VERSION "3.5.1" -#define PROGRAM_MODIFICATION_DATE "08-30-2013" +#define PROGRAM_VERSION "4.3.2" +#define PROGRAM_MODIFICATION_DATE "2017-05-09" -/*#define DEBUG_CHECK_IPC 1 */ -/*#define DEBUG_CHECK_IPC2 1*/ +NAGIOS_BEGIN_DECL +/*************************************************************/ +/************** SHARED GLOBAL VARIABLES **********************/ +/*************************************************************/ +extern int date_format; +extern int interval_length; +extern char *illegal_output_chars; +extern char illegal_output_char_map[256]; +extern int log_rotation_method; +extern int check_external_commands; +/* set this if you're going to add a ton of comments at once */ +extern int defer_comment_sorting; +extern unsigned long next_downtime_id; -/* daemon is thread safe */ -#ifdef NSCORE -#ifndef _REENTRANT -#define _REENTRANT -#endif -#ifndef _THREAD_SAFE -#define _THREAD_SAFE +extern char *object_cache_file; +extern char *status_file; + +extern time_t program_start; +extern int nagios_pid; +extern int daemon_mode; + +extern time_t last_log_rotation; + +extern int process_performance_data; +extern int enable_flap_detection; +extern int enable_notifications; +extern int execute_service_checks; +extern int accept_passive_service_checks; +extern int execute_host_checks; +extern int accept_passive_host_checks; +extern int enable_event_handlers; +extern int obsess_over_services; +extern int obsess_over_hosts; + +extern int enable_timing_point; + +extern char *config_file_dir; + +#ifdef HAVE_TZNAME +#ifdef CYGWIN +extern char *_tzname[2] __declspec(dllimport); +#else +extern char *tzname[2]; #endif #endif + +NAGIOS_END_DECL + + /* Experimental performance tweaks - use with caution */ #undef USE_MEMORY_PERFORMANCE_TWEAKS -/* my_free has been freed from bondage as a function */ -#define my_free(ptr) do { if(ptr) { free(ptr); ptr = NULL; } } while(0) - +/****************** OBJECT STATES ********************/ +#define STATE_OK 0 +#define STATE_WARNING 1 +#define STATE_CRITICAL 2 +#define STATE_UNKNOWN 3 +#define STATE_UP 0 +#define STATE_DOWN 1 +#define STATE_UNREACHABLE 2 +/* for legacy reasons */ +#define HOST_UP STATE_UP +#define HOST_DOWN STATE_DOWN +#define HOST_UNREACHABLE STATE_UNREACHABLE /***************************** COMMANDS *********************************/ @@ -151,26 +199,20 @@ #define CMD_ENABLE_HOSTGROUP_SVC_CHECKS 67 #define CMD_DISABLE_HOSTGROUP_SVC_CHECKS 68 -#define CMD_CANCEL_HOST_DOWNTIME 69 /* not internally implemented */ -#define CMD_CANCEL_SVC_DOWNTIME 70 /* not internally implemented */ - -#define CMD_CANCEL_ACTIVE_HOST_DOWNTIME 71 /* old - no longer used */ -#define CMD_CANCEL_PENDING_HOST_DOWNTIME 72 /* old - no longer used */ - -#define CMD_CANCEL_ACTIVE_SVC_DOWNTIME 73 /* old - no longer used */ -#define CMD_CANCEL_PENDING_SVC_DOWNTIME 74 /* old - no longer used */ - -#define CMD_CANCEL_ACTIVE_HOST_SVC_DOWNTIME 75 /* unimplemented */ -#define CMD_CANCEL_PENDING_HOST_SVC_DOWNTIME 76 /* unimplemented */ - -#define CMD_FLUSH_PENDING_COMMANDS 77 +/* commands 69-77 are unimplemented */ +#define CMD_UNIMPLEMENTED_69 69 +#define CMD_UNIMPLEMENTED_70 70 +#define CMD_UNIMPLEMENTED_71 71 +#define CMD_UNIMPLEMENTED_72 72 +#define CMD_UNIMPLEMENTED_73 73 +#define CMD_UNIMPLEMENTED_74 74 +#define CMD_UNIMPLEMENTED_75 75 +#define CMD_UNIMPLEMENTED_76 76 +#define CMD_UNIMPLEMENTED_77 77 #define CMD_DEL_HOST_DOWNTIME 78 #define CMD_DEL_SVC_DOWNTIME 79 -#define CMD_ENABLE_FAILURE_PREDICTION 80 -#define CMD_DISABLE_FAILURE_PREDICTION 81 - #define CMD_ENABLE_PERFORMANCE_DATA 82 #define CMD_DISABLE_PERFORMANCE_DATA 83 @@ -304,21 +346,37 @@ #define CMD_DEL_DOWNTIME_BY_HOSTGROUP_NAME 171 #define CMD_DEL_DOWNTIME_BY_START_TIME_COMMENT 172 +/* new commands in Nagios 4.x found below... */ +#define CMD_CLEAR_HOST_FLAPPING_STATE 173 +#define CMD_CLEAR_SVC_FLAPPING_STATE 174 + /* custom command introduced in Nagios 3.x */ #define CMD_CUSTOM_COMMAND 999 +/**************************** COMMAND ERRORS *****************************/ +#define CMD_ERROR_OK 0 /* No errors encountered */ +#define CMD_ERROR_UNKNOWN_COMMAND 1 /* Unknown/unsupported command */ +#define CMD_ERROR_MALFORMED_COMMAND 2 /* Command malformed/missing timestamp? */ +#define CMD_ERROR_INTERNAL_ERROR 3 /* Internal error */ +#define CMD_ERROR_FAILURE 4 /* Command routine failed */ + +extern const char *cmd_error_strerror(int error_code); + +/**************************** CHECK TYPES ********************************/ + +#define CHECK_TYPE_ACTIVE 0 +#define CHECK_TYPE_PASSIVE 1 +#define CHECK_TYPE_PARENT 2 /* (active) check for the benefit of dependent objects */ +#define CHECK_TYPE_FILE 3 /* from spool files (yuck) */ +#define CHECK_TYPE_OTHER 4 /* for modules to use */ -/************************ SERVICE CHECK TYPES ****************************/ +/************* LEGACY (deprecated) CHECK TYPES ***************************/ -#define SERVICE_CHECK_ACTIVE 0 /* Nagios performed the service check */ -#define SERVICE_CHECK_PASSIVE 1 /* the service check result was submitted by an external source */ - - -/************************** HOST CHECK TYPES *****************************/ - -#define HOST_CHECK_ACTIVE 0 /* Nagios performed the host check */ -#define HOST_CHECK_PASSIVE 1 /* the host check result was submitted by an external source */ +#define SERVICE_CHECK_ACTIVE CHECK_TYPE_ACTIVE +#define SERVICE_CHECK_PASSIVE CHECK_TYPE_PASSIVE +#define HOST_CHECK_ACTIVE CHECK_TYPE_ACTIVE +#define HOST_CHECK_PASSIVE CHECK_TYPE_PASSIVE /************************ SERVICE STATE TYPES ****************************/ @@ -365,6 +423,7 @@ #define CHECK_OPTION_FORCE_EXECUTION 1 /* force execution of a check (ignores disabled services/hosts, invalid timeperiods) */ #define CHECK_OPTION_FRESHNESS_CHECK 2 /* this is a freshness check */ #define CHECK_OPTION_ORPHAN_CHECK 4 /* this is an orphan check */ +#define CHECK_OPTION_DEPENDENCY_CHECK 8 /* dependency check. different scheduling rules apply */ /**************************** PROGRAM MODES ******************************/ @@ -405,24 +464,6 @@ #define MAX_CHECK_STATS_TYPES 11 -/************************* GENERAL DEFINITIONS **************************/ - -#define OK 0 -#define ERROR -2 /* value was changed from -1 so as to not interfere with STATUS_UNKNOWN plugin result */ - - -#ifndef TRUE -#define TRUE 1 -#elif (TRUE!=1) -#define TRUE 1 -#endif -#ifndef FALSE -#define FALSE 0 -#elif (FALSE!=0) -#define FALSE 0 -#endif - - /****************** HOST CONFIG FILE READING OPTIONS ********************/ #define READ_HOSTS 1 @@ -444,16 +485,6 @@ #define READ_ALL_OBJECT_DATA READ_HOSTS | READ_HOSTGROUPS | READ_CONTACTS | READ_CONTACTGROUPS | READ_SERVICES | READ_COMMANDS | READ_TIMEPERIODS | READ_SERVICEESCALATIONS | READ_SERVICEDEPENDENCIES | READ_HOSTDEPENDENCIES | READ_HOSTESCALATIONS | READ_HOSTEXTINFO | READ_SERVICEEXTINFO | READ_SERVICEGROUPS -/************************** DATE RANGE TYPES ****************************/ - -#define DATERANGE_CALENDAR_DATE 0 /* 2008-12-25 */ -#define DATERANGE_MONTH_DATE 1 /* july 4 (specific month) */ -#define DATERANGE_MONTH_DAY 2 /* day 21 (generic month) */ -#define DATERANGE_MONTH_WEEK_DAY 3 /* 3rd thursday (specific month) */ -#define DATERANGE_WEEK_DAY 4 /* 3rd thursday (generic month) */ -#define DATERANGE_TYPES 5 - - /************************** DATE/TIME TYPES *****************************/ #define LONG_DATE_TIME 0 @@ -501,3 +532,4 @@ #define MODATTR_CHECK_TIMEPERIOD 16384 #define MODATTR_CUSTOM_VARIABLE 32768 #define MODATTR_NOTIFICATION_TIMEPERIOD 65536 +#endif /* NAGIOS_COMMON_H_INCLUDED */ diff --git a/include/compat.h b/include/compat.h deleted file mode 100644 index cf7dd27..0000000 --- a/include/compat.h +++ /dev/null @@ -1,19 +0,0 @@ -/* compatibility macros, primarily to keep indentation programs - * from going bananas when indenting everything below - #ifdef __cplusplus - 'extern "C" {' - #endif - * as if it was a real block, which is just godsdamn annoying. - */ -#ifndef _COMPAT_H -#define _COMPAT_H - -#ifdef __cplusplus -# define NAGIOS_BEGIN_DECL extern "C" { -# define NAGIOS_END_DECL } -#else -# define NAGIOS_BEGIN_DECL /* nothing */ -# define NAGIOS_END_DECL /* more of nothing */ -#endif - -#endif /* _COMPAT_H */ diff --git a/include/config.h.in b/include/config.h.in index 22fc438..bc80050 100644 --- a/include/config.h.in +++ b/include/config.h.in @@ -2,7 +2,6 @@ * * Nagios Config Header File * Written By: Ethan Galstad (egalstad@nagios.org) - * Last Modified: 11-02-2008 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -30,12 +29,6 @@ /* Event broker integration */ #undef USE_EVENT_BROKER -/* Embed a PERL interpreter into Nagios with optional cache for compiled code (contributed by Stephen Davies) */ -#undef EMBEDDEDPERL -#undef THREADEDPERL -/* 0 = cache, 1 = do not cache */ -#define DO_CLEAN "1" - /* commands used by CGIs */ #undef TRACEROUTE_COMMAND #undef PING_COMMAND @@ -87,6 +80,7 @@ #undef HAVE_INITGROUPS #undef HAVE_GETLOADAVG #undef HAVE_GDIMAGECREATETRUECOLOR +#undef HAVE_SIGACTION @@ -147,9 +141,9 @@ #undef HAVE_PWD_H #ifdef HAVE_PWD_H -#include +#include "config_pwd.h" #endif - + #undef HAVE_GRP_H #ifdef HAVE_GRP_H #include @@ -200,6 +194,15 @@ #include #endif +/* Another Solarisism: getloadavg() lives in , not , + * so include the former if it exists. This may be true on other systems, or + * this function may be missing altogether (see: + * https://www.gnu.org/software/gnulib/manual/html_node/getloadavg.html). */ +#undef HAVE_SYS_LOADAVG_H +#ifdef HAVE_SYS_LOADAVG_H +#include +#endif + #undef HAVE_SYS_TYPES_H #ifdef HAVE_SYS_TYPES_H #include @@ -245,11 +248,6 @@ #include #endif -#undef HAVE_PTHREAD_H -#ifdef HAVE_PTHREAD_H -#include -#endif - #undef HAVE_REGEX_H #ifdef HAVE_REGEX_H #include @@ -314,6 +312,11 @@ #include #endif +#undef HAVE_SYS_PRCTL_H +#ifdef HAVE_SYS_PRCTL_H +#include +#endif + /* configure script should allow user to override ltdl choice, but this will do for now... */ #undef USE_LTDL #undef HAVE_LTDL_H diff --git a/include/config_pwd.h b/include/config_pwd.h new file mode 100644 index 0000000..20fdbd4 --- /dev/null +++ b/include/config_pwd.h @@ -0,0 +1,23 @@ +#ifndef NAGIOS_CONFIG_PWD_H_INCLUDED +#define NAGIOS_CONFIG_PWD_H_INCLUDED +/** + * @file include/config_pwd.h + * A wrapper header to let us conditionally define and then undefine + * __XOPEN_OR_POSIX to suppress the conflicting 'struct comment' declaration on + * Solaris. We can't do this in config.h.in since the undef will be commented + * out when config.h is generated. + */ + +#if defined(__sun) && defined(__SVR4) && !defined(__XOPEN_OR_POSIX) +#define __XOPEN_OR_POSIX +#define NEED_TO_UNDEF__XOPEN_OR_POSIX +#endif + +#include + +#if defined(NEED_TO_UNDEF__XOPEN_OR_POSIX) +#undef __XOPEN_OR_POSIX +#undef NEED_TO_UNDEF__XOPEN_OR_POSIX +#endif + +#endif diff --git a/include/defaults.h b/include/defaults.h new file mode 100644 index 0000000..a2e05b3 --- /dev/null +++ b/include/defaults.h @@ -0,0 +1,94 @@ +#ifndef NAGIOS_DEFAULTS_H_INCLUDED +#define NAGIOS_DEFAULTS_H_INCLUDED + +/******************* DEFAULT VALUES *******************/ + +#define DEFAULT_LOG_LEVEL 1 /* log all events to main log file */ +#define DEFAULT_USE_SYSLOG 1 /* log events to syslog? 1=yes, 0=no */ +#define DEFAULT_SYSLOG_LEVEL 2 /* log only severe events to syslog */ + +#define DEFAULT_NOTIFICATION_LOGGING 1 /* log notification events? 1=yes, 0=no */ + +#define DEFAULT_INTER_CHECK_DELAY 5.0 /* seconds between initial service check scheduling */ +#define DEFAULT_INTERLEAVE_FACTOR 1 /* default interleave to use when scheduling checks */ +#define DEFAULT_RETRY_INTERVAL 30 /* services are retried in 30 seconds if they're not OK */ +#define DEFAULT_CHECK_REAPER_INTERVAL 10 /* interval in seconds to reap host and service check results */ +#define DEFAULT_MAX_REAPER_TIME 30 /* maximum number of seconds to spend reaping service checks before we break out for a while */ +#define DEFAULT_MAX_CHECK_RESULT_AGE 3600 /* maximum number of seconds that a check result file is considered to be valid */ +#define DEFAULT_MAX_PARALLEL_SERVICE_CHECKS 0 /* maximum number of service checks we can have running at any given time (0=unlimited) */ +#define DEFAULT_RETENTION_UPDATE_INTERVAL 60 /* minutes between auto-save of retention data */ +#define DEFAULT_RETENTION_SCHEDULING_HORIZON 900 /* max seconds between program restarts that we will preserve scheduling information */ +#define DEFAULT_STATUS_UPDATE_INTERVAL 60 /* seconds between aggregated status data updates */ +#define DEFAULT_FRESHNESS_CHECK_INTERVAL 60 /* seconds between service result freshness checks */ +#define DEFAULT_AUTO_RESCHEDULING_INTERVAL 30 /* seconds between host and service check rescheduling events */ +#define DEFAULT_AUTO_RESCHEDULING_WINDOW 180 /* window of time (in seconds) for which we should reschedule host and service checks */ +#define DEFAULT_ORPHAN_CHECK_INTERVAL 60 /* seconds between checks for orphaned hosts and services */ + +#define DEFAULT_INTERVAL_LENGTH 60 /* seconds per interval unit for check scheduling */ + +#define DEFAULT_NOTIFICATION_TIMEOUT 30 /* max time in seconds to wait for notification commands to complete */ +#define DEFAULT_EVENT_HANDLER_TIMEOUT 30 /* max time in seconds to wait for event handler commands to complete */ +#define DEFAULT_HOST_CHECK_TIMEOUT 30 /* max time in seconds to wait for host check commands to complete */ +#define DEFAULT_SERVICE_CHECK_TIMEOUT 60 /* max time in seconds to wait for service check commands to complete */ +#define DEFAULT_OCSP_TIMEOUT 15 /* max time in seconds to wait for obsessive compulsive processing commands to complete */ +#define DEFAULT_OCHP_TIMEOUT 15 /* max time in seconds to wait for obsessive compulsive processing commands to complete */ +#define DEFAULT_PERFDATA_TIMEOUT 5 /* max time in seconds to wait for performance data commands to complete */ +#define DEFAULT_TIME_CHANGE_THRESHOLD 900 /* compensate for time changes of more than 15 minutes */ + +#define DEFAULT_LOG_HOST_RETRIES 0 /* don't log host retries */ +#define DEFAULT_LOG_SERVICE_RETRIES 0 /* don't log service retries */ +#define DEFAULT_LOG_EVENT_HANDLERS 1 /* log event handlers */ +#define DEFAULT_LOG_INITIAL_STATES 0 /* don't log initial service and host states */ +#define DEFAULT_LOG_CURRENT_STATES 1 /* log current service and host states after rotating log */ +#define DEFAULT_LOG_EXTERNAL_COMMANDS 1 /* log external commands */ +#define DEFAULT_LOG_PASSIVE_CHECKS 1 /* log passive service checks */ + +#define DEFAULT_DEBUG_LEVEL 0 /* don't log any debugging information */ +#define DEFAULT_DEBUG_VERBOSITY 1 +#define DEFAULT_MAX_DEBUG_FILE_SIZE 1000000 /* max size of debug log */ + +#define DEFAULT_AGGRESSIVE_HOST_CHECKING 0 /* don't use "aggressive" host checking */ +#define DEFAULT_CHECK_EXTERNAL_COMMANDS 1 /* check for external commands */ +#define DEFAULT_CHECK_ORPHANED_SERVICES 1 /* check for orphaned services */ +#define DEFAULT_CHECK_ORPHANED_HOSTS 1 /* check for orphaned hosts */ +#define DEFAULT_ENABLE_FLAP_DETECTION 0 /* don't enable flap detection */ +#define DEFAULT_PROCESS_PERFORMANCE_DATA 0 /* don't process performance data */ +#define DEFAULT_CHECK_SERVICE_FRESHNESS 1 /* check service result freshness */ +#define DEFAULT_CHECK_HOST_FRESHNESS 0 /* don't check host result freshness */ +#define DEFAULT_AUTO_RESCHEDULE_CHECKS 0 /* don't auto-reschedule host and service checks */ +#define DEFAULT_TRANSLATE_PASSIVE_HOST_CHECKS 0 /* should we translate DOWN/UNREACHABLE passive host checks? */ +#define DEFAULT_PASSIVE_HOST_CHECKS_SOFT 0 /* passive host checks are treated as HARD by default */ + +#define DEFAULT_LOW_SERVICE_FLAP_THRESHOLD 20.0 /* low threshold for detection of service flapping */ +#define DEFAULT_HIGH_SERVICE_FLAP_THRESHOLD 30.0 /* high threshold for detection of service flapping */ +#define DEFAULT_LOW_HOST_FLAP_THRESHOLD 20.0 /* low threshold for detection of host flapping */ +#define DEFAULT_HIGH_HOST_FLAP_THRESHOLD 30.0 /* high threshold for detection of host flapping */ + +#define DEFAULT_HOST_CHECK_SPREAD 30 /* max minutes to schedule all initial host checks */ +#define DEFAULT_SERVICE_CHECK_SPREAD 30 /* max minutes to schedule all initial service checks */ + +#define DEFAULT_CACHED_HOST_CHECK_HORIZON 15 /* max age in seconds that cached host checks can be used */ +#define DEFAULT_CACHED_SERVICE_CHECK_HORIZON 15 /* max age in seconds that cached service checks can be used */ +#define DEFAULT_ENABLE_PREDICTIVE_HOST_DEPENDENCY_CHECKS 1 /* should we use predictive host dependency checks? */ +#define DEFAULT_ENABLE_PREDICTIVE_SERVICE_DEPENDENCY_CHECKS 1 /* should we use predictive service dependency checks? */ + +#define DEFAULT_USE_LARGE_INSTALLATION_TWEAKS 0 /* don't use tweaks for large Nagios installations */ + +#define DEFAULT_ADDITIONAL_FRESHNESS_LATENCY 15 /* seconds to be added to freshness thresholds when automatically calculated by Nagios */ + +#define DEFAULT_CHECK_FOR_UPDATES 1 /* should we check for new Nagios releases? */ +#define DEFAULT_BARE_UPDATE_CHECK 0 /* report current version and new installs */ +#define MINIMUM_UPDATE_CHECK_INTERVAL 60*60*22 /* 22 hours minimum between checks - please be kind to our servers! */ +#define BASE_UPDATE_CHECK_INTERVAL 60*60*22 /* 22 hours base interval */ +#define UPDATE_CHECK_INTERVAL_WOBBLE 60*60*4 /* 4 hour wobble on top of base interval */ +#define BASE_UPDATE_CHECK_RETRY_INTERVAL 60*60*1 /* 1 hour base retry interval */ +#define UPDATE_CHECK_RETRY_INTERVAL_WOBBLE 60*60*3 /* 3 hour wobble on top of base retry interval */ + +#define DEFAULT_ALLOW_EMPTY_HOSTGROUP_ASSIGNMENT 2 /* Allow assigning to empty hostgroups by default, but warn about it */ + +#define DEFAULT_HOST_PERFDATA_FILE_TEMPLATE "[HOSTPERFDATA]\t$TIMET$\t$HOSTNAME$\t$HOSTEXECUTIONTIME$\t$HOSTOUTPUT$\t$HOSTPERFDATA$" +#define DEFAULT_SERVICE_PERFDATA_FILE_TEMPLATE "[SERVICEPERFDATA]\t$TIMET$\t$HOSTNAME$\t$SERVICEDESC$\t$SERVICEEXECUTIONTIME$\t$SERVICELATENCY$\t$SERVICEOUTPUT$\t$SERVICEPERFDATA$" +#define DEFAULT_HOST_PERFDATA_PROCESS_EMPTY_RESULTS 1 +#define DEFAULT_SERVICE_PERFDATA_PROCESS_EMPTY_RESULTS 1 + +#endif /* NAGIOS_DEFAULTS_H_INCLUDED */ diff --git a/include/downtime.h b/include/downtime.h index e9b873b..4bee3d2 100644 --- a/include/downtime.h +++ b/include/downtime.h @@ -2,8 +2,6 @@ * * DOWNTIME.H - Header file for scheduled downtime functions * - * Copyright (c) 2001-2005 Ethan Galstad (egalstad@nagios.org) - * Last Modified: 11-25-2005 * * License: * @@ -23,17 +21,19 @@ *****************************************************************************/ -#ifndef _DOWNTIME_H -#define _DOWNTIME_H +#ifndef NAGIOS_DOWNTIME_H_INCLUDED +#define NAGIOS_DOWNTIME_H_INCLUDED -#include "compat.h" #include "common.h" #include "objects.h" +#ifndef NSCGI +#include "nagios.h" +#endif NAGIOS_BEGIN_DECL /* SCHEDULED_DOWNTIME_ENTRY structure */ -typedef struct scheduled_downtime_struct { +typedef struct scheduled_downtime { int type; char *host_name; char *service_description; @@ -49,22 +49,25 @@ typedef struct scheduled_downtime_struct { int start_notification_sent; char *author; char *comment; -#ifdef NSCORE unsigned long comment_id; +#ifndef NSCGI int start_flex_downtime; int incremented_pending_downtime; -// int start_event; -// int stop_event; #endif - struct scheduled_downtime_struct *next; + struct scheduled_downtime *next; +#ifndef NSCGI + struct timed_event *start_event, *stop_event; +#endif + struct scheduled_downtime *prev; } scheduled_downtime; +extern struct scheduled_downtime *scheduled_downtime_list; -#ifdef NSCORE -int initialize_downtime_data(char *); /* initializes scheduled downtime data */ -int cleanup_downtime_data(char *); /* cleans up scheduled downtime data */ +int initialize_downtime_data(void); /* initializes scheduled downtime data */ +int cleanup_downtime_data(void); /* cleans up scheduled downtime data */ +#ifndef NSCGI int add_new_downtime(int, char *, char *, time_t, char *, char *, time_t, time_t, int, unsigned long, unsigned long, unsigned long *, int, int); int add_new_host_downtime(char *, time_t, char *, char *, time_t, time_t, int, unsigned long, unsigned long, unsigned long *, int, int); int add_new_service_downtime(char *, char *, time_t, char *, char *, time_t, time_t, int, unsigned long, unsigned long, unsigned long *, int, int); @@ -77,11 +80,13 @@ int schedule_downtime(int, char *, char *, time_t, char *, char *, time_t, time_ int unschedule_downtime(int, unsigned long); int register_downtime(int, unsigned long); -int handle_scheduled_downtime(scheduled_downtime *); +int handle_scheduled_downtime(struct scheduled_downtime *); int handle_scheduled_downtime_by_id(unsigned long); -int check_pending_flex_host_downtime(host *); -int check_pending_flex_service_downtime(service *); +int check_pending_flex_host_downtime(struct host *); +int check_pending_flex_service_downtime(struct service *); +int is_host_in_pending_flex_downtime(struct host *); +int is_service_in_pending_flex_downtime(struct service *); int check_for_expired_downtime(void); #endif @@ -97,9 +102,9 @@ extern int defer_downtime_sorting; int add_downtime(int, char *, char *, time_t, char *, char *, time_t, time_t, time_t, int, unsigned long, unsigned long, unsigned long, int, int); int sort_downtime(void); -scheduled_downtime *find_downtime(int, unsigned long); -scheduled_downtime *find_host_downtime(unsigned long); -scheduled_downtime *find_service_downtime(unsigned long); +struct scheduled_downtime *find_downtime(int, unsigned long); +struct scheduled_downtime *find_host_downtime(unsigned long); +struct scheduled_downtime *find_service_downtime(unsigned long); void free_downtime_data(void); /* frees memory allocated to scheduled downtime list */ diff --git a/include/epn_nagios.h b/include/epn_nagios.h deleted file mode 100644 index 2399afe..0000000 --- a/include/epn_nagios.h +++ /dev/null @@ -1,34 +0,0 @@ -/************************************************************************ - * - * Embedded Perl Header File - * Last Modified: 01-15-2009 - * - ************************************************************************/ - - -/******** BEGIN EMBEDDED PERL INTERPRETER DECLARATIONS ********/ - -#include -#include - -#include -#undef DEBUG /* epn-compiled Nagios spews just - this has a side effect of potentially disabling debug output on epn systems */ -#undef ctime /* don't need perl's threaded version */ -#undef printf /* can't use perl's printf until initialized */ - -/* In perl.h (or friends) there is a macro that defines sighandler as Perl_sighandler, so we must #undef it so we can use our sighandler() function */ -#undef sighandler - -/* and we don't need perl's reentrant versions */ -#undef localtime -#undef getpwnam -#undef getgrnam -#undef strerror - -#ifdef aTHX -EXTERN_C void xs_init(pTHX); -#else -EXTERN_C void xs_init(void); -#endif - -/******** END EMBEDDED PERL INTERPRETER DECLARATIONS ********/ diff --git a/include/getcgi.h b/include/getcgi.h index 7cbb8db..76d8014 100644 --- a/include/getcgi.h +++ b/include/getcgi.h @@ -2,16 +2,15 @@ * * GETCGI.H - Nagios CGI Input Routine Include File * - * Last Modified: 11-25-2005 * *****************************************************/ -#include "compat.h" +#include "lib/lnag-utils.h" NAGIOS_BEGIN_DECL #define ACCEPT_LANGUAGE_Q_DELIMITER ";q=" -/* information for a single language in the variable HTTP_ACCEPT_LANGUAGE +/* information for a single language in the variable HTTP_ACCEPT_LANGUAGE sent by the browser */ typedef struct accept_language_struct { char * language; @@ -19,7 +18,7 @@ typedef struct accept_language_struct { double q; } accept_language; -/* information for all languages in the variable HTTP_ACCEPT_LANGUAGE +/* information for all languages in the variable HTTP_ACCEPT_LANGUAGE sent by the browser */ typedef struct accept_languages_struct { int count; diff --git a/include/jsonutils.h b/include/jsonutils.h new file mode 100644 index 0000000..b6756a1 --- /dev/null +++ b/include/jsonutils.h @@ -0,0 +1,227 @@ +/************************************************************************** + * + * JSONUTILS.H - Utility information for Nagios CGI for that return + * JSON-formatted data + * + * Copyright (c) 2013 Nagios Enterprises, LLC + * Last Modified: 04-13-2013 + * + * License: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + *************************************************************************/ + +#ifndef NAGIOS_JSONUTILS_H_INCLUDED +#define NAGIOS_JSONUTILS_H_INCLUDED + +/* JSON object definitions */ +#define JSON_TYPE_INVALID 0 +#define JSON_TYPE_OBJECT 1 +#define JSON_TYPE_ARRAY 2 +#define JSON_TYPE_INTEGER 3 +#define JSON_TYPE_REAL 4 +#define JSON_TYPE_TIME_T 5 +#define JSON_TYPE_STRING 6 +#define JSON_TYPE_BOOLEAN 7 +#define JSON_TYPE_DURATION 8 + +struct json_object_struct; + +typedef struct json_object_member_struct { + char *key; + unsigned type; + union { + long long integer; + unsigned long long unsigned_integer; + time_t time; + double real; + char * string; + unsigned boolean; + struct json_object_struct *object; + } value; + } json_object_member; + +typedef struct json_object_struct { + unsigned member_count; + json_object_member **members; + } json_object; + +typedef json_object json_array; + +/* Mapping from CGI query string option to value */ +typedef struct string_value_mapping_struct { + char *string; /* String to map from */ + unsigned value; /* Value to map to */ + char *description; /* Description of the meaning of the + string/value */ + } string_value_mapping; + +typedef struct option_help_struct { + const char * name; /* name used in query */ + const char * label; /* short label for name */ + const char * type; /* option type */ + /* If the type is of the form nagios:/, value values + for this option will be obtained by sending the query + 'http:///.cgi?objecttype=' */ + const char * required[25]; /* optiontypes required + for */ + const char * optional[25]; /* optiontypes optional + for */ + const char * depends_on; /* valid values dependent on + other option */ + const char * description; /* longer description */ + const string_value_mapping * valid_values; /* list of valid values */ + } option_help; + +/* String escaping structures */ +typedef struct json_escape_pair_struct { + const wchar_t *from; + const wchar_t *to; +} json_escape_pair; + +typedef struct json_escape_struct { + const int count; + const json_escape_pair *pairs; +} json_escape; + +/* Output Format Version */ +#define OUTPUT_FORMAT_VERSION 0 + +/* Result Types */ +#define RESULT_SUCCESS 0 +#define RESULT_MEMORY_ALLOCATION_ERROR 1 +#define RESULT_FILE_OPEN_READ_ERROR 2 +#define RESULT_OPTION_INVALID 3 +#define RESULT_OPTION_MISSING 4 +#define RESULT_OPTION_VALUE_MISSING 5 +#define RESULT_OPTION_VALUE_INVALID 6 +#define RESULT_OPTION_IGNORED 7 + +/* Boolean Values - Used when selecting true, false, or both */ +#define BOOLEAN_TRUE 1 +#define BOOLEAN_FALSE 2 +#define BOOLEAN_EITHER (BOOLEAN_TRUE | BOOLEAN_FALSE) + +/* Formatting Options */ +#define JSON_FORMAT_WHITESPACE (1<<0) +#define JSON_FORMAT_ENUMERATE (1<<1) +#define JSON_FORMAT_BITMASK (1<<2) +#define JSON_FORMAT_DURATION (1<<3) +#if 0 +#define JSON_FORMAT_DATETIME (1<<3) +#define JSON_FORMAT_DATE (1<<4) +#define JSON_FORMAT_TIME (1<<5) +#endif + +/* Possible Query Statuses */ +#define QUERY_STATUS_ALPHA 0 +#define QUERY_STATUS_BETA 1 +#define QUERY_STATUS_RELEASED 2 +#define QUERY_STATUS_DEPRECATED 3 + +extern const string_value_mapping svm_format_options[]; +extern const string_value_mapping svm_host_statuses[]; +extern const string_value_mapping svm_host_states[]; +extern const string_value_mapping svm_service_statuses[]; +extern const string_value_mapping svm_service_states[]; +extern const string_value_mapping svm_check_options[]; +extern const string_value_mapping svm_host_check_types[]; +extern const string_value_mapping svm_service_check_types[]; +extern const string_value_mapping svm_state_types[]; +extern const string_value_mapping svm_acknowledgement_types[]; +extern const string_value_mapping svm_comment_types[]; +extern const string_value_mapping svm_comment_entry_types[]; +extern const string_value_mapping svm_downtime_types[]; +extern const string_value_mapping parent_host_extras[]; +extern const string_value_mapping child_host_extras[]; +extern const string_value_mapping parent_service_extras[]; +extern const string_value_mapping child_service_extras[]; +#ifdef JSON_NAGIOS_4X +extern const string_value_mapping svm_option_types[]; +#endif + +extern const char *dayofweek[]; +extern const char *month[]; + +extern json_object *json_new_object(void); +extern void json_free_object(json_object *, int); +extern json_array *json_new_array(void); +extern void json_free_member(json_object_member *, int); +extern void json_object_append_object(json_object *, char *, json_object *); +extern void json_object_append_array(json_object *, char *, json_array *); +extern void json_object_append_integer(json_object *, char *, int); +extern void json_object_append_real(json_object *, char *, double); +extern void json_object_append_time(json_object *, char *, unsigned long); +extern void json_object_append_time_t(json_object *, char *, time_t); +extern void json_set_time_t(json_object_member *, time_t); +extern void json_object_append_string(json_object *, char *, + const json_escape *, char *, ...); +extern void json_object_append_boolean(json_object *, char *, int); +extern void json_array_append_object(json_array *, json_object *); +extern void json_array_append_array(json_array *, json_array *); +extern void json_array_append_integer(json_array *, int); +extern void json_array_append_real(json_array *, double); +extern void json_array_append_time(json_array *, unsigned long); +extern void json_array_append_time_t(json_array *, time_t); +extern void json_array_append_string(json_array *, const json_escape *, + char *, ...); +extern void json_array_append_boolean(json_array *, int); +extern void json_object_append_duration(json_object *, char *, unsigned long); +extern void json_array_append_duration(json_object *, unsigned long); +extern json_object_member *json_get_object_member(json_object *, char *); +extern json_object_member *json_get_array_member(json_object *, char *); +extern void json_object_print(json_object *, int, int, char *, unsigned); +extern void json_array_print(json_array *, int, int, char *, unsigned); +extern void json_member_print(json_object_member *, int, int, char *, unsigned); + +extern json_object *json_result(time_t, char *, char *, int, time_t, authdata *, + int, char *, ...); +extern json_object *json_help(option_help *); +extern int passes_start_and_count_limits(int, int, int, int); +extern void indentf(int, int, char *, ...); +extern void json_string(int, int, char *, char *); +extern void json_boolean(int, int, char *, int); +extern void json_int(int, int, char *, int); +extern void json_unsigned(int, int, char *, unsigned long long); +extern void json_float(int, int, char *, double); +extern void json_time(int, int, char *, unsigned long); +extern void json_time_t(int, int, char *, time_t, char *); +extern void json_duration(int, int, char *, unsigned long, int); + +extern void json_enumeration(json_object *, unsigned, char *, int, + const string_value_mapping *); +extern void json_bitmask(json_object *, unsigned, char *, int, + const string_value_mapping *); + +extern int parse_bitmask_cgivar(char *, char *, int, json_object *, time_t, + authdata *, char *, char *, const string_value_mapping *, unsigned *); +extern int parse_enumeration_cgivar(char *, char *, int, json_object *, + time_t, authdata *, char *, char *, const string_value_mapping *, + int *); +extern int parse_string_cgivar(char *, char *, int, json_object *, time_t, + authdata *, char *, char *, char **); +extern int parse_time_cgivar(char *, char *, int, json_object *, time_t, + authdata *, char *, char *, time_t *); +extern int parse_boolean_cgivar(char *, char *, int, json_object *, time_t, + authdata *, char *, char *, int *); +extern int parse_int_cgivar(char *, char *, int, json_object *, time_t, + authdata *, char *, char *, int *); + +extern int get_query_status(const int[][2], int); +extern char *svm_get_string_from_value(int, const string_value_mapping *); +extern char *svm_get_description_from_value(int, const string_value_mapping *); + +extern time_t compile_time(const char *, const char *); +extern char *json_escape_string(const char *, const json_escape *); +#endif diff --git a/include/locations.h.in b/include/locations.h.in index c8516e8..889c1de 100644 --- a/include/locations.h.in +++ b/include/locations.h.in @@ -2,7 +2,6 @@ * * Nagios Locations Header File * Written By: Ethan Galstad (egalstad@nagios.org) - * Last Modified: 04-30-2007 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -29,6 +28,7 @@ #define DEFAULT_DOWNTIME_FILE "@localstatedir@/downtime.dat" #define DEFAULT_RETENTION_FILE "@localstatedir@/retention.dat" #define DEFAULT_COMMAND_FILE "@localstatedir@/rw/nagios.cmd" +#define DEFAULT_QUERY_SOCKET "@localstatedir@/rw/nagios.qh" #define DEFAULT_CONFIG_FILE "@sysconfdir@/nagios.cfg" #define DEFAULT_PHYSICAL_HTML_PATH "@datadir@" #define DEFAULT_URL_HTML_PATH "@htmurl@" @@ -39,5 +39,3 @@ #define DEFAULT_OBJECT_CACHE_FILE "@localstatedir@/objects.cache" #define DEFAULT_PRECACHED_OBJECT_FILE "@localstatedir@/objects.precache" #define DEFAULT_EVENT_BROKER_FILE "@localstatedir@/broker.socket" -#define DEFAULT_P1_FILE "@bindir@/p1.pl" /**** EMBEDDED PERL ****/ -#define DEFAULT_AUTH_FILE "" /**** EMBEDDED PERL - IS THIS USED? ****/ diff --git a/include/logging.h b/include/logging.h index bf14837..4a86fb2 100644 --- a/include/logging.h +++ b/include/logging.h @@ -1,7 +1,6 @@ -#ifndef INCLUDE_logging_h__ -#define INCLUDE_logging_h__ +#ifndef NAGIOS_LOGGING_H_INCLUDED +#define NAGIOS_LOGGING_H_INCLUDED -#include "compat.h" #include "objects.h" /******************* LOGGING TYPES ********************/ @@ -47,7 +46,6 @@ #define DEBUGL_RETENTIONDATA 4 #define DEBUGL_EVENTS 8 #define DEBUGL_CHECKS 16 -#define DEBUGL_IPC 16 #define DEBUGL_FLAPPING 16 #define DEBUGL_EVENTHANDLERS 16 #define DEBUGL_PERFDATA 16 @@ -58,6 +56,8 @@ #define DEBUGL_DOWNTIME 512 #define DEBUGL_COMMENTS 1024 #define DEBUGL_MACROS 2048 +#define DEBUGL_IPC 4096 +#define DEBUGL_SCHEDULING 8192 #define DEBUGV_BASIC 0 #define DEBUGV_MORE 1 @@ -81,8 +81,9 @@ int log_service_states(int, time_t *); /* logs initial/current int rotate_log_file(time_t); /* rotates the main log file */ int write_log_file_info(time_t *); /* records log file/version info */ int open_debug_log(void); -int chown_debug_log(uid_t, gid_t); int close_debug_log(void); +int close_log_file(void); +int fix_log_file_owner(uid_t uid, gid_t gid); #endif /* !NSCGI */ NAGIOS_END_DECL diff --git a/include/macros.h b/include/macros.h index aca43f1..94bc0a5 100644 --- a/include/macros.h +++ b/include/macros.h @@ -2,7 +2,6 @@ * * MACROS.H - Common macro functions * Written By: Ethan Galstad (egalstad@nagios.org) - * Last Modified: 10-28-2007 * * License: * @@ -20,10 +19,9 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ************************************************************************/ -#ifndef _MACROS_H -#define _MACROS_H +#ifndef NAGIOS_MACROS_H_INCLUDED +#define NAGIOS_MACROS_H_INCLUDED -#include "compat.h" #include "common.h" #include "objects.h" @@ -40,7 +38,7 @@ #define MAX_USER_MACROS 256 /* maximum number of $USERx$ macros */ -#define MACRO_X_COUNT 153 /* size of macro_x[] array */ +#define MACRO_X_COUNT 157 /* size of macro_x[] array */ NAGIOS_BEGIN_DECL @@ -216,7 +214,10 @@ typedef struct nagios_macros nagios_macros; #define MACRO_LASTHOSTSTATEID 150 #define MACRO_LASTSERVICESTATE 151 #define MACRO_LASTSERVICESTATEID 152 - +#define MACRO_HOSTIMPORTANCE 153 +#define MACRO_SERVICEIMPORTANCE 154 +#define MACRO_HOSTANDSERVICESIMPORTANCE 155 +#define MACRO_HOSTGROUPMEMBERADDRESSES 156 /************* MACRO CLEANING OPTIONS *****************/ @@ -275,6 +276,8 @@ int grab_servicegroup_macros_r(nagios_macros *mac, servicegroup *); int grab_hostgroup_macros_r(nagios_macros *mac, hostgroup *); int grab_contact_macros_r(nagios_macros *mac, contact *); +int grab_argv_macros_r(nagios_macros *mac, char *check_command); + int grab_macro_value_r(nagios_macros *mac, char *, char **, int *, int *); int grab_macrox_value_r(nagios_macros *mac, int, char *, char *, char **, int *); int grab_custom_macro_value_r(nagios_macros *mac, char *, char *, char *, char **); @@ -316,9 +319,10 @@ int clear_servicegroup_macros_r(nagios_macros *mac); int clear_contact_macros_r(nagios_macros *mac); int clear_contactgroup_macros_r(nagios_macros *mac); int clear_summary_macros_r(nagios_macros *mac); +int clear_datetime_macros_r(nagios_macros *mac); -#ifdef NSCORE +#ifndef NSCGI int set_all_macro_environment_vars(int); int set_macrox_environment_vars(int); int set_argv_macro_environment_vars(int); diff --git a/include/nagios.h b/include/nagios.h index 4fda64b..7a6823b 100644 --- a/include/nagios.h +++ b/include/nagios.h @@ -2,7 +2,6 @@ * * Nagios Main Header File * Written By: Ethan Galstad (egalstad@nagios.org) - * Last Modified: 12-14-2008 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -18,23 +17,251 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ************************************************************************/ -#ifndef _NAGIOS_H -#define _NAGIOS_H +#ifndef NAGIOS_NAGIOS_H_INCLUDED +#define NAGIOS_NAGIOS_H_INCLUDED -#ifndef __GNUC__ -# define __attribute__(x) /* nothing */ -#endif #ifndef NSCORE # define NSCORE #endif -#include "compat.h" -#include "logging.h" +#include "defaults.h" #include "common.h" +#include "logging.h" #include "locations.h" #include "objects.h" #include "macros.h" +/* + * global variables only used in the core. Reducing this list would be + * a Good Thing(tm). + */ +extern char *nagios_binary_path; +extern char *config_file; +extern char *command_file; +extern char *temp_file; +extern char *temp_path; +extern char *check_result_path; +extern char *lock_file; +extern char *object_precache_file; + +extern unsigned int nofile_limit, nproc_limit, max_apps; + +extern int num_check_workers; +extern char *qh_socket_path; + +extern char *nagios_user; +extern char *nagios_group; + +extern char *macro_user[MAX_USER_MACROS]; + +extern char *ocsp_command; +extern char *ochp_command; +extern command *ocsp_command_ptr; +extern command *ochp_command_ptr; +extern int ocsp_timeout; +extern int ochp_timeout; + +extern char *global_host_event_handler; +extern char *global_service_event_handler; +extern command *global_host_event_handler_ptr; +extern command *global_service_event_handler_ptr; + +extern char *illegal_object_chars; + +extern int use_regexp_matches; +extern int use_true_regexp_matching; + +extern int use_syslog; +extern char *log_file; +extern char *log_archive_path; +extern int log_notifications; +extern int log_service_retries; +extern int log_host_retries; +extern int log_event_handlers; +extern int log_external_commands; +extern int log_passive_checks; +extern unsigned long logging_options; +extern unsigned long syslog_options; + +extern int service_check_timeout; +extern int service_check_timeout_state; +extern int host_check_timeout; +extern int event_handler_timeout; +extern int notification_timeout; + +extern int log_initial_states; +extern int log_current_states; + +extern int daemon_dumps_core; +extern int sig_id; +extern int caught_signal; + + +extern int verify_config; +extern int test_scheduling; +extern int precache_objects; +extern int use_precached_objects; + +extern int service_inter_check_delay_method; +extern int host_inter_check_delay_method; +extern int service_interleave_factor_method; +extern int max_host_check_spread; +extern int max_service_check_spread; + +extern sched_info scheduling_info; + +extern int max_parallel_service_checks; + +extern int check_reaper_interval; +extern int max_check_reaper_time; +extern int service_freshness_check_interval; +extern int host_freshness_check_interval; +extern int auto_rescheduling_interval; +extern int auto_rescheduling_window; + +extern int check_orphaned_services; +extern int check_orphaned_hosts; +extern int check_service_freshness; +extern int check_host_freshness; +extern int auto_reschedule_checks; + +extern int additional_freshness_latency; + +extern int check_for_updates; +extern int bare_update_check; +extern time_t last_update_check; +extern unsigned long update_uid; +extern int update_available; +extern char *last_program_version; +extern char *new_program_version; + +extern int use_aggressive_host_checking; +extern time_t cached_host_check_horizon; +extern time_t cached_service_check_horizon; +extern int enable_predictive_host_dependency_checks; +extern int enable_predictive_service_dependency_checks; + +extern int soft_state_dependencies; + +extern int retain_state_information; +extern int retention_update_interval; +extern int use_retained_program_state; +extern int use_retained_scheduling_info; +extern int retention_scheduling_horizon; +extern char *retention_file; +extern unsigned long retained_host_attribute_mask; +extern unsigned long retained_service_attribute_mask; +extern unsigned long retained_contact_host_attribute_mask; +extern unsigned long retained_contact_service_attribute_mask; +extern unsigned long retained_process_host_attribute_mask; +extern unsigned long retained_process_service_attribute_mask; + +extern int translate_passive_host_checks; +extern int passive_host_checks_are_soft; + +extern int status_update_interval; +extern char *retention_file; + +extern int time_change_threshold; + +extern unsigned long event_broker_options; + +extern double low_service_flap_threshold; +extern double high_service_flap_threshold; +extern double low_host_flap_threshold; +extern double high_host_flap_threshold; + +extern int use_large_installation_tweaks; +extern int enable_environment_macros; +extern int free_child_process_memory; +extern int child_processes_fork_twice; + +extern char *use_timezone; + +extern time_t max_check_result_file_age; + +extern char *debug_file; +extern int debug_level; +extern int debug_verbosity; +extern unsigned long max_debug_file_size; + +extern int allow_empty_hostgroup_assignment; + +extern int host_down_disable_service_checks; + +extern time_t last_program_stop; +extern time_t event_start; + +extern int sigshutdown, sigrestart; +extern int currently_running_service_checks; +extern int currently_running_host_checks; + +extern unsigned long next_event_id; +extern unsigned long next_problem_id; +extern unsigned long next_comment_id; +extern unsigned long next_notification_id; + +extern unsigned long modified_process_attributes; +extern unsigned long modified_host_process_attributes; +extern unsigned long modified_service_process_attributes; + +extern squeue_t *nagios_squeue; +extern iobroker_set *nagios_iobs; + +extern struct check_stats check_statistics[MAX_CHECK_STATS_TYPES]; + +/*** perfdata variables ***/ +extern int perfdata_timeout; +extern char *host_perfdata_command; +extern char *service_perfdata_command; +extern char *host_perfdata_file_template; +extern char *service_perfdata_file_template; +extern char *host_perfdata_file; +extern char *service_perfdata_file; +extern int host_perfdata_file_append; +extern int service_perfdata_file_append; +extern int host_perfdata_file_pipe; +extern int service_perfdata_file_pipe; +extern unsigned long host_perfdata_file_processing_interval; +extern unsigned long service_perfdata_file_processing_interval; +extern char *host_perfdata_file_processing_command; +extern char *service_perfdata_file_processing_command; +extern int host_perfdata_process_empty_results; +extern int service_perfdata_process_empty_results; +/*** end perfdata variables */ + +extern struct notify_list *notification_list; + +extern struct check_engine nagios_check_engine; + +/* + * Everything we need to keep system load in check. + * Don't use this from modules. + */ +struct load_control { + time_t last_check; /* last time we checked the real load */ + time_t last_change; /* last time we changed settings */ + time_t check_interval; /* seconds between load checks */ + double load[3]; /* system load, as reported by getloadavg() */ + float backoff_limit; /* limit we must reach before we back off */ + float rampup_limit; /* limit we must reach before we ramp back up */ + unsigned int backoff_change; /* backoff by this much */ + unsigned int rampup_change; /* ramp up by this much */ + unsigned int changes; /* number of times we've changed settings */ + unsigned int jobs_max; /* upper setting for jobs_limit */ + unsigned int jobs_limit; /* current limit */ + unsigned int jobs_min; /* lower setting for jobs_limit */ + unsigned int jobs_running; /* jobs currently running */ + unsigned int nproc_limit; /* rlimit for user processes */ + unsigned int nofile_limit; /* rlimit for open files */ + unsigned int options; /* various option flags */ +}; +extern struct load_control loadctl; + +/* options for load control */ +#define LOADCTL_ENABLED (1 << 0) + + /************* MISC LENGTH/SIZE DEFINITIONS ***********/ /* @@ -46,103 +273,6 @@ #define MAX_PLUGIN_OUTPUT_LENGTH 8192 /* max length of plugin output (including perf data) */ - - /******************* DEFAULT VALUES *******************/ - -#define DEFAULT_LOG_LEVEL 1 /* log all events to main log file */ -#define DEFAULT_USE_SYSLOG 1 /* log events to syslog? 1=yes, 0=no */ -#define DEFAULT_SYSLOG_LEVEL 2 /* log only severe events to syslog */ - -#define DEFAULT_NOTIFICATION_LOGGING 1 /* log notification events? 1=yes, 0=no */ - -#define DEFAULT_INTER_CHECK_DELAY 5.0 /* seconds between initial service check scheduling */ -#define DEFAULT_INTERLEAVE_FACTOR 1 /* default interleave to use when scheduling checks */ -#define DEFAULT_SLEEP_TIME 0.5 /* seconds between event run checks */ -#define DEFAULT_INTERVAL_LENGTH 60 /* seconds per interval unit for check scheduling */ -#define DEFAULT_RETRY_INTERVAL 30 /* services are retried in 30 seconds if they're not OK */ -#define DEFAULT_COMMAND_CHECK_INTERVAL -1 /* interval to check for external commands (default = as often as possible) */ -#define DEFAULT_CHECK_REAPER_INTERVAL 10 /* interval in seconds to reap host and service check results */ -#define DEFAULT_MAX_REAPER_TIME 30 /* maximum number of seconds to spend reaping service checks before we break out for a while */ -#define DEFAULT_MAX_CHECK_RESULT_AGE 3600 /* maximum number of seconds that a check result file is considered to be valid */ -#define DEFAULT_MAX_PARALLEL_SERVICE_CHECKS 0 /* maximum number of service checks we can have running at any given time (0=unlimited) */ -#define DEFAULT_RETENTION_UPDATE_INTERVAL 60 /* minutes between auto-save of retention data */ -#define DEFAULT_RETENTION_SCHEDULING_HORIZON 900 /* max seconds between program restarts that we will preserve scheduling information */ -#define DEFAULT_STATUS_UPDATE_INTERVAL 60 /* seconds between aggregated status data updates */ -#define DEFAULT_FRESHNESS_CHECK_INTERVAL 60 /* seconds between service result freshness checks */ -#define DEFAULT_AUTO_RESCHEDULING_INTERVAL 30 /* seconds between host and service check rescheduling events */ -#define DEFAULT_AUTO_RESCHEDULING_WINDOW 180 /* window of time (in seconds) for which we should reschedule host and service checks */ -#define DEFAULT_ORPHAN_CHECK_INTERVAL 60 /* seconds between checks for orphaned hosts and services */ - -#define DEFAULT_NOTIFICATION_TIMEOUT 30 /* max time in seconds to wait for notification commands to complete */ -#define DEFAULT_EVENT_HANDLER_TIMEOUT 30 /* max time in seconds to wait for event handler commands to complete */ -#define DEFAULT_HOST_CHECK_TIMEOUT 30 /* max time in seconds to wait for host check commands to complete */ -#define DEFAULT_SERVICE_CHECK_TIMEOUT 60 /* max time in seconds to wait for service check commands to complete */ -#define DEFAULT_OCSP_TIMEOUT 15 /* max time in seconds to wait for obsessive compulsive processing commands to complete */ -#define DEFAULT_OCHP_TIMEOUT 15 /* max time in seconds to wait for obsessive compulsive processing commands to complete */ -#define DEFAULT_PERFDATA_TIMEOUT 5 /* max time in seconds to wait for performance data commands to complete */ -#define DEFAULT_TIME_CHANGE_THRESHOLD 900 /* compensate for time changes of more than 15 minutes */ - -#define DEFAULT_LOG_HOST_RETRIES 0 /* don't log host retries */ -#define DEFAULT_LOG_SERVICE_RETRIES 0 /* don't log service retries */ -#define DEFAULT_LOG_EVENT_HANDLERS 1 /* log event handlers */ -#define DEFAULT_LOG_INITIAL_STATES 0 /* don't log initial service and host states */ -#define DEFAULT_LOG_EXTERNAL_COMMANDS 1 /* log external commands */ -#define DEFAULT_LOG_PASSIVE_CHECKS 1 /* log passive service checks */ - -#define DEFAULT_DEBUG_LEVEL 0 /* don't log any debugging information */ -#define DEFAULT_DEBUG_VERBOSITY 1 -#define DEFAULT_MAX_DEBUG_FILE_SIZE 1000000 /* max size of debug log */ - -#define DEFAULT_AGGRESSIVE_HOST_CHECKING 0 /* don't use "aggressive" host checking */ -#define DEFAULT_CHECK_EXTERNAL_COMMANDS 1 /* check for external commands */ -#define DEFAULT_CHECK_ORPHANED_SERVICES 1 /* check for orphaned services */ -#define DEFAULT_CHECK_ORPHANED_HOSTS 1 /* check for orphaned hosts */ -#define DEFAULT_ENABLE_FLAP_DETECTION 0 /* don't enable flap detection */ -#define DEFAULT_PROCESS_PERFORMANCE_DATA 0 /* don't process performance data */ -#define DEFAULT_CHECK_SERVICE_FRESHNESS 1 /* check service result freshness */ -#define DEFAULT_CHECK_HOST_FRESHNESS 0 /* don't check host result freshness */ -#define DEFAULT_AUTO_RESCHEDULE_CHECKS 0 /* don't auto-reschedule host and service checks */ -#define DEFAULT_TRANSLATE_PASSIVE_HOST_CHECKS 0 /* should we translate DOWN/UNREACHABLE passive host checks? */ -#define DEFAULT_PASSIVE_HOST_CHECKS_SOFT 0 /* passive host checks are treated as HARD by default */ - -#define DEFAULT_LOW_SERVICE_FLAP_THRESHOLD 20.0 /* low threshold for detection of service flapping */ -#define DEFAULT_HIGH_SERVICE_FLAP_THRESHOLD 30.0 /* high threshold for detection of service flapping */ -#define DEFAULT_LOW_HOST_FLAP_THRESHOLD 20.0 /* low threshold for detection of host flapping */ -#define DEFAULT_HIGH_HOST_FLAP_THRESHOLD 30.0 /* high threshold for detection of host flapping */ - -#define DEFAULT_HOST_CHECK_SPREAD 30 /* max minutes to schedule all initial host checks */ -#define DEFAULT_SERVICE_CHECK_SPREAD 30 /* max minutes to schedule all initial service checks */ - -#define DEFAULT_CACHED_HOST_CHECK_HORIZON 15 /* max age in seconds that cached host checks can be used */ -#define DEFAULT_CACHED_SERVICE_CHECK_HORIZON 15 /* max age in seconds that cached service checks can be used */ -#define DEFAULT_ENABLE_PREDICTIVE_HOST_DEPENDENCY_CHECKS 1 /* should we use predictive host dependency checks? */ -#define DEFAULT_ENABLE_PREDICTIVE_SERVICE_DEPENDENCY_CHECKS 1 /* should we use predictive service dependency checks? */ - -#define DEFAULT_USE_LARGE_INSTALLATION_TWEAKS 0 /* don't use tweaks for large Nagios installations */ - -#define DEFAULT_ENABLE_EMBEDDED_PERL 0 /* enable embedded Perl interpreter (if compiled in) */ -#define DEFAULT_USE_EMBEDDED_PERL_IMPLICITLY 1 /* by default, embedded Perl is used for Perl plugins that don't explicitly disable it */ - -#define DEFAULT_ADDITIONAL_FRESHNESS_LATENCY 15 /* seconds to be added to freshness thresholds when automatically calculated by Nagios */ - -#define DEFAULT_CHECK_FOR_UPDATES 1 /* should we check for new Nagios releases? */ -#define DEFAULT_BARE_UPDATE_CHECK 0 /* report current version and new installs */ -#define MINIMUM_UPDATE_CHECK_INTERVAL 60*60*22 /* 22 hours minimum between checks - please be kind to our servers! */ -#define BASE_UPDATE_CHECK_INTERVAL 60*60*22 /* 22 hours base interval */ -#define UPDATE_CHECK_INTERVAL_WOBBLE 60*60*4 /* 4 hour wobble on top of base interval */ -#define BASE_UPDATE_CHECK_RETRY_INTERVAL 60*60*1 /* 1 hour base retry interval */ -#define UPDATE_CHECK_RETRY_INTERVAL_WOBBLE 60*60*3 /* 3 hour wobble on top of base retry interval */ - -#define DEFAULT_ALLOW_EMPTY_HOSTGROUP_ASSIGNMENT 0 /* Do not allow empty hostgroups by default */ - - /******************** HOST STATUS *********************/ - -#define HOST_UP 0 -#define HOST_DOWN 1 -#define HOST_UNREACHABLE 2 - - - /******************* STATE LOGGING TYPES **************/ #define INITIAL_STATES 1 @@ -164,15 +294,6 @@ - /****************** SERVICE STATES ********************/ - -#define STATE_OK 0 -#define STATE_WARNING 1 -#define STATE_CRITICAL 2 -#define STATE_UNKNOWN 3 /* changed from -1 on 02/24/2001 */ - - - /****************** FLAPPING TYPES ********************/ #define HOST_FLAPPING 0 @@ -197,7 +318,7 @@ #define NOTIFICATION_DOWNTIMESTART 5 #define NOTIFICATION_DOWNTIMEEND 6 #define NOTIFICATION_DOWNTIMECANCELLED 7 -#define NOTIFICATION_CUSTOM 99 +#define NOTIFICATION_CUSTOM 8 @@ -245,30 +366,36 @@ #define EVENT_SLEEP 98 /* asynchronous sleep event that occurs when event queues are empty */ #define EVENT_USER_FUNCTION 99 /* USER-defined function (modules) */ -#define EVENT_TYPE_STR( type) ( \ - type == EVENT_SERVICE_CHECK ? "EVENT_SERVICE_CHECK" : \ - type == EVENT_COMMAND_CHECK ? "EVENT_COMMAND_CHECK" : \ - type == EVENT_LOG_ROTATION ? "EVENT_LOG_ROTATION" : \ - type == EVENT_PROGRAM_SHUTDOWN ? "EVENT_PROGRAM_SHUTDOWN" : \ - type == EVENT_PROGRAM_RESTART ? "EVENT_PROGRAM_RESTART" : \ - type == EVENT_CHECK_REAPER ? "EVENT_CHECK_REAPER" : \ - type == EVENT_ORPHAN_CHECK ? "EVENT_ORPHAN_CHECK" : \ - type == EVENT_RETENTION_SAVE ? "EVENT_RETENTION_SAVE" : \ - type == EVENT_STATUS_SAVE ? "EVENT_STATUS_SAVE" : \ - type == EVENT_SCHEDULED_DOWNTIME ? "EVENT_SCHEDULED_DOWNTIME" : \ - type == EVENT_SFRESHNESS_CHECK ? "EVENT_SFRESHNESS_CHECK" : \ - type == EVENT_EXPIRE_DOWNTIME ? "EVENT_EXPIRE_DOWNTIME" : \ - type == EVENT_HOST_CHECK ? "EVENT_HOST_CHECK" : \ - type == EVENT_HFRESHNESS_CHECK ? "EVENT_HFRESHNESS_CHECK" : \ - type == EVENT_RESCHEDULE_CHECKS ? "EVENT_RESCHEDULE_CHECKS" : \ - type == EVENT_EXPIRE_COMMENT ? "EVENT_EXPIRE_COMMENT" : \ - type == EVENT_CHECK_PROGRAM_UPDATE ? "EVENT_CHECK_PROGRAM_UPDATE" : \ - type == EVENT_SLEEP ? "EVENT_SLEEP" : \ - type == EVENT_USER_FUNCTION ? "EVENT_USER_FUNCTION" : \ - "UNKNOWN_EVENT_TYPE" \ +/* + * VERSIONFIX: Make EVENT_SLEEP and EVENT_USER_FUNCTION appear + * linearly in order. + */ + +#define EVENT_TYPE_STR(type) ( \ + type == EVENT_SERVICE_CHECK ? "SERVICE_CHECK" : \ + type == EVENT_COMMAND_CHECK ? "COMMAND_CHECK" : \ + type == EVENT_LOG_ROTATION ? "LOG_ROTATION" : \ + type == EVENT_PROGRAM_SHUTDOWN ? "PROGRAM_SHUTDOWN" : \ + type == EVENT_PROGRAM_RESTART ? "PROGRAM_RESTART" : \ + type == EVENT_CHECK_REAPER ? "CHECK_REAPER" : \ + type == EVENT_ORPHAN_CHECK ? "ORPHAN_CHECK" : \ + type == EVENT_RETENTION_SAVE ? "RETENTION_SAVE" : \ + type == EVENT_STATUS_SAVE ? "STATUS_SAVE" : \ + type == EVENT_SCHEDULED_DOWNTIME ? "SCHEDULED_DOWNTIME" : \ + type == EVENT_SFRESHNESS_CHECK ? "SFRESHNESS_CHECK" : \ + type == EVENT_EXPIRE_DOWNTIME ? "EXPIRE_DOWNTIME" : \ + type == EVENT_HOST_CHECK ? "HOST_CHECK" : \ + type == EVENT_HFRESHNESS_CHECK ? "HFRESHNESS_CHECK" : \ + type == EVENT_RESCHEDULE_CHECKS ? "RESCHEDULE_CHECKS" : \ + type == EVENT_EXPIRE_COMMENT ? "EXPIRE_COMMENT" : \ + type == EVENT_CHECK_PROGRAM_UPDATE ? "CHECK_PROGRAM_UPDATE" : \ + type == EVENT_SLEEP ? "SLEEP" : \ + type == EVENT_USER_FUNCTION ? "USER_FUNCTION" : \ + "UNKNOWN" \ ) + /******* INTER-CHECK DELAY CALCULATION TYPES **********/ #define ICD_NONE 0 /* no inter-check delay */ @@ -291,143 +418,54 @@ #define PENDING_DOWNTIME 1 /* pending downtime - scheduled for the future */ - - /****************** DATA STRUCTURES *******************/ - NAGIOS_BEGIN_DECL -/* TIMED_EVENT structure */ -typedef struct timed_event_struct { - int event_type; - time_t run_time; - int recurring; - unsigned long event_interval; - int compensate_for_time_change; - void *timing_func; - void *event_data; - void *event_args; - int event_options; - struct timed_event_struct *next; - struct timed_event_struct *prev; - } timed_event; - - -/* NOTIFY_LIST structure */ -typedef struct notify_list_struct { - contact *contact; - struct notify_list_struct *next; - } notification; - - -/* CHECK_RESULT structure */ -typedef struct check_result_struct { - int object_check_type; /* is this a service or a host check? */ - char *host_name; /* host name */ - char *service_description; /* service description */ - int check_type; /* was this an active or passive service check? */ - int check_options; - int scheduled_check; /* was this a scheduled or an on-demand check? */ - int reschedule_check; /* should we reschedule the next check */ - char *output_file; /* what file is the output stored in? */ - FILE *output_file_fp; - int output_file_fd; - double latency; - struct timeval start_time; /* time the service check was initiated */ - struct timeval finish_time; /* time the service check was completed */ - int early_timeout; /* did the service check timeout? */ - int exited_ok; /* did the plugin check return okay? */ - int return_code; /* plugin return code */ - char *output; /* plugin output */ - struct check_result_struct *next; - } check_result; - - -/* SCHED_INFO structure */ -typedef struct sched_info_struct { - int total_services; - int total_scheduled_services; - int total_hosts; - int total_scheduled_hosts; - double average_services_per_host; - double average_scheduled_services_per_host; - unsigned long service_check_interval_total; - unsigned long host_check_interval_total; - double average_service_execution_time; - double average_service_check_interval; - double average_host_check_interval; - double average_service_inter_check_delay; - double average_host_inter_check_delay; - double service_inter_check_delay; - double host_inter_check_delay; - int service_interleave_factor; - int max_service_check_spread; - int max_host_check_spread; - time_t first_service_check; - time_t last_service_check; - time_t first_host_check; - time_t last_host_check; - } sched_info; - - -/* PASSIVE_CHECK_RESULT structure */ -typedef struct passive_check_result_struct { - int object_check_type; - char *host_name; - char *service_description; - int return_code; - char *output; - time_t check_time; - double latency; - struct passive_check_result_struct *next; - } passive_check_result; - - -/* CIRCULAR_BUFFER structure - used by worker threads */ -typedef struct circular_buffer_struct { - void **buffer; - int tail; - int head; - int items; - int high; /* highest number of items that has ever been stored in buffer */ - unsigned long overflow; - pthread_mutex_t buffer_lock; - } circular_buffer; - - -/* DBUF structure - dynamic string storage */ -typedef struct dbuf_struct { - char *buf; - unsigned long used_size; - unsigned long allocated_size; - unsigned long chunk_size; - } dbuf; - - -#define CHECK_STATS_BUCKETS 15 - -/* used for tracking host and service check statistics */ -typedef struct check_stats_struct { - int current_bucket; - int bucket[CHECK_STATS_BUCKETS]; - int overflow_bucket; - int minute_stats[3]; - time_t last_update; - } check_stats; - - -/******************* THREAD STUFF ********************/ - - /* slots in circular buffers */ -#define DEFAULT_EXTERNAL_COMMAND_BUFFER_SLOTS 4096 - - /* worker threads */ -#define TOTAL_WORKER_THREADS 1 - -#define COMMAND_WORKER_THREAD 0 - +/* useful for hosts and services to determine time 'til next check */ +#define normal_check_window(o) ((time_t)(o->check_interval * interval_length)) +#define retry_check_window(o) ((time_t)(o->retry_interval * interval_length)) +#define check_window(o) \ + ((o->current_state && o->state_type == SOFT_STATE) ? \ + retry_check_window(o) : \ + normal_check_window(o)) +/** Nerd subscription type */ +struct nerd_subscription { + int sd; + struct nerd_channel *chan; + char *format; /* requested format (macro string) for this subscription */ +}; /******************** FUNCTIONS **********************/ +extern int set_loadctl_options(char *opts, unsigned int len); + +/* silly helpers useful pretty much all over the place */ +extern const char *service_state_name(int state); +extern const char *host_state_name(int state); +extern const char *state_type_name(int state_type); +extern const char *check_type_name(int check_type); +extern const char *check_result_source(check_result *cr); + +/*** Nagios Event Radio Dispatcher functions ***/ +extern int nerd_init(void); +extern int nerd_mkchan(const char *name, const char *description, int (*handler)(int, void *), unsigned int callbacks); +extern int nerd_cancel_subscriber(int sd); +extern int nerd_get_channel_id(const char *chan_name); +extern objectlist *nerd_get_subscriptions(int chan_id); +extern int nerd_broadcast(unsigned int chan_id, void *buf, unsigned int len); + +/*** Query Handler functions, types and macros*/ +typedef int (*qh_handler)(int, char *, unsigned int); +extern int dump_event_stats(int sd); + +/* return codes for query_handlers() */ +#define QH_OK 0 /* keep listening */ +#define QH_CLOSE 1 /* we should close the socket */ +#define QH_INVALID 2 /* invalid query. Log and close */ +#define QH_TAKEOVER 3 /* handler will take full control. de-register but don't close */ +extern int qh_init(const char *path); +extern void qh_deinit(const char *path); +extern int qh_register_handler(const char *name, const char *description, unsigned int options, qh_handler handler); +extern const char *qh_strerror(int code); /**** Configuration Functions ****/ int read_main_config_file(char *); /* reads the main config file (nagios.cfg) */ @@ -443,33 +481,31 @@ void init_timing_loop(void); /* setup the initial sche void setup_sighandler(void); /* trap signals */ void reset_sighandler(void); /* reset signals to default action */ extern void handle_sigxfsz(int); /* handle SIGXFSZ */ + int daemon_init(void); /* switches to daemon mode */ int drop_privileges(char *, char *); /* drops privileges before startup */ void display_scheduling_info(void); /* displays service check scheduling information */ +void init_main_cfg_vars(int); /* Initialize the non-shared main configuration variables */ /**** Event Queue Functions ****/ -int schedule_new_event(int, int, time_t, int, unsigned long, void *, int, void *, void *, int); /* schedules a new timed event */ -void reschedule_event(timed_event *, timed_event **, timed_event **); /* reschedules an event */ -void add_event(timed_event *, timed_event **, timed_event **); /* adds an event to the execution queue */ -void remove_event(timed_event *, timed_event **, timed_event **); /* remove an event from the execution queue */ +int init_event_queue(void); /* creates the queue nagios_squeue */ +timed_event *schedule_new_event(int, int, time_t, int, unsigned long, void *, int, void *, void *, int); /* schedules a new timed event */ +void reschedule_event(squeue_t *sq, timed_event *event); /* reschedules an event */ +void add_event(squeue_t *sq, timed_event *event); /* adds an event to the execution queue */ +void remove_event(squeue_t *sq, timed_event *event); /* remove an event from the execution queue */ int event_execution_loop(void); /* main monitoring/event handler loop */ int handle_timed_event(timed_event *); /* top level handler for timed events */ void adjust_check_scheduling(void); /* auto-adjusts scheduling of host and service checks */ void compensate_for_system_time_change(unsigned long, unsigned long); /* attempts to compensate for a change in the system time */ void adjust_timestamp_for_time_change(time_t, time_t, unsigned long, time_t *); /* adjusts a timestamp variable for a system time change */ -void resort_event_list(timed_event **, timed_event **); /* resorts event list by event run time for system time changes */ /**** IPC Functions ****/ -int move_check_result_to_queue(char *); int process_check_result_queue(char *); -int find_executing_checks(char *); -int process_check_result_file(char *, check_result **, int, int); -int add_check_result_to_list(check_result **, check_result *); -check_result *read_check_result(check_result **); /* reads a host/service check result from the list in memory */ +int process_check_result_file(char *); +int process_check_result(check_result *); int delete_check_result_file(char *); -int free_check_result_list(check_result **); int init_check_result(check_result *); int free_check_result(check_result *); /* frees memory associated with a host/service check result */ int parse_check_output(char *, char **, char **, char **, int, int); @@ -478,6 +514,7 @@ int close_command_file(void); /* closes and deletes the external command fil /**** Monitoring/Event Handler Functions ****/ +int check_service_parents(service *svc); /* checks service parents */ int check_service_dependencies(service *, int); /* checks service dependencies */ int check_host_dependencies(host *, int); /* checks host dependencies */ void check_for_orphaned_services(void); /* checks for orphaned services */ @@ -494,9 +531,9 @@ int my_system_r(nagios_macros *mac, char *, int, int *, double *, char **, int); void check_for_service_flapping(service *, int, int); /* determines whether or not a service is "flapping" between states */ void check_for_host_flapping(host *, int, int, int); /* determines whether or not a host is "flapping" between states */ void set_service_flap(service *, double, double, double, int); /* handles a service that is flapping */ -void clear_service_flap(service *, double, double, double); /* handles a service that has stopped flapping */ +void clear_service_flap(service *, double, double, double, int); /* handles a service that has stopped flapping */ void set_host_flap(host *, double, double, double, int); /* handles a host that is flapping */ -void clear_host_flap(host *, double, double, double); /* handles a host that has stopped flapping */ +void clear_host_flap(host *, double, double, double, int); /* handles a host that has stopped flapping */ void enable_flap_detection_routines(void); /* enables flap detection on a program-wide basis */ void disable_flap_detection_routines(void); /* disables flap detection on a program-wide basis */ void enable_host_flap_detection(host *); /* enables flap detection for a particular host */ @@ -508,18 +545,15 @@ void handle_service_flap_detection_disabled(service *); /* handles the details /**** Route/Host Check Functions ****/ -int perform_on_demand_host_check(host *, int *, int, int, unsigned long); -int perform_scheduled_host_check(host *, int, double); -int check_host_check_viability_3x(host *, int, int *, time_t *); -int adjust_host_check_attempt_3x(host *, int); +int check_host_check_viability(host *, int, int *, time_t *); +int adjust_host_check_attempt(host *, int); int determine_host_reachability(host *); -int process_host_check_result_3x(host *, int, char *, int, int, int, unsigned long); -int perform_on_demand_host_check_3x(host *, int *, int, int, unsigned long); -int run_sync_host_check_3x(host *, int *, int, int, unsigned long); -int execute_sync_host_check_3x(host *); -int run_scheduled_host_check_3x(host *, int, double); -int run_async_host_check_3x(host *, int, double, int, int, int *, time_t *); -int handle_async_host_check_result_3x(host *, check_result *); +int process_host_check_result(host *, int, char *, int, int, int, unsigned long); +int perform_on_demand_host_check(host *, int *, int, int, unsigned long); +int execute_sync_host_check(host *); +int run_scheduled_host_check(host *, int, double); +int run_async_host_check(host *, int, double, int, int, int *, time_t *); +int handle_async_host_check_result(host *, check_result *); /**** Service Check Functions ****/ @@ -533,7 +567,7 @@ int handle_async_service_check_result(service *, check_result *); int handle_host_state(host *); /* top level host state handler */ -/**** Common Check Fucntions *****/ +/**** Common Check Functions *****/ int reap_check_results(void); @@ -555,6 +589,7 @@ int run_global_host_event_handler(nagios_macros *mac, host *); /* runs the glo /**** Notification Functions ****/ +const char *notification_reason_name(unsigned int reason_type); int check_service_notification_viability(service *, int, int); /* checks viability of notifying all contacts about a service */ int is_valid_escalation_for_service_notification(service *, serviceescalation *, int); /* checks if an escalation entry is valid for a particular service notification */ int should_service_notification_be_escalated(service *); /* checks if a service notification should be escalated */ @@ -584,12 +619,24 @@ void free_notification_list(void); /* frees all memory allocated to the n /**** Miscellaneous Functions ****/ void sighandler(int); /* handles signals */ -void service_check_sighandler(int); /* handles timeouts when executing service checks */ -void host_check_sighandler(int); /* handles timeouts when executing host checks */ void my_system_sighandler(int); /* handles timeouts when executing commands via my_system() */ char *get_next_string_from_buf(char *buf, int *start_index, int bufsize); int compare_strings(char *, char *); /* compares two strings for equality */ char *escape_newlines(char *); +/** + * Unescapes newlines and backslashes in a check result output string read from + * a source that uses newlines as a delimiter (e.g., files in the checkresults + * spool dir, or the command pipe). + * @note: There is an unescape_newlines() in cgi/cgiutils.c that unescapes more + * than '\\' and '\n' in place. Since this function is specifically intended + * for processing escaped plugin output, we'll use a more specific name to + * avoid confusion and conflicts. + * @param rawbuf Input string tp unescape. + * @return An unescaped copy of rawbuf in a newly allocated string, or NULL if + * rawbuf is NULL or no memory could be allocated for the new string. + */ +char *unescape_check_result_output(const char *rawbuf); + int contains_illegal_object_chars(char *); /* tests whether or not an object name (host, service, etc.) contains illegal characters */ int my_rename(char *, char *); /* renames a file - works across filesystems */ int my_fcopy(char *, char *); /* copies a file - works across filesystems */ @@ -610,19 +657,15 @@ time_t calculate_time_from_weekday_of_month(int, int, int, int); /* calculates m time_t calculate_time_from_day_of_month(int, int, int); /* calculates midnight time of specific (1st, last, etc.) day of a particular month */ void get_next_valid_time(time_t, time_t *, timeperiod *); /* get the next valid time in a time period */ time_t get_next_log_rotation_time(void); /* determine the next time to schedule a log rotation */ -int init_embedded_perl(char **); /* initialized embedded perl interpreter */ -int deinit_embedded_perl(void); /* cleans up embedded perl */ -int file_uses_embedded_perl(char *); /* tests whether or not the embedded perl interpreter should be used on a file */ int dbuf_init(dbuf *, int); int dbuf_free(dbuf *); -int dbuf_strcat(dbuf *, char *); +int dbuf_strcat(dbuf *, const char *); int set_environment_var(char *, char *, int); /* sets/clears and environment variable */ int check_for_nagios_updates(int, int); /* checks to see if new version of Nagios are available */ int query_update_api(void); /* checks to see if new version of Nagios are available */ /**** External Command Functions ****/ -int check_for_external_commands(void); /* checks for any external commands */ int process_external_command1(char *); /* top-level external command processor */ int process_external_command2(int, time_t, char *); /* process an external command */ int process_external_commands_from_file(char *, int); /* process external commands in a file */ @@ -700,9 +743,6 @@ void enable_service_freshness_checks(void); /* enable service freshness checks void disable_service_freshness_checks(void); /* disable service freshness checks */ void enable_host_freshness_checks(void); /* enable host freshness checks */ void disable_host_freshness_checks(void); /* disable host freshness checks */ -void process_passive_checks(void); /* processes passive host and service check results */ -void enable_all_failure_prediction(void); /* enables failure prediction on a program-wide basis */ -void disable_all_failure_prediction(void); /* disables failure prediction on a program-wide basis */ void enable_performance_data(void); /* enables processing of performance data on a program-wide basis */ void disable_performance_data(void); /* disables processing of performance data on a program-wide basis */ void start_executing_host_checks(void); /* starts executing host checks */ @@ -721,14 +761,11 @@ void enable_contact_host_notifications(contact *); /* enables host notifica void disable_contact_host_notifications(contact *); /* disables host notifications for a specific contact */ void enable_contact_service_notifications(contact *); /* enables service notifications for a specific contact */ void disable_contact_service_notifications(contact *); /* disables service notifications for a specific contact */ +void clear_host_flapping_state(host *); /* clears the flapping state for a specific host */ +void clear_service_flapping_state(service *); /* clears the flapping state for a specific service */ -int init_command_file_worker_thread(void); -int shutdown_command_file_worker_thread(void); -void * command_file_worker_thread(void *); -void cleanup_command_file_worker_thread(void *); - -int submit_external_command(char *, int *); -int submit_raw_external_command(char *, time_t *, int *); +int launch_command_file_worker(void); +int shutdown_command_file_worker(void); char *get_program_version(void); char *get_program_modification_date(void); diff --git a/include/nebcallbacks.h b/include/nebcallbacks.h index a9e631a..f67477a 100644 --- a/include/nebcallbacks.h +++ b/include/nebcallbacks.h @@ -2,8 +2,6 @@ * * NEBCALLBACKS.H - Include file for event broker modules * - * Copyright (c) 2002-2007 Ethan Galstad (egalstad@nagios.org) - * Last Modified: 01-06-2007 * * License: * @@ -22,53 +20,44 @@ * *****************************************************************************/ -#ifndef _NEBCALLBACKS_H -#define _NEBCALLBACKS_H +#ifndef NAGIOS_NEBCALLBACKS_H_INCLUDED +#define NAGIOS_NEBCALLBACKS_H_INCLUDED -#include "compat.h" #include "nebmodules.h" /***** CALLBACK TYPES *****/ -#define NEBCALLBACK_NUMITEMS 33 /* total number of callback types we have */ +#define NEBCALLBACK_NUMITEMS 26 /* total number of callback types we have */ -#define NEBCALLBACK_RESERVED0 0 /* reserved for future use */ -#define NEBCALLBACK_RESERVED1 1 -#define NEBCALLBACK_RESERVED2 2 -#define NEBCALLBACK_RESERVED3 3 -#define NEBCALLBACK_RESERVED4 4 - -#define NEBCALLBACK_RAW_DATA 5 -#define NEBCALLBACK_NEB_DATA 6 - -#define NEBCALLBACK_PROCESS_DATA 7 -#define NEBCALLBACK_TIMED_EVENT_DATA 8 -#define NEBCALLBACK_LOG_DATA 9 -#define NEBCALLBACK_SYSTEM_COMMAND_DATA 10 -#define NEBCALLBACK_EVENT_HANDLER_DATA 11 -#define NEBCALLBACK_NOTIFICATION_DATA 12 -#define NEBCALLBACK_SERVICE_CHECK_DATA 13 -#define NEBCALLBACK_HOST_CHECK_DATA 14 -#define NEBCALLBACK_COMMENT_DATA 15 -#define NEBCALLBACK_DOWNTIME_DATA 16 -#define NEBCALLBACK_FLAPPING_DATA 17 -#define NEBCALLBACK_PROGRAM_STATUS_DATA 18 -#define NEBCALLBACK_HOST_STATUS_DATA 19 -#define NEBCALLBACK_SERVICE_STATUS_DATA 20 -#define NEBCALLBACK_ADAPTIVE_PROGRAM_DATA 21 -#define NEBCALLBACK_ADAPTIVE_HOST_DATA 22 -#define NEBCALLBACK_ADAPTIVE_SERVICE_DATA 23 -#define NEBCALLBACK_EXTERNAL_COMMAND_DATA 24 -#define NEBCALLBACK_AGGREGATED_STATUS_DATA 25 -#define NEBCALLBACK_RETENTION_DATA 26 -#define NEBCALLBACK_CONTACT_NOTIFICATION_DATA 27 -#define NEBCALLBACK_CONTACT_NOTIFICATION_METHOD_DATA 28 -#define NEBCALLBACK_ACKNOWLEDGEMENT_DATA 29 -#define NEBCALLBACK_STATE_CHANGE_DATA 30 -#define NEBCALLBACK_CONTACT_STATUS_DATA 31 -#define NEBCALLBACK_ADAPTIVE_CONTACT_DATA 32 +#define NEBCALLBACK_PROCESS_DATA 0 +#define NEBCALLBACK_TIMED_EVENT_DATA 1 +#define NEBCALLBACK_LOG_DATA 2 +#define NEBCALLBACK_SYSTEM_COMMAND_DATA 3 +#define NEBCALLBACK_EVENT_HANDLER_DATA 4 +#define NEBCALLBACK_NOTIFICATION_DATA 5 +#define NEBCALLBACK_SERVICE_CHECK_DATA 6 +#define NEBCALLBACK_HOST_CHECK_DATA 7 +#define NEBCALLBACK_COMMENT_DATA 8 +#define NEBCALLBACK_DOWNTIME_DATA 9 +#define NEBCALLBACK_FLAPPING_DATA 10 +#define NEBCALLBACK_PROGRAM_STATUS_DATA 11 +#define NEBCALLBACK_HOST_STATUS_DATA 12 +#define NEBCALLBACK_SERVICE_STATUS_DATA 13 +#define NEBCALLBACK_ADAPTIVE_PROGRAM_DATA 14 +#define NEBCALLBACK_ADAPTIVE_HOST_DATA 15 +#define NEBCALLBACK_ADAPTIVE_SERVICE_DATA 16 +#define NEBCALLBACK_EXTERNAL_COMMAND_DATA 17 +#define NEBCALLBACK_AGGREGATED_STATUS_DATA 18 +#define NEBCALLBACK_RETENTION_DATA 19 +#define NEBCALLBACK_CONTACT_NOTIFICATION_DATA 20 +#define NEBCALLBACK_CONTACT_NOTIFICATION_METHOD_DATA 21 +#define NEBCALLBACK_ACKNOWLEDGEMENT_DATA 22 +#define NEBCALLBACK_STATE_CHANGE_DATA 23 +#define NEBCALLBACK_CONTACT_STATUS_DATA 24 +#define NEBCALLBACK_ADAPTIVE_CONTACT_DATA 25 +#define nebcallback_flag(x) (1 << (x)) /***** CALLBACK FUNCTIONS *****/ NAGIOS_BEGIN_DECL diff --git a/include/neberrors.h b/include/neberrors.h index 31e6e83..d4cba36 100644 --- a/include/neberrors.h +++ b/include/neberrors.h @@ -2,8 +2,6 @@ * * NEBERRORS.H - Event broker errors * - * Copyright (c) 2003-2006 Ethan Galstad (egalstad@nagios.org) - * Last Modified: 12-12-2006 * * License: * @@ -22,8 +20,8 @@ * *****************************************************************************/ -#ifndef _NEBERRORS_H -#define _NEBERRORS_H +#ifndef NAGIOS_NEBERRORS_H_INCLUDED +#define NAGIOS_NEBERRORS_H_INCLUDED /***** GENERIC DEFINES *****/ diff --git a/include/nebmods.h b/include/nebmods.h index 8cbcdf8..760ff0b 100644 --- a/include/nebmods.h +++ b/include/nebmods.h @@ -2,8 +2,6 @@ * * NEBMODS.H - Include file for event broker modules * - * Copyright (c) 2002-2005 Ethan Galstad (egalstad@nagios.org) - * Last Modified: 11-25-2005 * * License: * @@ -22,10 +20,9 @@ * *****************************************************************************/ -#ifndef _NEBMODS_H -#define _NEBMODS_H +#ifndef NAGIOS_NEBMODS_H_INCLUDED +#define NAGIOS_NEBMODS_H_INCLUDED -#include "compat.h" #include "nebcallbacks.h" #include "nebmodules.h" @@ -53,6 +50,7 @@ int neb_free_module_list(void); int neb_unload_all_modules(int, int); int neb_unload_module(nebmodule *, int, int); int neb_add_module(char *, char *, int); +int neb_add_core_module(nebmodule *mod); /***** CALLBACK FUNCTIONS *****/ diff --git a/include/nebmodules.h b/include/nebmodules.h index 2638501..4fc2b2f 100644 --- a/include/nebmodules.h +++ b/include/nebmodules.h @@ -2,8 +2,6 @@ * * NEBMODULES.H - Include file for event broker modules * - * Copyright (c) 2002-2006 Ethan Galstad (egalstad@nagios.org) - * Last Modified: 02-27-2006 * * License: * @@ -22,16 +20,16 @@ * *****************************************************************************/ -#ifndef _NEBMODULES_H -#define _NEBMODULES_H +#ifndef NAGIOS_NEBMODULES_H_INCLUDED +#define NAGIOS_NEBMODULES_H_INCLUDED -#include "compat.h" +#include "common.h" NAGIOS_BEGIN_DECL /***** MODULE VERSION INFORMATION *****/ #define NEB_API_VERSION(x) int __neb_api_version = x; -#define CURRENT_NEB_API_VERSION 3 +#define CURRENT_NEB_API_VERSION 4 @@ -70,10 +68,12 @@ NAGIOS_BEGIN_DECL /* NEB module structure */ typedef struct nebmodule_struct { char *filename; + char *dl_file; /* the file we actually loaded */ char *args; char *info[NEBMODULE_MODINFO_NUMITEMS]; int should_be_loaded; int is_currently_loaded; + int core_module; #ifdef USE_LTDL lt_dlhandle module_handle; lt_ptr init_func; @@ -82,9 +82,6 @@ typedef struct nebmodule_struct { void *module_handle; void *init_func; void *deinit_func; -#endif -#ifdef HAVE_PTHREAD_H - pthread_t thread_id; #endif struct nebmodule_struct *next; } nebmodule; diff --git a/include/nebstructs.h b/include/nebstructs.h index 38965d2..9862ea9 100644 --- a/include/nebstructs.h +++ b/include/nebstructs.h @@ -2,8 +2,6 @@ * * NEBSTRUCTS.H - Event broker includes for Nagios * - * Copyright (c) 2003-2007 Ethan Galstad (egalstad@nagios.org) - * Last Modified: 10-28-2007 * * License: * @@ -22,10 +20,10 @@ * *****************************************************************************/ -#ifndef _NEBSTRUCTS_H -#define _NEBSTRUCTS_H +#ifndef NAGIOS_NEBSTRUCTS_H_INCLUDED +#define NAGIOS_NEBSTRUCTS_H_INCLUDED -#include "compat.h" +#include "common.h" #include "objects.h" #include "nagios.h" @@ -142,6 +140,7 @@ typedef struct nebstruct_host_check_struct { char *output; char *long_output; char *perf_data; + check_result *check_result_ptr; void *object_ptr; } nebstruct_host_check_data; @@ -174,6 +173,7 @@ typedef struct nebstruct_service_check_struct { char *output; char *long_output; char *perf_data; + check_result *check_result_ptr; void *object_ptr; } nebstruct_service_check_data; @@ -256,7 +256,6 @@ typedef struct nebstruct_program_status_struct { time_t program_start; int pid; int daemon_mode; - time_t last_command_check; time_t last_log_rotation; int notifications_enabled; int active_service_checks_enabled; @@ -265,7 +264,6 @@ typedef struct nebstruct_program_status_struct { int passive_host_checks_enabled; int event_handlers_enabled; int flap_detection_enabled; - int failure_prediction_enabled; int process_performance_data; int obsess_over_hosts; int obsess_over_services; @@ -519,8 +517,8 @@ typedef struct nebstruct_statechange_struct { int current_attempt; int max_attempts; char *output; - void *object_ptr; + char *longoutput; } nebstruct_statechange_data; NAGIOS_END_DECL diff --git a/include/netutils.h b/include/netutils.h index 839fa8f..1407e3f 100644 --- a/include/netutils.h +++ b/include/netutils.h @@ -1,9 +1,9 @@ -#ifndef _NETUTILS_H -#define _NETUTILS_H -#include "compat.h" +#ifndef NAGIOS_NETUGILS_H_INCLUDED +#define NAGIOS_NETUGILS_H_INCLUDED +#include "common.h" NAGIOS_BEGIN_DECL -int my_tcp_connect(char *host_name, int port, int *sd, int timeout); -int my_sendall(int s, char *buf, int *len, int timeout); +int my_tcp_connect(const char *host_name, int port, int *sd, int timeout); +int my_sendall(int s, const char *buf, int *len, int timeout); int my_recvall(int s, char *buf, int *len, int timeout); NAGIOS_END_DECL #endif diff --git a/include/objectjson.h b/include/objectjson.h new file mode 100644 index 0000000..5e05e15 --- /dev/null +++ b/include/objectjson.h @@ -0,0 +1,298 @@ +/************************************************************************** + * + * OBJECTJSON.H - Nagios CGI for returning JSON-formatted object data + * + * Copyright (c) 2013 Nagios Enterprises, LLC + * Last Modified: 04-13-2013 + * + * License: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + *************************************************************************/ + +#ifndef NAGIOS_OBJECTJSON_H_INCLUDED +#define NAGIOS_OBJECTJSON_H_INCLUDED + +/* Structure containing CGI query string options and values */ +typedef struct object_json_cgi_data_struct { + /* Format options for JSON output */ + unsigned format_options; + /* Query being requested */ + int query; + /* Index of starting object returned for list requests */ + int start; + /* Number of objects returned for list requests */ + int count; + /* Return details for each entity in a list request */ + int details; + /* strftime format string for time_t values */ + char * strftime_format; + /* Name of host whose children should be returned if parenthost is + specified */ + char * parent_host_name; + /* Use the parent host field or search all hosts */ + int use_parent_host; + /* Host whose children should be returned if use_parent_host is non-zero */ + host * parent_host; + /* Name of host whose parents should be returned if childhost is + specified */ + char * child_host_name; + /* Use the child host field or search all hosts */ + int use_child_host; + /* Host whose parents should be returned if use_child_host is non-zero */ + host * child_host; + /* Name of host for which details should be returned */ + char * host_name; + /* Host whose host name is host_name */ + host * host; + /* Name of host whose hostgroup should be returned if hostgroupmember is + specified */ + char * hostgroup_member_name; + /* Host whose hostgroup should be returned if hostgroup_member_name is + specified */ + host * hostgroup_member; + /* Name of hostgroup for which details should be returned */ + char * hostgroup_name; + /* Hostgroup whose name is hostgroup_name */ + hostgroup * hostgroup; + /* Name of servicegroup for which details should be returned */ + char * servicegroup_name; + /* Servicegroup whose name is servicegroup_name */ + servicegroup * servicegroup; + /* Name of service for which details should be returned */ + char * service_description; + /* Service whose host name is host_name and whose description is + service_description*/ + service * service; + /* Name of host for which servicegroup should be returned if + servicegroupmemberhost and servicegroupmemberservice are specified */ + char * servicegroup_member_host_name; + /* Name of service for which servicegroup should be returned if + servicegroupmemberhost and servicegroupmemberservice are specified */ + char * servicegroup_member_service_description; + /* Service whose servicegroup should be returned if + servicegroup_member_host_name and + servicegroup_member_service_description are specified */ + service * servicegroup_member; + /* Name of service whose children should be returned if parentservice is + specified */ + char * parent_service_name; + /* Name of service whose parents should be returned if childservice is + specified */ + char * child_service_name; + /* Name of contactgroup for which details should be returned */ + char * contactgroup_name; + /* Contactgroup whose name is contactgroup_name */ + contactgroup * contactgroup; + /* Name of contact for which details should be returned */ + char * contact_name; + /* Contact whose contact name is contact_name */ + contact * contact; + /* Name of contact whose contactgroup should be returned if + contactgroupmember is specified */ + char * contactgroup_member_name; + /* Contact whose contactgroup should be returned if + contactgroup_member_name is specified */ + contact * contactgroup_member; + /* Name of timeperiod for which details should be returned */ + char * timeperiod_name; + /* Timeperiod whose timeperiod name is timeperiod_name */ + timeperiod *timeperiod; + /* Name of check timeperiod for which details should be returned */ + char * check_timeperiod_name; + /* Timeperiod whose timeperiod name is check_timeperiod_name */ + timeperiod *check_timeperiod; + /* Name of host notification timeperiod for which details should + be returned */ + char * host_notification_timeperiod_name; + /* Timeperiod whose timeperiod name is host_notification_timeperiod_name */ + timeperiod *host_notification_timeperiod; + /* Name of service notification timeperiod for which details should + be returned */ + char * service_notification_timeperiod_name; + /* Timeperiod whose timeperiod name is + service_notification_timeperiod_name */ + timeperiod *service_notification_timeperiod; + /* Name of command for which details should be returned */ + char * command_name; + /* Command whose command name is command_name */ + command * command; + /* Name of check command to be used as a selector */ + char * check_command_name; + /* Command whose command name is check_command_name */ + command * check_command; + /* Name of event handler to be used as a selector */ + char * event_handler_name; + /* Command whose command name is event_handler_name */ + command * event_handler; + /* Name of master host to be used as a selector for dependencies */ + char * master_host_name; + /* Host whose host name is master_host_name */ + host * master_host; + /* Name of master hostgroup to be used as a selector for dependencies */ + char * master_hostgroup_name; + /* Host whose hostgroup name is master_hostgroup_name */ + hostgroup * master_hostgroup; + /* Name of master service to be used as a selector for dependencies */ + char * master_service_description; + /* Service whose service name is master_service_description */ + service * master_service; + /* Name of master servicegroup to be used as a selector for dependencies */ + char * master_servicegroup_name; + /* Service whose servicegroup name is master_servicegroup_name */ + servicegroup * master_servicegroup; + /* Name of dependent host to be used as a selector for dependencies */ + char * dependent_host_name; + /* Host whose host name is dependent_host_name */ + host * dependent_host; + /* Name of dependent hostgroup to be used as a selector for dependencies */ + char * dependent_hostgroup_name; + /* Host whose hostgroup name is dependent_hostgroup_name */ + hostgroup * dependent_hostgroup; + /* Name of dependent service to be used as a selector for dependencies */ + char * dependent_service_description; + /* Service whose service name is dependent_service_description */ + service * dependent_service; + /* Name of dependent servicegroup to be used as a selector for + dependencies */ + char * dependent_servicegroup_name; + /* Service whose servicegroup name is dependent_servicegroup_name */ + servicegroup * dependent_servicegroup; + } object_json_cgi_data; + +/* Object Type Information */ +#define OBJECT_QUERY_INVALID 0 +#define OBJECT_QUERY_HOSTCOUNT 1 +#define OBJECT_QUERY_HOSTLIST 2 +#define OBJECT_QUERY_HOST 3 +#define OBJECT_QUERY_HOSTGROUPCOUNT 4 +#define OBJECT_QUERY_HOSTGROUPLIST 5 +#define OBJECT_QUERY_HOSTGROUP 6 +#define OBJECT_QUERY_SERVICECOUNT 7 +#define OBJECT_QUERY_SERVICELIST 8 +#define OBJECT_QUERY_SERVICE 9 +#define OBJECT_QUERY_SERVICEGROUPCOUNT 10 +#define OBJECT_QUERY_SERVICEGROUPLIST 11 +#define OBJECT_QUERY_SERVICEGROUP 12 +#define OBJECT_QUERY_CONTACTCOUNT 13 +#define OBJECT_QUERY_CONTACTLIST 14 +#define OBJECT_QUERY_CONTACT 15 +#define OBJECT_QUERY_CONTACTGROUPCOUNT 16 +#define OBJECT_QUERY_CONTACTGROUPLIST 17 +#define OBJECT_QUERY_CONTACTGROUP 18 +#define OBJECT_QUERY_TIMEPERIODCOUNT 19 +#define OBJECT_QUERY_TIMEPERIODLIST 20 +#define OBJECT_QUERY_TIMEPERIOD 21 +#define OBJECT_QUERY_COMMANDCOUNT 22 +#define OBJECT_QUERY_COMMANDLIST 23 +#define OBJECT_QUERY_COMMAND 24 +#define OBJECT_QUERY_SERVICEDEPENDENCYCOUNT 25 +#define OBJECT_QUERY_SERVICEDEPENDENCYLIST 26 +#define OBJECT_QUERY_SERVICEESCALATIONCOUNT 27 +#define OBJECT_QUERY_SERVICEESCALATIONLIST 28 +#define OBJECT_QUERY_HOSTDEPENDENCYCOUNT 29 +#define OBJECT_QUERY_HOSTDEPENDENCYLIST 30 +#define OBJECT_QUERY_HOSTESCALATIONCOUNT 31 +#define OBJECT_QUERY_HOSTESCALATIONLIST 32 +#define OBJECT_QUERY_HELP 33 + +extern json_object * json_object_custom_variables(struct customvariablesmember *); + +extern json_object *json_object_hostcount(int, host *, int, host *, hostgroup *, + contact *, contactgroup *, timeperiod *, timeperiod *, command *, + command *); +extern json_object *json_object_hostlist(unsigned, int, int, int, int, host *, + int, host *, hostgroup *, contact *, contactgroup *, timeperiod *, + timeperiod *, command *, command *); +extern json_object *json_object_host(unsigned, host *); +extern void json_object_host_details(json_object *, unsigned, host *); + +extern json_object *json_object_hostgroupcount(unsigned, host *); +extern json_object *json_object_hostgrouplist(unsigned, int, int, int, host *); +extern json_object *json_object_hostgroup(unsigned, hostgroup *); +extern void json_object_hostgroup_details(json_object *, unsigned, hostgroup *); + +extern json_object *json_object_servicecount(host *, int, host *, int, host *, + hostgroup *, servicegroup *, contact *, char *, char *, char *, + contactgroup *, timeperiod *, timeperiod *, command *, command *); +extern json_object *json_object_servicelist(unsigned, int, int, int, host *, + int, host *, int, host *, hostgroup *, servicegroup *, contact *, + char *, char *, char *, contactgroup *, timeperiod *, timeperiod *, + command *, command *); +extern json_object *json_object_service(unsigned, service *); +extern void json_object_service_details(json_object *, unsigned, service *); + +extern json_object *json_object_servicegroupcount(service *); +extern json_object *json_object_servicegrouplist(unsigned, int, int, int, + service *); +extern json_object *json_object_servicegroup(unsigned, servicegroup *); +extern void json_object_servicegroup_details(json_object *, unsigned, + servicegroup *); + +extern json_object *json_object_contactcount(contactgroup *, timeperiod *, + timeperiod *); +extern json_object *json_object_contactlist(unsigned, int, int, int, + contactgroup *, timeperiod *, timeperiod *); +extern json_object *json_object_contact(unsigned, contact *); +extern void json_object_contact_details(json_object *, unsigned, contact *); + +extern json_object *json_object_contactgroupcount(contact *); +extern json_object *json_object_contactgrouplist(unsigned, int, int, int, + contact *); +extern json_object *json_object_contactgroup(unsigned, contactgroup *); +extern void json_object_contactgroup_details(json_object *, unsigned, + contactgroup *); + +extern json_object *json_object_timeperiodcount(void); +extern json_object *json_object_timeperiodlist(unsigned, int, int, int); +extern json_object *json_object_timeperiod(unsigned, timeperiod *); +extern void json_object_timeperiod_details(json_object *, unsigned, timeperiod *); +extern void json_object_timerange(json_array *, unsigned, timerange *); +extern json_object *json_object_daterange(unsigned, daterange *, int); + +extern json_object *json_object_commandcount(void); +extern json_object *json_object_commandlist(unsigned, int, int, int); +extern json_object *json_object_command(unsigned, command *); +extern void json_object_command_details(json_object *, unsigned, command *); + +extern json_object *json_object_servicedependencycount(host *, hostgroup *, + char *, servicegroup *, host *, hostgroup *, char *, servicegroup *); +extern json_object *json_object_servicedependencylist(unsigned, int, int, + host *, hostgroup *, char *, servicegroup *, host *, hostgroup *, + char *, servicegroup *); +extern void json_object_servicedependency_details(json_object *, unsigned, + servicedependency *); + +extern json_object *json_object_serviceescalationcount(host *, char *, + hostgroup *, servicegroup *, contact *, contactgroup *); +extern json_object *json_object_serviceescalationlist(unsigned, int, int, + host *, char *, hostgroup *, servicegroup *, contact *, contactgroup *); +extern void json_object_serviceescalation_details(json_object *, unsigned, + serviceescalation *); + +extern json_object *json_object_hostdependencycount(host *, hostgroup *, + host *, hostgroup *); +extern json_object *json_object_hostdependencylist(unsigned, int, int, host *, + hostgroup *, host *, hostgroup *); +extern void json_object_hostdependency_details(json_object *, unsigned, + hostdependency *); + +extern json_object *json_object_hostescalationcount(host *, hostgroup *, + contact *, contactgroup *); +extern json_object *json_object_hostescalationlist(unsigned, int, int, host *, + hostgroup *, contact *, contactgroup *); +extern void json_object_hostescalation_details(json_object *, unsigned, + hostescalation *); + +#endif diff --git a/include/objects.h b/include/objects.h index 57d458e..9a8a556 100644 --- a/include/objects.h +++ b/include/objects.h @@ -2,8 +2,6 @@ * * OBJECTS.H - Header file for object addition/search functions * - * Copyright (c) 1999-2007 Ethan Galstad (egalstad@nagios.org) - * Last Modified: 11-10-2007 * * License: * @@ -23,10 +21,9 @@ *****************************************************************************/ -#ifndef _OBJECTS_H -#define _OBJECTS_H +#ifndef NAGIOS_OBJECTS_H_INCLUDED +#define NAGIOS_OBJECTS_H_INCLUDED -#include "compat.h" #include "common.h" NAGIOS_BEGIN_DECL @@ -34,7 +31,7 @@ NAGIOS_BEGIN_DECL /*************** CURRENT OBJECT REVISION **************/ -#define CURRENT_OBJECT_STRUCTURE_VERSION 307 /* increment when changes are made to data structures... */ +#define CURRENT_OBJECT_STRUCTURE_VERSION 403 /* increment when changes are made to data structures... */ /* Nagios 3 starts at 300, Nagios 4 at 400, etc. */ @@ -49,6 +46,7 @@ NAGIOS_BEGIN_DECL /***************** SKIP LISTS ****************/ #define NUM_OBJECT_SKIPLISTS 12 +#define NUM_HASHED_OBJECT_TYPES 8 #define HOST_SKIPLIST 0 #define SERVICE_SKIPLIST 1 @@ -64,29 +62,186 @@ NAGIOS_BEGIN_DECL #define SERVICEESCALATION_SKIPLIST 11 +/***************** DATE RANGE TYPES *******************/ + +#define DATERANGE_CALENDAR_DATE 0 /* 2008-12-25 */ +#define DATERANGE_MONTH_DATE 1 /* july 4 (specific month) */ +#define DATERANGE_MONTH_DAY 2 /* day 21 (generic month) */ +#define DATERANGE_MONTH_WEEK_DAY 3 /* 3rd thursday (specific month) */ +#define DATERANGE_WEEK_DAY 4 /* 3rd thursday (generic month) */ +#define DATERANGE_TYPES 5 + + +/* + * flags for notification_options, flapping_options and other similar + * flags. They overlap (hosts and services), so we can't use enum's. + */ +#define OPT_NOTHING 0 /* no options selected */ +#define OPT_ALL (~0) /* everything selected, so all bits set */ +#define OPT_DOWN (1 << HOST_DOWN) +#define OPT_UP (1 << HOST_UP) +#define OPT_UNREACHABLE (1 << HOST_UNREACHABLE) +#define OPT_OK (1 << STATE_OK) +#define OPT_WARNING (1 << STATE_WARNING) +#define OPT_CRITICAL (1 << STATE_CRITICAL) +#define OPT_UNKNOWN (1 << STATE_UNKNOWN) +#define OPT_RECOVERY OPT_OK +/* and now the "unreal" states... */ +#define OPT_PENDING (1 << 10) +#define OPT_FLAPPING (1 << 11) +#define OPT_DOWNTIME (1 << 12) +#define OPT_DISABLED (1 << 15) /* will denote disabled checks some day */ + +/* macros useful with both hosts and services */ +#define flag_set(c, flag) ((c) |= (flag)) +#define flag_get(c, flag) (unsigned int)((c) & (flag)) +#define flag_isset(c, flag) (flag_get((c), (flag)) == (unsigned int)(flag)) +#define flag_unset(c, flag) (c &= ~(flag)) +#define should_stalk(o) flag_isset(o->stalking_options, 1 << o->current_state) +#define should_flap_detect(o) flag_isset(o->flap_detection_options, 1 << o->current_state) +#define should_notify(o) flag_isset(o->notification_options, 1 << o->current_state) +#define add_notified_on(o, f) (o->notified_on |= (1 << f)) + + +/* Event-related macros */ +#define NUDGE_MIN 5 +#define NUDGE_MAX 17 + /****************** DATA STRUCTURES *******************/ -typedef struct host_struct host; -typedef struct service_struct service; -typedef struct contact_struct contact; +/* @todo Remove typedef's of non-opaque types in Nagios 5 */ +typedef struct host host; +typedef struct service service; +typedef struct contact contact; + +/* TIMED_EVENT structure */ +typedef struct timed_event { + int event_type; + time_t run_time; + int recurring; + unsigned long event_interval; + int compensate_for_time_change; + void *timing_func; + void *event_data; + void *event_args; + int event_options; + unsigned int priority; /* 0 is auto, 1 is highest. n+1 < n */ + struct squeue_event *sq_event; + } timed_event; + + +/* NOTIFY_LIST structure */ +typedef struct notify_list { + struct contact *contact; + struct notify_list *next; + } notification; + + +/* + * *name can be "Nagios Core", "Merlin", "mod_gearman" or "DNX", fe. + * source_name gets passed the 'source' pointer from check_result + * and must return a non-free()'able string useful for printing what + * we need to determine exactly where the check was received from, + * such as "mod_gearman worker@10.11.12.13", or "Nagios Core command + * file worker" (for passive checks submitted locally), which will be + * stashed with hosts and services and used as the "CHECKSOURCE" macro. + */ +struct check_engine { + char *name; /* "Nagios Core", "Merlin", "Mod Gearman" fe */ + const char *(*source_name)( const void *); + void (*clean_result)(void *); +}; + +/* CHECK_RESULT structure */ +typedef struct check_result { + int object_check_type; /* is this a service or a host check? */ + char *host_name; /* host name */ + char *service_description; /* service description */ + int check_type; /* was this an active or passive service check? */ + int check_options; + int scheduled_check; /* was this a scheduled or an on-demand check? */ + int reschedule_check; /* should we reschedule the next check */ + char *output_file; /* what file is the output stored in? */ + FILE *output_file_fp; + double latency; + struct timeval start_time; /* time the service check was initiated */ + struct timeval finish_time; /* time the service check was completed */ + int early_timeout; /* did the service check timeout? */ + int exited_ok; /* did the plugin check return okay? */ + int return_code; /* plugin return code */ + char *output; /* plugin output */ + struct rusage rusage; /* resource usage by this check */ + struct check_engine *engine; /* where did we get this check from? */ + const void *source; /* engine handles this */ + } check_result; + + +/* SCHED_INFO structure */ +typedef struct sched_info { + int total_services; + int total_scheduled_services; + int total_hosts; + int total_scheduled_hosts; + double average_services_per_host; + double average_scheduled_services_per_host; + unsigned long service_check_interval_total; + unsigned long host_check_interval_total; + double average_service_execution_time; + double average_service_check_interval; + double average_host_check_interval; + double average_service_inter_check_delay; + double average_host_inter_check_delay; + double service_inter_check_delay; + double host_inter_check_delay; + int service_interleave_factor; + int max_service_check_spread; + int max_host_check_spread; + time_t first_service_check; + time_t last_service_check; + time_t first_host_check; + time_t last_host_check; + } sched_info; + + +/* DBUF structure - dynamic string storage */ +typedef struct dbuf { + char *buf; + unsigned long used_size; + unsigned long allocated_size; + unsigned long chunk_size; + } dbuf; + + +#define CHECK_STATS_BUCKETS 15 + +/* used for tracking host and service check statistics */ +typedef struct check_stats { + int current_bucket; + int bucket[CHECK_STATS_BUCKETS]; + int overflow_bucket; + int minute_stats[3]; + time_t last_update; + } check_stats; + + /* OBJECT LIST STRUCTURE */ -typedef struct objectlist_struct { +typedef struct objectlist { void *object_ptr; - struct objectlist_struct *next; + struct objectlist *next; } objectlist; /* TIMERANGE structure */ -typedef struct timerange_struct { +typedef struct timerange { unsigned long range_start; unsigned long range_end; - struct timerange_struct *next; + struct timerange *next; } timerange; /* DATERANGE structure */ -typedef struct daterange_struct { +typedef struct daterange { int type; int syear; /* start year */ int smon; /* start month */ @@ -99,109 +254,96 @@ typedef struct daterange_struct { int ewday; int ewday_offset; int skip_interval; - timerange *times; - struct daterange_struct *next; + struct timerange *times; + struct daterange *next; } daterange; /* TIMEPERIODEXCLUSION structure */ -typedef struct timeperiodexclusion_struct { +typedef struct timeperiodexclusion { char *timeperiod_name; - struct timeperiod_struct *timeperiod_ptr; - struct timeperiodexclusion_struct *next; + struct timeperiod *timeperiod_ptr; + struct timeperiodexclusion *next; } timeperiodexclusion; /* TIMEPERIOD structure */ -typedef struct timeperiod_struct { +typedef struct timeperiod { + unsigned int id; char *name; char *alias; - timerange *days[7]; - daterange *exceptions[DATERANGE_TYPES]; - timeperiodexclusion *exclusions; - struct timeperiod_struct *next; - struct timeperiod_struct *nexthash; + struct timerange *days[7]; + struct daterange *exceptions[DATERANGE_TYPES]; + struct timeperiodexclusion *exclusions; + struct timeperiod *next; } timeperiod; /* CONTACTSMEMBER structure */ -typedef struct contactsmember_struct { +typedef struct contactsmember { char *contact_name; -#ifdef NSCORE - contact *contact_ptr; -#endif - struct contactsmember_struct *next; + struct contact *contact_ptr; + struct contactsmember *next; } contactsmember; /* CONTACTGROUP structure */ -typedef struct contactgroup_struct { +typedef struct contactgroup { + unsigned int id; char *group_name; char *alias; - contactsmember *members; - struct contactgroup_struct *next; - struct contactgroup_struct *nexthash; + struct contactsmember *members; + struct contactgroup *next; } contactgroup; /* CONTACTGROUPSMEMBER structure */ -typedef struct contactgroupsmember_struct { +typedef struct contactgroupsmember { char *group_name; -#ifdef NSCORE - contactgroup *group_ptr; -#endif - struct contactgroupsmember_struct *next; + struct contactgroup *group_ptr; + struct contactgroupsmember *next; } contactgroupsmember; /* CUSTOMVARIABLESMEMBER structure */ -typedef struct customvariablesmember_struct { +typedef struct customvariablesmember { char *variable_name; char *variable_value; int has_been_modified; - struct customvariablesmember_struct *next; + struct customvariablesmember *next; } customvariablesmember; /* COMMAND structure */ -typedef struct command_struct { +typedef struct command { + unsigned int id; char *name; char *command_line; - struct command_struct *next; - struct command_struct *nexthash; + struct command *next; } command; /* COMMANDSMEMBER structure */ -typedef struct commandsmember_struct { +typedef struct commandsmember { char *command; -#ifdef NSCORE - command *command_ptr; -#endif - struct commandsmember_struct *next; + struct command *command_ptr; + struct commandsmember *next; } commandsmember; /* CONTACT structure */ - struct contact_struct { +struct contact { + unsigned int id; char *name; char *alias; char *email; char *pager; char *address[MAX_CONTACT_ADDRESSES]; - commandsmember *host_notification_commands; - commandsmember *service_notification_commands; - int notify_on_service_unknown; - int notify_on_service_warning; - int notify_on_service_critical; - int notify_on_service_recovery; - int notify_on_service_flapping; - int notify_on_service_downtime; - int notify_on_host_down; - int notify_on_host_unreachable; - int notify_on_host_recovery; - int notify_on_host_flapping; - int notify_on_host_downtime; + struct commandsmember *host_notification_commands; + struct commandsmember *service_notification_commands; + unsigned int host_notification_options; + unsigned int service_notification_options; + unsigned int minimum_value; char *host_notification_period; char *service_notification_period; int host_notifications_enabled; @@ -209,110 +351,105 @@ typedef struct commandsmember_struct { int can_submit_commands; int retain_status_information; int retain_nonstatus_information; - customvariablesmember *custom_variables; -#ifdef NSCORE + struct customvariablesmember *custom_variables; +#ifndef NSCGI time_t last_host_notification; time_t last_service_notification; unsigned long modified_attributes; unsigned long modified_host_attributes; unsigned long modified_service_attributes; - - timeperiod *host_notification_period_ptr; - timeperiod *service_notification_period_ptr; - objectlist *contactgroups_ptr; #endif - struct contact_struct *next; - struct contact_struct *nexthash; + + struct timeperiod *host_notification_period_ptr; + struct timeperiod *service_notification_period_ptr; + struct objectlist *contactgroups_ptr; + struct contact *next; }; /* SERVICESMEMBER structure */ -typedef struct servicesmember_struct { +typedef struct servicesmember { char *host_name; char *service_description; -#ifdef NSCORE - service *service_ptr; -#endif - struct servicesmember_struct *next; + struct service *service_ptr; + struct servicesmember *next; } servicesmember; /* HOSTSMEMBER structure */ -typedef struct hostsmember_struct { +typedef struct hostsmember { char *host_name; -#ifdef NSCORE - host *host_ptr; -#endif - struct hostsmember_struct *next; + struct host *host_ptr; + struct hostsmember *next; } hostsmember; /* HOSTGROUP structure */ -typedef struct hostgroup_struct { +typedef struct hostgroup { + unsigned int id; char *group_name; char *alias; - hostsmember *members; + struct hostsmember *members; char *notes; char *notes_url; char *action_url; - struct hostgroup_struct *next; - struct hostgroup_struct *nexthash; + struct hostgroup *next; } hostgroup; /* HOST structure */ -struct host_struct { +struct host { + unsigned int id; char *name; char *display_name; char *alias; char *address; - hostsmember *parent_hosts; - hostsmember *child_hosts; - servicesmember *services; - char *host_check_command; + struct hostsmember *parent_hosts; + struct hostsmember *child_hosts; + struct servicesmember *services; + char *check_command; int initial_state; double check_interval; double retry_interval; int max_attempts; char *event_handler; - contactgroupsmember *contact_groups; - contactsmember *contacts; + struct contactgroupsmember *contact_groups; + struct contactsmember *contacts; double notification_interval; double first_notification_delay; - int notify_on_down; - int notify_on_unreachable; - int notify_on_recovery; - int notify_on_flapping; - int notify_on_downtime; + unsigned int notification_options; + unsigned int hourly_value; char *notification_period; char *check_period; int flap_detection_enabled; double low_flap_threshold; double high_flap_threshold; - int flap_detection_on_up; - int flap_detection_on_down; - int flap_detection_on_unreachable; - int stalk_on_up; - int stalk_on_down; - int stalk_on_unreachable; + int flap_detection_options; + unsigned int stalking_options; int check_freshness; int freshness_threshold; int process_performance_data; int checks_enabled; - int accept_passive_host_checks; + const char *check_source; + int accept_passive_checks; int event_handler_enabled; int retain_status_information; int retain_nonstatus_information; - int failure_prediction_enabled; - char *failure_prediction_options; - int obsess_over_host; + int obsess; char *notes; char *notes_url; char *action_url; char *icon_image; char *icon_image_alt; + char *statusmap_image; /* used by lots of graphing tools */ +/* #ifdef NSCGI */ + /* + * these are kept in ancillary storage for the daemon and + * thrown out as soon as we've created the object cache. + * The CGI's still attach them though, since they are the + * only users of this utter crap. + */ char *vrml_image; - char *statusmap_image; int have_2d_coords; int x_2d; int y_2d; @@ -321,8 +458,9 @@ struct host_struct { double y_3d; double z_3d; int should_be_drawn; +/* #endif */ customvariablesmember *custom_variables; -#ifdef NSCORE +#ifndef NSCGI int problem_has_been_acknowledged; int acknowledgement_type; int check_type; @@ -343,8 +481,8 @@ struct host_struct { int is_executing; int check_options; int notifications_enabled; - time_t last_host_notification; - time_t next_host_notification; + time_t last_notification; + time_t next_notification; time_t next_check; int should_be_scheduled; time_t last_check; @@ -355,8 +493,7 @@ struct host_struct { time_t last_time_unreachable; int has_been_checked; int is_being_freshened; - int notified_on_down; - int notified_on_unreachable; + int notified_on; int current_notification_number; int no_more_notifications; unsigned long current_notification_id; @@ -372,88 +509,81 @@ struct host_struct { int total_services; unsigned long total_service_check_interval; unsigned long modified_attributes; - int circular_path_checked; - int contains_circular_path; - - command *event_handler_ptr; - command *check_command_ptr; - timeperiod *check_period_ptr; - timeperiod *notification_period_ptr; - objectlist *hostgroups_ptr; #endif - struct host_struct *next; - void *next_check_event; + + struct command *event_handler_ptr; + struct command *check_command_ptr; + struct timeperiod *check_period_ptr; + struct timeperiod *notification_period_ptr; + struct objectlist *hostgroups_ptr; + /* objects we depend upon */ + struct objectlist *exec_deps, *notify_deps; + struct objectlist *escalation_list; + struct host *next; + struct timed_event *next_check_event; }; /* SERVICEGROUP structure */ -typedef struct servicegroup_struct { +typedef struct servicegroup { + unsigned int id; char *group_name; char *alias; - servicesmember *members; + struct servicesmember *members; char *notes; char *notes_url; char *action_url; - struct servicegroup_struct *next; - struct servicegroup_struct *nexthash; + struct servicegroup *next; } servicegroup; /* SERVICE structure */ -struct service_struct { +struct service { + unsigned int id; char *host_name; char *description; char *display_name; - char *service_check_command; + struct servicesmember *parents; + struct servicesmember *children; + char *check_command; char *event_handler; int initial_state; double check_interval; double retry_interval; int max_attempts; int parallelize; - contactgroupsmember *contact_groups; - contactsmember *contacts; + struct contactgroupsmember *contact_groups; + struct contactsmember *contacts; double notification_interval; double first_notification_delay; - int notify_on_unknown; - int notify_on_warning; - int notify_on_critical; - int notify_on_recovery; - int notify_on_flapping; - int notify_on_downtime; - int stalk_on_ok; - int stalk_on_warning; - int stalk_on_unknown; - int stalk_on_critical; + unsigned int notification_options; + unsigned int stalking_options; + unsigned int hourly_value; int is_volatile; char *notification_period; char *check_period; int flap_detection_enabled; double low_flap_threshold; double high_flap_threshold; - int flap_detection_on_ok; - int flap_detection_on_warning; - int flap_detection_on_unknown; - int flap_detection_on_critical; + unsigned int flap_detection_options; int process_performance_data; int check_freshness; int freshness_threshold; - int accept_passive_service_checks; + int accept_passive_checks; int event_handler_enabled; int checks_enabled; + const char *check_source; int retain_status_information; int retain_nonstatus_information; int notifications_enabled; - int obsess_over_service; - int failure_prediction_enabled; - char *failure_prediction_options; + int obsess; char *notes; char *notes_url; char *action_url; char *icon_image; char *icon_image_alt; - customvariablesmember *custom_variables; -#ifdef NSCORE + struct customvariablesmember *custom_variables; +#ifndef NSCGI int problem_has_been_acknowledged; int acknowledgement_type; int host_problem_at_last_check; @@ -485,9 +615,7 @@ struct service_struct { time_t last_time_critical; int has_been_checked; int is_being_freshened; - int notified_on_unknown; - int notified_on_warning; - int notified_on_critical; + unsigned int notified_on; int current_notification_number; unsigned long current_notification_id; double latency; @@ -502,46 +630,43 @@ struct service_struct { unsigned long flapping_comment_id; double percent_state_change; unsigned long modified_attributes; - - host *host_ptr; - command *event_handler_ptr; - char *event_handler_args; - command *check_command_ptr; - char *check_command_args; - timeperiod *check_period_ptr; - timeperiod *notification_period_ptr; - objectlist *servicegroups_ptr; #endif - struct service_struct *next; - void *next_check_event; + + struct host *host_ptr; + struct command *event_handler_ptr; + char *event_handler_args; + struct command *check_command_ptr; + char *check_command_args; + struct timeperiod *check_period_ptr; + struct timeperiod *notification_period_ptr; + struct objectlist *servicegroups_ptr; + struct objectlist *exec_deps, *notify_deps; + struct objectlist *escalation_list; + struct service *next; + struct timed_event *next_check_event; }; /* SERVICE ESCALATION structure */ -typedef struct serviceescalation_struct { +typedef struct serviceescalation { + unsigned int id; char *host_name; char *description; int first_notification; int last_notification; double notification_interval; char *escalation_period; - int escalate_on_recovery; - int escalate_on_warning; - int escalate_on_unknown; - int escalate_on_critical; - contactgroupsmember *contact_groups; - contactsmember *contacts; -#ifdef NSCORE - service *service_ptr; - timeperiod *escalation_period_ptr; -#endif - struct serviceescalation_struct *next; - struct serviceescalation_struct *nexthash; + int escalation_options; + struct contactgroupsmember *contact_groups; + struct contactsmember *contacts; + struct service *service_ptr; + struct timeperiod *escalation_period_ptr; } serviceescalation; /* SERVICE DEPENDENCY structure */ -typedef struct servicedependency_struct { +typedef struct servicedependency { + unsigned int id; int dependency_type; char *dependent_host_name; char *dependent_service_description; @@ -549,200 +674,195 @@ typedef struct servicedependency_struct { char *service_description; char *dependency_period; int inherits_parent; - int fail_on_ok; - int fail_on_warning; - int fail_on_unknown; - int fail_on_critical; - int fail_on_pending; -#ifdef NSCORE - int circular_path_checked; - int contains_circular_path; - - service *master_service_ptr; - service *dependent_service_ptr; - timeperiod *dependency_period_ptr; -#endif - struct servicedependency_struct *next; - struct servicedependency_struct *nexthash; + int failure_options; + struct service *master_service_ptr; + struct service *dependent_service_ptr; + struct timeperiod *dependency_period_ptr; } servicedependency; /* HOST ESCALATION structure */ -typedef struct hostescalation_struct { +typedef struct hostescalation { + unsigned int id; char *host_name; int first_notification; int last_notification; double notification_interval; char *escalation_period; - int escalate_on_recovery; - int escalate_on_down; - int escalate_on_unreachable; - contactgroupsmember *contact_groups; - contactsmember *contacts; -#ifdef NSCORE - host *host_ptr; - timeperiod *escalation_period_ptr; -#endif - struct hostescalation_struct *next; - struct hostescalation_struct *nexthash; + int escalation_options; + struct contactgroupsmember *contact_groups; + struct contactsmember *contacts; + struct host *host_ptr; + struct timeperiod *escalation_period_ptr; } hostescalation; /* HOST DEPENDENCY structure */ -typedef struct hostdependency_struct { +typedef struct hostdependency { + unsigned int id; int dependency_type; char *dependent_host_name; char *host_name; char *dependency_period; int inherits_parent; - int fail_on_up; - int fail_on_down; - int fail_on_unreachable; - int fail_on_pending; -#ifdef NSCORE - int circular_path_checked; - int contains_circular_path; - - host *master_host_ptr; - host *dependent_host_ptr; - timeperiod *dependency_period_ptr; -#endif - struct hostdependency_struct *next; - struct hostdependency_struct *nexthash; + int failure_options; + struct host *master_host_ptr; + struct host *dependent_host_ptr; + struct timeperiod *dependency_period_ptr; } hostdependency; - - - -/****************** HASH STRUCTURES ********************/ - -typedef struct host_cursor_struct { - int host_hashchain_iterator; - host *current_host_pointer; - } host_cursor; - +extern struct command *command_list; +extern struct timeperiod *timeperiod_list; +extern struct host *host_list; +extern struct service *service_list; +extern struct contact *contact_list; +extern struct hostgroup *hostgroup_list; +extern struct servicegroup *servicegroup_list; +extern struct contactgroup *contactgroup_list; +extern struct hostescalation *hostescalation_list; +extern struct serviceescalation *serviceescalation_list; +extern struct command **command_ary; +extern struct timeperiod **timeperiod_ary; +extern struct host **host_ary; +extern struct service **service_ary; +extern struct contact **contact_ary; +extern struct hostgroup **hostgroup_ary; +extern struct servicegroup **servicegroup_ary; +extern struct contactgroup **contactgroup_ary; +extern struct hostescalation **hostescalation_ary; +extern struct hostdependency **hostdependency_ary; +extern struct serviceescalation **serviceescalation_ary; +extern struct servicedependency **servicedependency_ary; /********************* FUNCTIONS **********************/ /**** Top-level input functions ****/ -int read_object_config_data(char *, int, int, int); /* reads all external configuration data of specific types */ +int read_object_config_data(const char *, int); /* reads all external configuration data of specific types */ /**** Object Creation Functions ****/ -contact *add_contact(char *, char *, char *, char *, char **, char *, char *, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int); /* adds a contact definition */ -commandsmember *add_service_notification_command_to_contact(contact *, char *); /* adds a service notification command to a contact definition */ -commandsmember *add_host_notification_command_to_contact(contact *, char *); /* adds a host notification command to a contact definition */ -customvariablesmember *add_custom_variable_to_contact(contact *, char *, char *); /* adds a custom variable to a service definition */ -host *add_host(char *, char *, char *, char *, char *, int, double, double, int, int, int, int, int, int, double, double, char *, int, char *, int, int, char *, int, int, double, double, int, int, int, int, int, int, int, int, char *, int, int, char *, char *, char *, char *, char *, char *, char *, int, int, int, double, double, double, int, int, int, int, int); /* adds a host definition */ -hostsmember *add_parent_host_to_host(host *, char *); /* adds a parent host to a host definition */ -hostsmember *add_child_link_to_host(host *, host *); /* adds a child host to a host definition */ -contactgroupsmember *add_contactgroup_to_host(host *, char *); /* adds a contactgroup to a host definition */ -contactsmember *add_contact_to_host(host *, char *); /* adds a contact to a host definition */ -customvariablesmember *add_custom_variable_to_host(host *, char *, char *); /* adds a custom variable to a host definition */ -timeperiod *add_timeperiod(char *, char *); /* adds a timeperiod definition */ -timeperiodexclusion *add_exclusion_to_timeperiod(timeperiod *, char *); /* adds an exclusion to a timeperiod */ -timerange *add_timerange_to_timeperiod(timeperiod *, int, unsigned long, unsigned long); /* adds a timerange to a timeperiod definition */ -daterange *add_exception_to_timeperiod(timeperiod *, int, int, int, int, int, int, int, int, int, int, int, int); -timerange *add_timerange_to_daterange(daterange *, unsigned long, unsigned long); -hostgroup *add_hostgroup(char *, char *, char *, char *, char *); /* adds a hostgroup definition */ -hostsmember *add_host_to_hostgroup(hostgroup *, char *); /* adds a host to a hostgroup definition */ -servicegroup *add_servicegroup(char *, char *, char *, char *, char *); /* adds a servicegroup definition */ -servicesmember *add_service_to_servicegroup(servicegroup *, char *, char *); /* adds a service to a servicegroup definition */ -contactgroup *add_contactgroup(char *, char *); /* adds a contactgroup definition */ -contactsmember *add_contact_to_contactgroup(contactgroup *, char *); /* adds a contact to a contact group definition */ -command *add_command(char *, char *); /* adds a command definition */ -service *add_service(char *, char *, char *, char *, int, int, int, int, double, double, double, double, char *, int, int, int, int, int, int, int, int, char *, int, char *, int, int, double, double, int, int, int, int, int, int, int, int, int, int, char *, int, int, char *, char *, char *, char *, char *, int, int, int); /* adds a service definition */ -contactgroupsmember *add_contactgroup_to_service(service *, char *); /* adds a contact group to a service definition */ -contactsmember *add_contact_to_service(service *, char *); /* adds a contact to a host definition */ -serviceescalation *add_serviceescalation(char *, char *, int, int, double, char *, int, int, int, int); /* adds a service escalation definition */ -contactgroupsmember *add_contactgroup_to_serviceescalation(serviceescalation *, char *); /* adds a contact group to a service escalation definition */ -contactsmember *add_contact_to_serviceescalation(serviceescalation *, char *); /* adds a contact to a service escalation definition */ -customvariablesmember *add_custom_variable_to_service(service *, char *, char *); /* adds a custom variable to a service definition */ -servicedependency *add_service_dependency(char *, char *, char *, char *, int, int, int, int, int, int, int, char *); /* adds a service dependency definition */ -hostdependency *add_host_dependency(char *, char *, int, int, int, int, int, int, char *); /* adds a host dependency definition */ -hostescalation *add_hostescalation(char *, int, int, double, char *, int, int, int); /* adds a host escalation definition */ -contactsmember *add_contact_to_hostescalation(hostescalation *, char *); /* adds a contact to a host escalation definition */ -contactgroupsmember *add_contactgroup_to_hostescalation(hostescalation *, char *); /* adds a contact group to a host escalation definition */ +struct contact *add_contact(char *name, char *alias, char *email, char *pager, char **addresses, char *svc_notification_period, char *host_notification_period, int service_notification_options, int host_notification_options, int service_notifications_enabled, int host_notifications_enabled, int can_submit_commands, int retain_status_information, int retain_nonstatus_information, unsigned int minimum_value); +struct commandsmember *add_service_notification_command_to_contact(contact *, char *); /* adds a service notification command to a contact definition */ +struct commandsmember *add_host_notification_command_to_contact(contact *, char *); /* adds a host notification command to a contact definition */ +struct customvariablesmember *add_custom_variable_to_contact(contact *, char *, char *); /* adds a custom variable to a service definition */ +struct host *add_host(char *name, char *display_name, char *alias, char *address, char *check_period, int initial_state, double check_interval, double retry_interval, int max_attempts, int notification_options, double notification_interval, double first_notification_delay, char *notification_period, int notifications_enabled, char *check_command, int checks_enabled, int accept_passive_checks, char *event_handler, int event_handler_enabled, int flap_detection_enabled, double low_flap_threshold, double high_flap_threshold, int flap_detection_options, int stalking_options, int process_perfdata, int check_freshness, int freshness_threshold, char *notes, char *notes_url, char *action_url, char *icon_image, char *icon_image_alt, char *vrml_image, char *statusmap_image, int x_2d, int y_2d, int have_2d_coords, double x_3d, double y_3d, double z_3d, int have_3d_coords, int should_be_drawn, int retain_status_information, int retain_nonstatus_information, int obsess_over_host, unsigned int hourly_value); +struct hostsmember *add_parent_host_to_host(host *, char *); /* adds a parent host to a host definition */ +struct servicesmember *add_parent_service_to_service(service *, char *host_name, char *description); +struct hostsmember *add_child_link_to_host(host *, host *); /* adds a child host to a host definition */ +struct servicesmember *add_child_link_to_service(service *, service *); /* adds a child host to a host definition */ +struct contactgroupsmember *add_contactgroup_to_host(host *, char *); /* adds a contactgroup to a host definition */ +struct contactsmember *add_contact_to_host(host *, char *); /* adds a contact to a host definition */ +struct customvariablesmember *add_custom_variable_to_host(host *, char *, char *); /* adds a custom variable to a host definition */ +struct timeperiod *add_timeperiod(char *, char *); /* adds a timeperiod definition */ +struct timeperiodexclusion *add_exclusion_to_timeperiod(timeperiod *, char *); /* adds an exclusion to a timeperiod */ +struct timerange *add_timerange_to_timeperiod(timeperiod *, int, unsigned long, unsigned long); /* adds a timerange to a timeperiod definition */ +struct daterange *add_exception_to_timeperiod(timeperiod *, int, int, int, int, int, int, int, int, int, int, int, int); +struct timerange *add_timerange_to_daterange(daterange *, unsigned long, unsigned long); +struct hostgroup *add_hostgroup(char *, char *, char *, char *, char *); /* adds a hostgroup definition */ +struct hostsmember *add_host_to_hostgroup(hostgroup *, char *); /* adds a host to a hostgroup definition */ +struct servicegroup *add_servicegroup(char *, char *, char *, char *, char *); /* adds a servicegroup definition */ +struct servicesmember *add_service_to_servicegroup(servicegroup *, char *, char *); /* adds a service to a servicegroup definition */ +struct contactgroup *add_contactgroup(char *, char *); /* adds a contactgroup definition */ +struct contactsmember *add_contact_to_contactgroup(contactgroup *, char *); /* adds a contact to a contact group definition */ +struct command *add_command(char *, char *); /* adds a command definition */ +struct service *add_service(char *host_name, char *description, char *display_name, char *check_period, int initial_state, int max_attempts, int parallelize, int accept_passive_checks, double check_interval, double retry_interval, double notification_interval, double first_notification_delay, char *notification_period, int notification_options, int notifications_enabled, int is_volatile, char *event_handler, int event_handler_enabled, char *check_command, int checks_enabled, int flap_detection_enabled, double low_flap_threshold, double high_flap_threshold, int flap_detection_options, int stalking_options, int process_perfdata, int check_freshness, int freshness_threshold, char *notes, char *notes_url, char *action_url, char *icon_image, char *icon_image_alt, int retain_status_information, int retain_nonstatus_information, int obsess_over_service, unsigned int hourly_value); +struct contactgroupsmember *add_contactgroup_to_service(service *, char *); /* adds a contact group to a service definition */ +struct contactsmember *add_contact_to_service(service *, char *); /* adds a contact to a host definition */ +struct serviceescalation *add_serviceescalation(char *host_name, char *description, int first_notification, int last_notification, double notification_interval, char *escalation_period, int escalation_options); +struct contactgroupsmember *add_contactgroup_to_serviceescalation(serviceescalation *, char *); /* adds a contact group to a service escalation definition */ +struct contactsmember *add_contact_to_serviceescalation(serviceescalation *, char *); /* adds a contact to a service escalation definition */ +struct customvariablesmember *add_custom_variable_to_service(service *, char *, char *); /* adds a custom variable to a service definition */ +struct servicedependency *add_service_dependency(char *dependent_host_name, char *dependent_service_description, char *host_name, char *service_description, int dependency_type, int inherits_parent, int failure_options, char *dependency_period); +struct hostdependency *add_host_dependency(char *dependent_host_name, char *host_name, int dependency_type, int inherits_parent, int failure_options, char *dependency_period); +struct hostescalation *add_hostescalation(char *host_name, int first_notification, int last_notification, double notification_interval, char *escalation_period, int escalation_options); +struct contactsmember *add_contact_to_hostescalation(hostescalation *, char *); /* adds a contact to a host escalation definition */ +struct contactgroupsmember *add_contactgroup_to_hostescalation(hostescalation *, char *); /* adds a contact group to a host escalation definition */ -contactsmember *add_contact_to_object(contactsmember **, char *); /* adds a contact to an object */ -customvariablesmember *add_custom_variable_to_object(customvariablesmember **, char *, char *); /* adds a custom variable to an object */ +struct contactsmember *add_contact_to_object(contactsmember **, char *); /* adds a contact to an object */ +struct customvariablesmember *add_custom_variable_to_object(customvariablesmember **, char *, char *); /* adds a custom variable to an object */ -servicesmember *add_service_link_to_host(host *, service *); +struct servicesmember *add_service_link_to_host(host *, service *); -/*** Object Skiplist Functions ****/ -int init_object_skiplists(void); -int free_object_skiplists(void); int skiplist_compare_text(const char *val1a, const char *val1b, const char *val2a, const char *val2b); -int skiplist_compare_host(void *a, void *b); -int skiplist_compare_service(void *a, void *b); -int skiplist_compare_command(void *a, void *b); -int skiplist_compare_timeperiod(void *a, void *b); -int skiplist_compare_contact(void *a, void *b); -int skiplist_compare_contactgroup(void *a, void *b); -int skiplist_compare_hostgroup(void *a, void *b); -int skiplist_compare_servicegroup(void *a, void *b); -int skiplist_compare_hostescalation(void *a, void *b); -int skiplist_compare_serviceescalation(void *a, void *b); -int skiplist_compare_hostdependency(void *a, void *b); -int skiplist_compare_servicedependency(void *a, void *b); - int get_host_count(void); int get_service_count(void); +int create_object_tables(unsigned int *); /**** Object Search Functions ****/ -timeperiod *find_timeperiod(char *); /* finds a timeperiod object */ -host *find_host(char *); /* finds a host object */ -hostgroup *find_hostgroup(char *); /* finds a hostgroup object */ -servicegroup *find_servicegroup(char *); /* finds a servicegroup object */ -contact *find_contact(char *); /* finds a contact object */ -contactgroup *find_contactgroup(char *); /* finds a contactgroup object */ -command *find_command(char *); /* finds a command object */ -service *find_service(char *, char *); /* finds a service object */ +struct timeperiod *find_timeperiod(const char *); +struct host *find_host(const char *); +struct hostgroup *find_hostgroup(const char *); +struct servicegroup *find_servicegroup(const char *); +struct contact *find_contact(const char *); +struct contactgroup *find_contactgroup(const char *); +struct command *find_command(const char *); +struct service *find_service(const char *, const char *); -/**** Object Traversal Functions ****/ -hostescalation *get_first_hostescalation_by_host(char *, void **); -hostescalation *get_next_hostescalation_by_host(char *, void **); -serviceescalation *get_first_serviceescalation_by_service(char *, char *, void **); -serviceescalation *get_next_serviceescalation_by_service(char *, char *, void **); -hostdependency *get_first_hostdependency_by_dependent_host(char *, void **); -hostdependency *get_next_hostdependency_by_dependent_host(char *, void **); -servicedependency *get_first_servicedependency_by_dependent_service(char *, char *, void **); -servicedependency *get_next_servicedependency_by_dependent_service(char *, char *, void **); - -#ifdef NSCORE -int add_object_to_objectlist(objectlist **, void *); +#define OBJECTLIST_DUPE 1 +int add_object_to_objectlist(struct objectlist **, void *); +int prepend_object_to_objectlist(struct objectlist **, void *); +int prepend_unique_object_to_objectlist(struct objectlist **, void *, size_t size); int free_objectlist(objectlist **); -#endif /**** Object Query Functions ****/ -int is_host_immediate_child_of_host(host *, host *); /* checks if a host is an immediate child of another host */ -int is_host_primary_immediate_child_of_host(host *, host *); /* checks if a host is an immediate child (and primary child) of another host */ -int is_host_immediate_parent_of_host(host *, host *); /* checks if a host is an immediate child of another host */ -int is_host_member_of_hostgroup(hostgroup *, host *); /* tests whether or not a host is a member of a specific hostgroup */ -int is_host_member_of_servicegroup(servicegroup *, host *); /* tests whether or not a service is a member of a specific servicegroup */ -int is_service_member_of_servicegroup(servicegroup *, service *); /* tests whether or not a service is a member of a specific servicegroup */ -int is_contact_member_of_contactgroup(contactgroup *, contact *); /* tests whether or not a contact is a member of a specific contact group */ -int is_contact_for_host(host *, contact *); /* tests whether or not a contact is a contact member for a specific host */ -int is_escalated_contact_for_host(host *, contact *); /* checks whether or not a contact is an escalated contact for a specific host */ -int is_contact_for_service(service *, contact *); /* tests whether or not a contact is a contact member for a specific service */ -int is_escalated_contact_for_service(service *, contact *); /* checks whether or not a contact is an escalated contact for a specific service */ -int is_host_immediate_parent_of_host(host *, host *); /* tests whether or not a host is an immediate parent of another host */ +unsigned int host_services_value(struct host *h); +int is_host_immediate_child_of_host(struct host *, struct host *); /* checks if a host is an immediate child of another host */ +int is_host_primary_immediate_child_of_host(struct host *, struct host *); /* checks if a host is an immediate child (and primary child) of another host */ +int is_host_immediate_parent_of_host(struct host *, struct host *); /* checks if a host is an immediate child of another host */ +int is_host_member_of_hostgroup(struct hostgroup *, struct host *); /* tests whether or not a host is a member of a specific hostgroup */ +int is_host_member_of_servicegroup(struct servicegroup *, struct host *); /* tests whether or not a service is a member of a specific servicegroup */ +int is_service_member_of_servicegroup(struct servicegroup *, struct service *); /* tests whether or not a service is a member of a specific servicegroup */ +int is_contact_member_of_contactgroup(struct contactgroup *, struct contact *); /* tests whether or not a contact is a member of a specific contact group */ +int is_contact_for_host(struct host *, struct contact *); /* tests whether or not a contact is a contact member for a specific host */ +int is_contactgroup_for_host(struct host *, struct contactgroup *); + /* tests whether a contact group is a contract group for a specific host */ +int is_escalated_contact_for_host(struct host *, struct contact *); /* checks whether or not a contact is an escalated contact for a specific host */ +int is_contact_for_host_escalation(hostescalation *, contact *); + /* tests whether a contact is an contact for a particular host escalation */ +int is_contactgroup_for_host_escalation(hostescalation *, contactgroup *); + /* tests whether a contactgroup is a contactgroup for a particular + host escalation */ +int is_contact_for_service(struct service *, struct contact *); /* tests whether or not a contact is a contact member for a specific service */ +int is_contactgroup_for_service(struct service *, struct contactgroup *); + /* tests whether a contact group is a contract group for a specific service */ +int is_escalated_contact_for_host(struct host *, struct contact *); /* checks whether or not a contact is an escalated contact for a specific host */ +int is_escalated_contact_for_service(struct service *, struct contact *); /* checks whether or not a contact is an escalated contact for a specific service */ +int is_contact_for_service_escalation(serviceescalation *, contact *); + /* tests whether a contact is an contact for a particular service + escalation */ +int is_contactgroup_for_service_escalation(serviceescalation *, contactgroup *); +/* tests whether a contactgroup is a contactgroup for a particular + service escalation */ -int number_of_immediate_child_hosts(host *); /* counts the number of immediate child hosts for a particular host */ -int number_of_total_child_hosts(host *); /* counts the number of total child hosts for a particular host */ -int number_of_immediate_parent_hosts(host *); /* counts the number of immediate parents hosts for a particular host */ -int number_of_total_parent_hosts(host *); /* counts the number of total parents hosts for a particular host */ +int number_of_immediate_child_hosts(struct host *); /* counts the number of immediate child hosts for a particular host */ +int number_of_total_child_hosts(struct host *); /* counts the number of total child hosts for a particular host */ +int number_of_immediate_parent_hosts(struct host *); /* counts the number of immediate parents hosts for a particular host */ -#ifdef NSCORE -int check_for_circular_servicedependency_path(servicedependency *, servicedependency *, int); /* checks if a circular dependency exists for a given service */ -int check_for_circular_hostdependency_path(hostdependency *, hostdependency *, int); /* checks if a circular dependency exists for a given host */ +#ifndef NSCGI +void fcache_contactlist(FILE *fp, const char *prefix, struct contactsmember *list); +void fcache_contactgrouplist(FILE *fp, const char *prefix, struct contactgroupsmember *list); +void fcache_hostlist(FILE *fp, const char *prefix, struct hostsmember *list); +void fcache_customvars(FILE *fp, struct customvariablesmember *cvlist); +void fcache_timeperiod(FILE *fp, struct timeperiod *temp_timeperiod); +void fcache_command(FILE *fp, struct command *temp_command); +void fcache_contactgroup(FILE *fp, struct contactgroup *temp_contactgroup); +void fcache_hostgroup(FILE *fp, struct hostgroup *temp_hostgroup); +void fcache_servicegroup(FILE *fp, struct servicegroup *temp_servicegroup); +void fcache_contact(FILE *fp, struct contact *temp_contact); +void fcache_host(FILE *fp, struct host *temp_host); +void fcache_service(FILE *fp, struct service *temp_service); +void fcache_servicedependency(FILE *fp, struct servicedependency *temp_servicedependency); +void fcache_serviceescalation(FILE *fp, struct serviceescalation *temp_serviceescalation); +void fcache_hostdependency(FILE *fp, struct hostdependency *temp_hostdependency); +void fcache_hostescalation(FILE *fp, struct hostescalation *temp_hostescalation); +int fcache_objects(char *cache_file); #endif diff --git a/include/perfdata.h b/include/perfdata.h index 6326f38..97e44bd 100644 --- a/include/perfdata.h +++ b/include/perfdata.h @@ -2,8 +2,6 @@ * * PERFDATA.H - Include file for performance data routines * - * Copyright (c) 2001-2005 Ethan Galstad (egalstad@nagios.org) - * Last Modified: 11-25-2005 * * License: * @@ -22,19 +20,19 @@ * *****************************************************************************/ -#ifndef _PERFDATA_H -#define _PERFDATA_H +#ifndef NAGIOS_PERFDATA_H_INCLUDED +#define NAGIOS_PERFDATA_H_INCLUDED -#include "compat.h" +#include "common.h" #include "objects.h" NAGIOS_BEGIN_DECL -int initialize_performance_data(char *); /* initializes performance data */ -int cleanup_performance_data(char *); /* cleans up performance data */ +int initialize_performance_data(const char *); /* initializes performance data */ +int cleanup_performance_data(void); /* cleans up performance data */ -int update_host_performance_data(host *); /* updates host performance data */ -int update_service_performance_data(service *); /* updates service performance data */ +int update_host_performance_data(host *); /* updates host performance data */ +int update_service_performance_data(service *); /* updates service performance data */ NAGIOS_END_DECL #endif diff --git a/include/shared.h b/include/shared.h index 021f425..6caa090 100644 --- a/include/shared.h +++ b/include/shared.h @@ -1,8 +1,8 @@ -#ifndef INCLUDE__shared_h__ -#define INCLUDE__shared_h__ +#ifndef NAGIOS_SHARED_H_INCLUDED +#define NAGIOS_SHARED_H_INCLUDED #include -#include "compat.h" +#include "lib/libnagios.h" NAGIOS_BEGIN_DECL @@ -17,12 +17,29 @@ typedef struct mmapfile_struct { void *mmap_buf; } mmapfile; -/* only usable on compile-time initialized arrays, for obvious reasons */ -#define ARRAY_SIZE(ary) (sizeof(ary) / sizeof(ary[0])) +/* official count of first-class objects */ +struct object_count { + unsigned int commands; + unsigned int timeperiods; + unsigned int hosts; + unsigned int hostescalations; + unsigned int hostdependencies; + unsigned int services; + unsigned int serviceescalations; + unsigned int servicedependencies; + unsigned int contacts; + unsigned int contactgroups; + unsigned int hostgroups; + unsigned int servicegroups; + }; -extern char *my_strtok(char *buffer, char *tokens); +extern struct object_count num_objects; + +extern void init_shared_cfg_vars(int); +extern void timing_point(const char *fmt, ...); /* print a message and the time since the first message */ +extern char *my_strtok(char *buffer, const char *tokens); extern char *my_strsep(char **stringp, const char *delim); -extern mmapfile *mmap_fopen(char *filename); +extern mmapfile *mmap_fopen(const char *filename); extern int mmap_fclose(mmapfile *temp_mmapfile); extern char *mmap_fgets(mmapfile *temp_mmapfile); extern char *mmap_fgets_multiline(mmapfile * temp_mmapfile); diff --git a/include/skiplist.h b/include/skiplist.h deleted file mode 100644 index 18d3add..0000000 --- a/include/skiplist.h +++ /dev/null @@ -1,70 +0,0 @@ -/************************************************************************ - * - * SKIPLIST.H - Skiplist data structures and functions - * - * Copyright (c) 2008 Ethan Galstad - * Last Modified: 02-24-2008 - * - * License: - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - ************************************************************************/ - -#ifndef _SKIPLIST_H -#define _SKIPLIST_H -#include "compat.h" - -#define SKIPLIST_OK 0 -#define SKIPLIST_ERROR_ARGS 1 -#define SKIPLIST_ERROR_MEMORY 2 -#define SKIPLIST_ERROR_DUPLICATE 3 - -NAGIOS_BEGIN_DECL - -typedef struct skiplistnode_struct { - void *data; - struct skiplistnode_struct *forward[1]; /* this must be the last element of the struct, as we allocate # of elements during runtime*/ - } skiplistnode; - -typedef struct skiplist_struct { - int current_level; - int max_levels; - float level_probability; - unsigned long items; - int allow_duplicates; - int append_duplicates; - int (*compare_function)(void *, void *); - skiplistnode *head; - } skiplist; - - -skiplist *skiplist_new(int max_levels, float level_probability, int allow_duplicates, int append_duplicates, int (*compare_function)(void *, void *)); -skiplistnode *skiplist_new_node(skiplist *list, int node_levels); -int skiplist_insert(skiplist *list, void *data); -int skiplist_random_level(skiplist *list); -int skiplist_empty(skiplist *list); -int skiplist_free(skiplist **list); -void *skiplist_peek(skiplist *); -void *skiplist_pop(skiplist *); -void *skiplist_get_first(skiplist *list, void **node_ptr); -void *skiplist_get_next(void **node_ptr); -void *skiplist_find_first(skiplist *list, void *data, void **node_ptr); -void *skiplist_find_next(skiplist *list, void *data, void **node_ptr); -int skiplist_delete(skiplist *list, void *data); -int skiplist_delete_first(skiplist *list, void *data); -int skiplist_delete_all(skiplist *list, void *data); -int skiplist_delete_node(skiplist *list, void *node_ptr); - -NAGIOS_END_DECL -#endif diff --git a/include/snprintf.h.in b/include/snprintf.h.in deleted file mode 100644 index c4a1446..0000000 --- a/include/snprintf.h.in +++ /dev/null @@ -1,3 +0,0 @@ -/* -*- C -*- */ -#undef HAVE_SNPRINTF -#undef NEED_VA_LIST diff --git a/include/sretention.h b/include/sretention.h index 95379db..5485c24 100644 --- a/include/sretention.h +++ b/include/sretention.h @@ -2,8 +2,6 @@ * * SRETENTION.H - Header for state retention routines * - * Copyright (c) 1999-2006 Ethan Galstad (egalstad@nagios.org) - * Last Modified: 02-28-2006 * * License: * @@ -22,11 +20,11 @@ * *****************************************************************************/ -#include "compat.h" +#include "common.h" NAGIOS_BEGIN_DECL -int initialize_retention_data(char *); -int cleanup_retention_data(char *); +int initialize_retention_data(const char *); +int cleanup_retention_data(void); int save_state_information(int); /* saves all host and state information */ int read_initial_state_information(void); /* reads in initial host and state information */ diff --git a/include/statusdata.h b/include/statusdata.h index fdb6f0c..3910c3e 100644 --- a/include/statusdata.h +++ b/include/statusdata.h @@ -2,8 +2,6 @@ * * STATUSDATA.H - Header for external status data routines * - * Copyright (c) 2000-2007 Ethan Galstad (egalstad@nagios.org) - * Last Modified: 10-19-2007 * * License: * @@ -22,17 +20,13 @@ * *****************************************************************************/ -#ifndef _STATUSDATA_H -#define _STATUSDATA_H +#ifndef NAGIOS_STATUSDATA_H_INCLUDED +#define NAGIOS_STATUSDATA_H_INCLUDED -#include "compat.h" - -#ifdef NSCORE +#include "common.h" #include "objects.h" -#endif #ifdef NSCGI - #define READ_PROGRAM_STATUS 1 #define READ_HOST_STATUS 2 #define READ_SERVICE_STATUS 4 @@ -82,7 +76,7 @@ typedef struct hoststatus_struct { int problem_has_been_acknowledged; int acknowledgement_type; int current_notification_number; - int accept_passive_host_checks; + int accept_passive_checks; int event_handler_enabled; int checks_enabled; int flap_detection_enabled; @@ -91,9 +85,8 @@ typedef struct hoststatus_struct { double latency; double execution_time; int scheduled_downtime_depth; - int failure_prediction_enabled; int process_performance_data; - int obsess_over_host; + int obsess; struct hoststatus_struct *next; struct hoststatus_struct *nexthash; } hoststatus; @@ -132,7 +125,7 @@ typedef struct servicestatus_struct { int problem_has_been_acknowledged; int acknowledgement_type; int current_notification_number; - int accept_passive_service_checks; + int accept_passive_checks; int event_handler_enabled; int flap_detection_enabled; int is_flapping; @@ -140,9 +133,8 @@ typedef struct servicestatus_struct { double latency; double execution_time; int scheduled_downtime_depth; - int failure_prediction_enabled; int process_performance_data; - int obsess_over_service; + int obsess; struct servicestatus_struct *next; struct servicestatus_struct *nexthash; } servicestatus; @@ -161,16 +153,16 @@ typedef struct servicestatus_struct { /**************************** HOST STATES ****************************/ #define HOST_PENDING 1 -#define HOST_UP 2 -#define HOST_DOWN 4 -#define HOST_UNREACHABLE 8 +#define SD_HOST_UP 2 +#define SD_HOST_DOWN 4 +#define SD_HOST_UNREACHABLE 8 /* Convert the (historically ordered) host states into a notion of "urgency". This is defined as, in ascending order: - HOST_UP (business as usual) + SD_HOST_UP (business as usual) HOST_PENDING (waiting for - supposedly first - check result) - HOST_UNREACHABLE (a problem, but likely not its cause) - HOST_DOWN (look here!!) + SD_HOST_UNREACHABLE (a problem, but likely not its cause) + SD_HOST_DOWN (look here!!) The exact values are irrelevant, so I try to make the conversion as CPU-efficient as possible: */ #define HOST_URGENCY(hs) ((hs)|(((hs)&0x5)<<1)) @@ -179,7 +171,7 @@ typedef struct servicestatus_struct { /**************************** FUNCTIONS ******************************/ -int read_status_data(char *, int); /* reads all status data */ +int read_status_data(const char *, int); /* reads all status data */ int add_host_status(hoststatus *); /* adds a host status entry to the list in memory */ int add_service_status(servicestatus *); /* adds a service status entry to the list in memory */ @@ -193,10 +185,10 @@ int get_servicestatus_count(char *, int); /* gets total number of services of a void free_status_data(void); /* free all memory allocated to status data */ #endif -#ifdef NSCORE -int initialize_status_data(char *); /* initializes status data at program start */ +#ifndef NSCGI +int initialize_status_data(const char *); /* initializes status data at program start */ int update_all_status_data(void); /* updates all status data */ -int cleanup_status_data(char *, int); /* cleans up status data at program termination */ +int cleanup_status_data(int); /* cleans up status data at program termination */ int update_program_status(int); /* updates program status data */ int update_host_status(host *, int); /* updates host status data */ int update_service_status(service *, int); /* updates service status data */ diff --git a/include/statusjson.h b/include/statusjson.h new file mode 100644 index 0000000..63e0ea8 --- /dev/null +++ b/include/statusjson.h @@ -0,0 +1,280 @@ +/************************************************************************** + * + * STATUSJSON.H - Nagios CGI for returning JSON-formatted status data + * + * Copyright (c) 2013 Nagios Enterprises, LLC + * Last Modified: 04-13-2013 + * + * License: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + *************************************************************************/ + +#ifndef NAGIOS_STATUSJSON_H_INCLUDED +#define NAGIOS_STATUSJSON_H_INCLUDED + +/* Structure containing CGI query string options and values */ +typedef struct status_json_cgi_data_struct { + /* Format options for JSON output */ + unsigned format_options; + /* Query being requested */ + int query; + /* Index of starting object returned for list requests */ + int start; + /* Number of objects returned for list requests */ + int count; + /* Return details for each entity in a list request */ + int details; + /* strftime format string for time_t values */ + char * strftime_format; + /* Name of host whose children should be returned if parenthost is + specified */ + char * parent_host_name; + /* Use the parent host field or search all hosts*/ + int use_parent_host; + /* Host whose children should be returned if use_parent_host is non-zero */ + host * parent_host; + /* Name of host whose parents should be returned if childhost is + specified */ + char * child_host_name; + /* Use the child host field or search all hosts*/ + int use_child_host; + /* Host whose parents should be returned if use_child_host is non-zero */ + host * child_host; + /* Name of host for which details should be returned */ + char * host_name; + /* Host whose host name is host_name */ + host * host; + /* The host status selector values */ + unsigned host_statuses; + /* Name of hostgroup for which details should be returned */ + char * hostgroup_name; + /* Hostgroup whose name is hostgroup_name */ + hostgroup * hostgroup; + /* Name of servicegroup for which details should be returned */ + char * servicegroup_name; + /* Servicegroup whose name is servicegroup_name */ + servicegroup * servicegroup; + /* Name of service for which details should be returned */ + char * service_description; + /* Service whose host name is host_name and whose description is + service_description*/ + service * service; + /* The service status selector values */ + unsigned service_statuses; + /* Name of service whose children should be returned if parentservice is + specified */ + char * parent_service_name; + /* Name of service whose parents should be returned if childservice is + specified */ + char * child_service_name; + /* Name of contactgroup for which details should be returned */ + char * contactgroup_name; + /* Contactgroup whose name is contactgroup_name */ + contactgroup * contactgroup; + /* Name of contact for which details should be returned */ + char * contact_name; + /* Contact whose contact name is contact_name */ + contact * contact; + /* Name of check timeperiod for which details should be returned */ + char * check_timeperiod_name; + /* Timeperiod whose timeperiod name is check_timeperiod_name */ + timeperiod *check_timeperiod; + /* Name of host notification timeperiod for which details should + be returned */ + char * host_notification_timeperiod_name; + /* Timeperiod whose timeperiod name is host_notification_timeperiod_name */ + timeperiod *host_notification_timeperiod; + /* Name of service notification timeperiod for which details should + be returned */ + char * service_notification_timeperiod_name; + /* Timeperiod whose timeperiod name is + service_notification_timeperiod_name */ + timeperiod *service_notification_timeperiod; + /* Name of check command to be used as a selector */ + char * check_command_name; + /* Command whose command name is check_command_name */ + command * check_command; + /* Name of event handle to be used as a selector */ + char * event_handler_name; + /* Command whose command name is event_handler_name */ + command * event_handler; + /* Type(s) of comments to include in comment count and list results */ + unsigned comment_types; + /* Entry type(s) of comments to include in comment count and list results */ + unsigned entry_types; + /* Persistence(s) of comments to include in comment count and list + results */ + unsigned persistence; + /* Whether comments that are expiring, non-expiring, or both are included + in comment count and list results */ + unsigned expiring; + /* ID of comment for which details should be returned */ + int comment_id; + /* Comment whose id is comment_id */ + nagios_comment *comment; + /* ID of downtime for which details should be returned */ + int downtime_id; + /* Downtime whose id is downtime_id */ + scheduled_downtime * downtime; + /* Start time for time-based queries */ + time_t start_time; + /* End time for time-based queries */ + time_t end_time; + /* Field on which to base time for hostcount and hostlist queries */ + int host_time_field; + /* Field on which to base time for servicecount and servicelist queries */ + int service_time_field; + /* Field on which to base time for commentcount and commentlist queries */ + int comment_time_field; + /* Field on which to base time for downtimecount and downtimelist queries */ + int downtime_time_field; + /* Object type to use for downtimecount and downtimelist queries */ + unsigned downtime_object_types; + /* Downtime type to use for downtimecount and downtimelist queries */ + unsigned downtime_types; + /* Whether downtimes that are triggered, non-triggered, or both are + included in downtime count and list results */ + unsigned triggered; + /* ID of a triggering downtime */ + int triggered_by; + /* Whether downtimes that are or are not in effect or both are included + in downtime count and list results */ + unsigned in_effect; + } status_json_cgi_data; + +/* Status Type Information */ +#define STATUS_QUERY_INVALID 0 +#define STATUS_QUERY_HOSTCOUNT 1 +#define STATUS_QUERY_HOSTLIST 2 +#define STATUS_QUERY_HOST 3 +#define STATUS_QUERY_SERVICECOUNT 4 +#define STATUS_QUERY_SERVICELIST 5 +#define STATUS_QUERY_SERVICE 6 +#if 0 +#define STATUS_QUERY_CONTACTCOUNT 7 +#define STATUS_QUERY_CONTACTLIST 8 +#define STATUS_QUERY_CONTACT 9 +#endif +#define STATUS_QUERY_COMMENTCOUNT 10 +#define STATUS_QUERY_COMMENTLIST 11 +#define STATUS_QUERY_COMMENT 12 +#define STATUS_QUERY_DOWNTIMECOUNT 13 +#define STATUS_QUERY_DOWNTIMELIST 14 +#define STATUS_QUERY_DOWNTIME 16 +#define STATUS_QUERY_PROGRAMSTATUS 17 +#define STATUS_QUERY_PERFORMANCEDATA 18 +#define STATUS_QUERY_HELP 19 + +/* Status Time Fields */ +#define STATUS_TIME_INVALID 0 +#define STATUS_TIME_LAST_UPDATE 1 /* host, service */ +#define STATUS_TIME_LAST_CHECK 2 /* host, service */ +#define STATUS_TIME_NEXT_CHECK 3 /* host, service */ +#define STATUS_TIME_LAST_STATE_CHANGE 4 /* host, service */ +#define STATUS_TIME_LAST_HARD_STATE_CHANGE 5 /* host, service */ +#define STATUS_TIME_LAST_TIME_UP 6 /* host */ +#define STATUS_TIME_LAST_TIME_DOWN 7 /* host */ +#define STATUS_TIME_LAST_TIME_UNREACHABLE 8 /* host */ +#define STATUS_TIME_LAST_TIME_OK 9 /* service */ +#define STATUS_TIME_LAST_TIME_WARNING 10 /* service */ +#define STATUS_TIME_LAST_TIME_CRITICAL 11 /* service */ +#define STATUS_TIME_LAST_TIME_UNKNOWN 12 /* service */ +#define STATUS_TIME_LAST_NOTIFICATION 13 /* host, service */ +#define STATUS_TIME_NEXT_NOTIFICATION 14 /* host, service */ +#define STATUS_TIME_ENTRY_TIME 15 /* comment, downtime */ +#define STATUS_TIME_EXPIRE_TIME 16 /* comment */ +#define STATUS_TIME_START_TIME 17 /* downtime */ +#define STATUS_TIME_FLEX_DOWNTIME_START 18 /* downtime */ +#define STATUS_TIME_END_TIME 19 /* downtime */ + +/* Comment Types */ +#define COMMENT_TYPE_HOST 1 +#define COMMENT_TYPE_SERVICE 2 +#define COMMENT_TYPE_ALL (COMMENT_TYPE_HOST | COMMENT_TYPE_SERVICE) + +/* Comment Entry Types */ +#define COMMENT_ENTRY_USER 1 +#define COMMENT_ENTRY_DOWNTIME 2 +#define COMMENT_ENTRY_FLAPPING 4 +#define COMMENT_ENTRY_ACKNOWLEDGEMENT 8 +#define COMMENT_ENTRY_ALL (COMMENT_ENTRY_USER |\ + COMMENT_ENTRY_DOWNTIME |\ + COMMENT_ENTRY_FLAPPING |\ + COMMENT_ENTRY_ACKNOWLEDGEMENT) + +/* Downtime Object Types */ +#define DOWNTIME_OBJECT_TYPE_HOST 1 +#define DOWNTIME_OBJECT_TYPE_SERVICE 2 +#define DOWNTIME_OBJECT_TYPE_ALL (DOWNTIME_OBJECT_TYPE_HOST |\ + DOWNTIME_OBJECT_TYPE_SERVICE) + +/* Downtime Types */ +#define DOWNTIME_TYPE_FIXED 1 +#define DOWNTIME_TYPE_FLEXIBLE 2 +#define DOWNTIME_TYPE_ALL (DOWNTIME_TYPE_FIXED | DOWNTIME_TYPE_FLEXIBLE) + +extern json_object *json_status_hostcount(unsigned, int, host *, int, host *, + hostgroup *, int, contact *, int, time_t, time_t, contactgroup *, + timeperiod *, timeperiod *, command *, command *); +extern json_object *json_status_hostlist(unsigned, int, int, int, int, host *, + int, host *, hostgroup *, int, contact *, int, time_t, time_t, + contactgroup *, timeperiod *, timeperiod *, command *, command *); +extern json_object *json_status_host(unsigned, host *, hoststatus *); +extern void json_status_host_details(json_object *, unsigned, host *, + hoststatus *); + +extern json_object *json_status_servicecount(unsigned, host *, int, host *, + int, host *, hostgroup *, servicegroup *, int, int, contact *, int, + time_t, time_t, char *, char *, char *, contactgroup *, timeperiod *, + timeperiod *, command *, command *); +extern json_object *json_status_servicelist(unsigned, int, int, int, host *, + int, host *, int, host *, hostgroup *, servicegroup *, int, int, + contact *, int, time_t, time_t, char *, char *, char *, contactgroup *, + timeperiod *, timeperiod *, command *, command *); +extern json_object *json_status_service(unsigned, service *, servicestatus *); +extern void json_status_service_details(json_object *, unsigned, service *, + servicestatus *); + +#if 0 +extern void json_status_contactlist(unsigned, unsigned, unsigned, unsigned, + unsigned, contactgroup *); +extern void json_status_contactlist(unsigned, unsigned, unsigned, unsigned, + unsigned, contactgroup *); +extern void json_status_contact(unsigned, unsigned, contact *); +extern void json_status_contact_details(unsigned, unsigned, contact *); +#endif + +extern json_object *json_status_commentcount(unsigned, int, time_t, time_t, + unsigned, unsigned, unsigned, unsigned, char *, char *); +extern json_object *json_status_commentlist(unsigned, int, int, int, int, + time_t, time_t, unsigned, unsigned, unsigned, unsigned, char *, char *); +extern json_object *json_status_comment(unsigned, nagios_comment *); +extern void json_status_comment_details(json_object *, unsigned, + nagios_comment *); + +extern json_object *json_status_downtimecount(unsigned, int, time_t, time_t, + unsigned, unsigned, unsigned, int, unsigned, char *, char *); +extern json_object *json_status_downtimelist(unsigned, int, int, int, int, + time_t, time_t, unsigned, unsigned, unsigned, int, unsigned, char *, + char *); +extern json_object *json_status_downtime(unsigned, scheduled_downtime *); +extern void json_status_downtime_details(json_object *, unsigned, + scheduled_downtime *); + +extern json_object *json_status_program(unsigned); + +extern json_object *json_status_performance(void); + +#endif diff --git a/include/workers.h b/include/workers.h new file mode 100644 index 0000000..58ce344 --- /dev/null +++ b/include/workers.h @@ -0,0 +1,60 @@ +#ifndef INCLUDE_WORKERS_H_INCLUDED +#define INCLUDE_WORKERS_H_INCLUDED +#include "lib/libnagios.h" +#include "lib/worker.h" +#include "nagios.h" /* for check_result definition */ + +/* different jobtypes. We add more as needed */ +#define WPJOB_CHECK 0 +#define WPJOB_NOTIFY 1 +#define WPJOB_OCSP 2 +#define WPJOB_OCHP 3 +#define WPJOB_GLOBAL_SVC_EVTHANDLER 4 +#define WPJOB_SVC_EVTHANDLER 5 +#define WPJOB_GLOBAL_HOST_EVTHANDLER 6 +#define WPJOB_HOST_EVTHANDLER 7 +#define WPJOB_CALLBACK 8 +#define WPJOB_HOST_PERFDATA 9 +#define WPJOB_SVC_PERFDATA 10 + +#define WPROC_FORCE (1 << 0) + +NAGIOS_BEGIN_DECL; + +typedef struct wproc_result { + unsigned int job_id; + unsigned int type; + time_t timeout; + struct timeval start; + struct timeval stop; + struct timeval runtime; + char *command; + char *outstd; + char *outerr; + char *error_msg; + int wait_status; + int error_code; + int exited_ok; + int early_timeout; + struct kvvec *response; + struct rusage rusage; +} wproc_result; + +extern unsigned int wproc_num_workers_spawned; +extern unsigned int wproc_num_workers_online; +extern unsigned int wproc_num_workers_desired; + +extern void wproc_reap(int jobs, int msecs); +extern int wproc_can_spawn(struct load_control *lc); +extern void free_worker_memory(int flags); +extern int workers_alive(void); +extern int init_workers(int desired_workers); +extern int wproc_run_check(check_result *cr, char *cmd, nagios_macros *mac); +extern int wproc_notify(char *cname, char *hname, char *sdesc, char *cmd, nagios_macros *mac); +extern int wproc_run(int job_type, char *cmd, int timeout, nagios_macros *mac); +extern int wproc_run_service_job(int jtype, int timeout, service *svc, char *cmd, nagios_macros *mac); +extern int wproc_run_host_job(int jtype, int timeout, host *hst, char *cmd, nagios_macros *mac); +extern int wproc_run_callback(char *cmt, int timeout, void (*cb)(struct wproc_result *, void *, int), void *data, nagios_macros *mac); + +NAGIOS_END_DECL; +#endif diff --git a/indent.sh b/indent.sh index d561da1..d9cf321 100755 --- a/indent.sh +++ b/indent.sh @@ -3,4 +3,4 @@ ARTISTIC_STYLE_OPTIONS=/dev/null export ARTISTIC_STYLE_OPTIONS -astyle --style=banner --indent=tab --unpad-paren --pad-oper --suffix=none "$@" +astyle --style=banner --indent=tab --unpad-paren --pad-oper --suffix=.pre-indent "$@" diff --git a/lib/.gitignore b/lib/.gitignore new file mode 100644 index 0000000..76185e6 --- /dev/null +++ b/lib/.gitignore @@ -0,0 +1,13 @@ +test-squeue +test-kvvec +test-iocache +test-iobroker +test-bitmap +test-dkhash +test-runcmd +test-fanout +test-nsutils +wproc +iobroker.h +snprintf.h +core diff --git a/lib/Makefile.in b/lib/Makefile.in new file mode 100644 index 0000000..86a0ab8 --- /dev/null +++ b/lib/Makefile.in @@ -0,0 +1,82 @@ +CC = @CC@ +COV_CFLAGS = -ggdb3 -O0 -ftest-coverage -fprofile-arcs -pg +LDFLAGS = +CFLAGS ?= -Wall @CFLAGS@ +ALL_CFLAGS = $(CFLAGS) @DEFS@ +LIBNAME = libnagios.a + +all: $(LIBNAME) + +SOCKETLIBS=@SOCKETLIBS@ +SNPRINTF_O=@SNPRINTF_O@ +TESTED_SRC_C := squeue.c kvvec.c iocache.c iobroker.c bitmap.c dkhash.c runcmd.c +TESTED_SRC_C += nsutils.c fanout.c +SRC_C := $(TESTED_SRC_C) pqueue.c worker.c skiplist.c nsock.c +SRC_C += nspath.c +SRC_O := $(patsubst %.c,%.o,$(SRC_C)) $(SNPRINTF_O) +TESTS := $(patsubst %.c,test-%,$(TESTED_SRC_C)) + +test: $(TESTS) + @for t in $(TESTS); do echo $$t:; ./$$t || exit 1; echo; done + +test-squeue: pqueue.o test-squeue.o t-utils.o + $(CC) $(ALL_CFLAGS) $(LDFLAGS) $^ -o $@ + +test-iocache: t-utils.o test-iocache.o + $(CC) $(ALL_CFLAGS) $(SOCKETLIBS) $^ -o $@ + +test-iobroker: t-utils.o test-iobroker.o + $(CC) $(ALL_CFLAGS) $(SOCKETLIBS) $^ -o $@ + +%.o: %.c %.h Makefile lnag-utils.h + $(CC) $(ALL_CFLAGS) -c $< -o $@ + +test-%.o: test-%.c %.c %.h Makefile + $(CC) $(ALL_CFLAGS) -c $< -o $@ + +test-%: t-utils.o test-%.o + $(CC) $(ALL_CFLAGS) $^ -o $@ + +$(LIBNAME): $(SRC_O) + $(AR) cr $@ $^ + +wproc: wproc.o $(LIBNAME) + $(CC) $(ALL_CFLAGS) $(ALL_LDFLAGS) $^ -o $@ + +coverage: + @$(MAKE) -s --no-print-directory clean + @$(MAKE) --no-print-directory cov-build + @$(MAKE) --no-print-directory cov-report + +cov-build: + $(MAKE) CFLAGS='$(COV_CFLAGS)' LDFLAGS='$(COV_CFLAGS)' test + +cov-report: + @{ for f in $(TESTS) pqueue; do \ + gcov -b -p $$f.c >/dev/null; \ + done; } + + @rm -f *.h.gcov test-*.c.gcov + @echo "--- untested functions:" | tee -a untested + @grep '^function .* called 0' *.c.gcov \ + | sed -e 's/function \([^ ]*\) called 0.*/\1/' \ + | sed -e 's/\.c\.gcov:/\.c:/' | tee -a untested + + +distclean: clean + rm -f Makefile iobroker.h + +clean: clean-test clean-coverage + rm -f core.* *.o *~ wproc *.a + +clean-test: clean-coverage + rm -f $(TESTS) + +clean-coverage: + rm -f untested *.gcov *.gcda *.gcno gmon.out + +.PHONY: clean clean-test clean-coverage coverage + +# stop make from removing intermediary files, as ours aren't really +# intermediary +.SECONDARY: diff --git a/lib/bitmap.c b/lib/bitmap.c new file mode 100644 index 0000000..3af89f9 --- /dev/null +++ b/lib/bitmap.c @@ -0,0 +1,311 @@ +#include +#include "bitmap.h" +#include +#include +#include + +#ifndef CHAR_BIT +# define CHAR_BIT 8 +#endif + +typedef unsigned int bmap; + +#define MAPSIZE (sizeof(bmap) * CHAR_BIT) +#define MAPMASK (MAPSIZE - 1) /* bits - 1, so 63 for 64-bit machines */ +#define SHIFTOUT (MAPSIZE == 64 ? 6 : 5) /* log2(bits) */ + +struct bitmap { + bmap *vector; + unsigned long alloc; +}; + +void bitmap_clear(bitmap *bm) +{ + if (bm) + memset(bm->vector, 0, bm->alloc * sizeof(bmap)); +} + +int bitmap_resize(bitmap *bm, unsigned long size) +{ + unsigned long ralloc; + bmap *nvec; + + if (!bm) + return -1; + + /* be tight on space */ + ralloc = (size >> SHIFTOUT) + !!(size & MAPMASK); + + if (!bm->vector) { + bm->vector = calloc(1, ralloc * sizeof(bmap)); + if (!bm->vector) + return -1; + bm->alloc = ralloc; + return 0; + } + + nvec = realloc(bm->vector, ralloc * sizeof(bmap)); + if (!nvec) { + return -1; + } + bm->vector = nvec; + bm->alloc = ralloc; + return 0; +} + +static bitmap *bitmap_init(bitmap *bm, unsigned long size) +{ + int ret; + + if (!bm) + return NULL; + + ret = bitmap_resize(bm, size); + if (ret < 0) + return NULL; + + return bm; +} + +bitmap *bitmap_create(unsigned long size) +{ + bitmap *bm; + + if (!(bm = calloc(1, sizeof(bitmap)))) + return NULL; + + if (bitmap_init(bm, size) == bm) + return bm; + + free(bm); + + return NULL; +} + +void bitmap_destroy(bitmap *bm) +{ + if (!bm) + return; + if (bm->vector) + free(bm->vector); + free(bm); +} + +bitmap *bitmap_copy(const bitmap *bm) +{ + bitmap *ret; + + if (!bm) + return NULL; + ret = bitmap_create(bitmap_cardinality(bm)); + if (!ret) + return NULL; + + memcpy(ret->vector, bm->vector, bitmap_size(bm)); + return ret; +} + +static inline unsigned int l_bits(bmap map) +{ + unsigned int i, tot_bits = 0; + + /* + * bits per byte. A 16k entry table would be slightly faster + * on most archs but a damn sight uglier on all of them + */ + const unsigned char bpb[256] = { + 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, + }; + + for (i = 0; i < sizeof(bmap); i++) { + const unsigned char ch = (map >> (i * CHAR_BIT)) & 0xff; + const unsigned char cbits = bpb[ch]; + tot_bits += cbits; + } + + return tot_bits; +} + + +int bitmap_set(bitmap *bm, unsigned long pos) +{ + const bmap l = pos >> SHIFTOUT; + const unsigned int bit = pos & MAPMASK; + + if (!bm) + return 0; + if (l > bm->alloc) + return -1; + + bm->vector[l] |= (1 << bit); + return 0; +} + +int bitmap_isset(const bitmap *bm, unsigned long pos) +{ + const bmap l = pos >> SHIFTOUT; + const int bit = pos & MAPMASK; + int set; + + if (!bm || l > bm->alloc) + return 0; + + set = !!(bm->vector[l] & (1 << bit)); + return set; +} + +int bitmap_unset(bitmap *bm, unsigned long pos) +{ + const bmap l = pos >> SHIFTOUT; + const int bit = pos & MAPMASK; + const int val = bitmap_isset(bm, pos); + + bm->vector[l] &= ~(1 << bit); + return val; +} + +unsigned long bitmap_cardinality(const bitmap *bm) +{ + if (!bm) + return 0; + + return bm->alloc * MAPSIZE; +} + +/* + * count set bits in alloc * (mapsize / 8) ops + */ +unsigned long bitmap_count_set_bits(const bitmap *bm) +{ + unsigned long i, set_bits = 0; + + if (!bm) + return 0; + + for (i = 0; i < bm->alloc; i++) { + set_bits += l_bits(bm->vector[i]); + } + + return set_bits; +} + +unsigned long bitmap_count_unset_bits(const bitmap *bm) +{ + return bitmap_cardinality(bm) - bitmap_count_set_bits(bm); +} + +#define BITMAP_MATH(a, b) \ + unsigned int i; \ + bitmap *bm; \ + /* a->alloc has to be smallest */ \ + if (a->alloc > b->alloc) { \ + const bitmap *temp = b; \ + b = a; \ + a = temp; \ + } \ + bm = bitmap_create(bitmap_cardinality(b)); \ + if (!bm) \ + return NULL; \ + for (i = 0; i < a->alloc; i++) + +bitmap *bitmap_intersect(const bitmap *a, const bitmap *b) +{ + BITMAP_MATH(a, b) { + bm->vector[i] = a->vector[i] & b->vector[i]; + } + + return bm; +} + + +bitmap *bitmap_union(const bitmap *a, const bitmap *b) +{ + if(!a) + return bitmap_copy(b); + if(!b) + return bitmap_copy(a); + do { + BITMAP_MATH(a, b) { + bm->vector[i] = a->vector[i] | b->vector[i]; + } + return bm; + } while(0); +} + +bitmap *bitmap_unite(bitmap *res, const bitmap *addme) +{ + unsigned int i; + + if(!addme || !res) + return res; + + if (bitmap_size(addme) > bitmap_size(res)) { + bitmap_resize(res, bitmap_size(addme)); + } + + for (i = 0; i < addme->alloc; i++) { + res->vector[i] |= addme->vector[i]; + } + return res; +} + +/* + * set difference gets everything in A that isn't also in B. A is the + * numerator, so if it's larger we must include any overflow in the + * resulting set. + */ +bitmap *bitmap_diff(const bitmap *a, const bitmap *b) +{ + const bitmap *a_ = a, *b_ = b; + + BITMAP_MATH(a, b) { + bm->vector[i] = a->vector[i] & ~(b->vector[i]); + } + if (a_->alloc > b_->alloc) { + memcpy(&bm->vector[i], &b->vector[i], (b->alloc - a->alloc) * MAPSIZE); + } + return bm; +} + +/* + * symmetric set difference lists all items only present in one set + */ +bitmap *bitmap_symdiff(const bitmap *a, const bitmap *b) +{ + BITMAP_MATH(a, b) { + bm->vector[i] = (a->vector[i] | b->vector[i]) ^ (a->vector[i] & b->vector[i]); + } + if (b->alloc > a->alloc) { + memcpy(&bm->vector[i], &b->vector[i], (b->alloc - a->alloc) * MAPSIZE); + } + return bm; +} + +#define min(a, b) (a > b ? b : a) +int bitmap_cmp(const bitmap *a, const bitmap *b) +{ + int ret; + + ret = memcmp(a->vector, b->vector, min(a->alloc, b->alloc) * MAPSIZE); + if (ret || a->alloc == b->alloc) { + return ret; + } + if (a->alloc > b->alloc) + return 1; + return -1; +} diff --git a/lib/bitmap.h b/lib/bitmap.h new file mode 100644 index 0000000..b729628 --- /dev/null +++ b/lib/bitmap.h @@ -0,0 +1,156 @@ +#ifndef LIBNAGIOS_bitmap_h__ +#define LIBNAGIOS_bitmap_h__ + +/** + * @file bitmap.h + * @brief Bit map API + * + * The bitmap api is useful for running set operations on objects + * indexed by unsigned integers. + * @{ + */ +struct bitmap; +typedef struct bitmap bitmap; + +/** + * Resize a bitmap + * If the bitmap is made smaller, data will silently be lost. + * + * @param bm The bitmap to resize + * @param size The new desired size of the bitmap + * @return 0 on success, -1 on errors. + */ +extern int bitmap_resize(bitmap *bm, unsigned long size); + +/** + * Create a bitmaptor of size 'size' + * @param size Desired storage capacity + * @return A bitmap pointer on success, NULL on errors + */ +extern bitmap *bitmap_create(unsigned long size); + +/** + * Destroy a bitmaptor by freeing all the memory it uses + * @param bm The bitmaptor to destroy + */ +extern void bitmap_destroy(bitmap *bm); + +/** + * Copy a bitmaptor + * @param bm The bitmaptor to copy + * @return Pointer to an identical bitmap on success, NULL on errors + */ +extern bitmap *bitmap_copy(const bitmap *bm); + +/** + * Set a bit in the map + * @param bm The bitmaptor to operate on + * @param pos Position of the bit to set + * @return 0 on success, -1 on errors + */ +extern int bitmap_set(bitmap *bm, unsigned long pos); + +/** + * Check if a particular bit is set in the map + * @param bm The bitmaptor to check + * @param pos Position of the bit to check + * @return 1 if set, otherwise 0 + */ +extern int bitmap_isset(const bitmap *bm, unsigned long pos); + +/** + * Unset a particular bit in the map + * @param bm The bitmaptor to operate on + * @param pos Position of the bit to unset + */ +extern int bitmap_unset(bitmap *bm, unsigned long pos); + +/** + * Obtain cardinality (max number of elements) of the bitmaptor + * @param bm The bitmaptor to check + * @return The cardinality of the bitmaptor + */ +extern unsigned long bitmap_cardinality(const bitmap *bm); +#define bitmap_size bitmap_cardinality + +/** + * Count set bits in map. Completed in O(n/8) time. + * @param bm The bitmaptor to count bits in + * @return The number of set bits + */ +extern unsigned long bitmap_count_set_bits(const bitmap *bm); + +/** + * Count unset bits in map. Completed in O(n/8) time. + * @param bm The bitmaptor to count bits in + * @return The number of set bits + */ +extern unsigned long bitmap_count_unset_bits(const bitmap *bm); + +/** + * Unset all bits in a bitmap + * @param bm The bitmap to clear + */ +extern void bitmap_clear(bitmap *bm); + +/** + * Calculate intersection of two bitmaps + * The intersection is defined as all bits that are members of + * both A and B. It's equivalent to bitwise AND. + * This function completes in O(n/sizeof(long)) operations. + * @param a The first bitmaptor + * @param b The second bitmaptor + * @return NULL on errors; A newly created bitmaptor on success. + */ +extern bitmap *bitmap_intersect(const bitmap *a, const bitmap *b); + +/** + * Calculate union of two bitmaps + * The union is defined as all bits that are members of + * A or B or both A and B. It's equivalent to bitwise OR. + * This function completes in O(n/sizeof(long)) operations. + * @param a The first bitmaptor + * @param b The second bitmaptor + * @return NULL on errors; A newly created bitmaptor on success. + */ +extern bitmap *bitmap_union(const bitmap *a, const bitmap *b); + +/** + * Calculate union of two bitmaps and store result in one of them + * @param res The first bitmap + * @param addme The bitmap to unite to the first bitmap + * @return NULL on errors, res on success + */ +extern bitmap *bitmap_unite(bitmap *res, const bitmap *addme); + +/** + * Calculate set difference between two bitmaps + * The set difference of A / B is defined as all members of A + * that isn't members of B. Note that parameter ordering matters + * for this function. + * This function completes in O(n/sizeof(long)) operations. + * @param a The first bitmaptor (numerator) + * @param b The first bitmaptor (denominator) + * @return NULL on errors; A newly created bitmaptor on success. + */ +extern bitmap *bitmap_diff(const bitmap *a, const bitmap *b); + +/** + * Calculate symmetric difference between two bitmaps + * The symmetric difference between A and B is the set that + * contains all elements in either set but not in both. + * This function completes in O(n/sizeof(long)) operations. + * @param a The first bitmaptor + * @param b The second bitmaptor + */ +extern bitmap *bitmap_symdiff(const bitmap *a, const bitmap *b); + +/** + * Compare two bitmaps for equality + * @param a The first bitmaptor + * @param b The other bitmaptor + * @return Similar to memcmp(), with tiebreaks determined by cardinality + */ +extern int bitmap_cmp(const bitmap *a, const bitmap *b); +/** @} */ +#endif /* LIBNAGIOS_bitmap_h__ */ diff --git a/lib/dkhash.c b/lib/dkhash.c new file mode 100644 index 0000000..d0b0deb --- /dev/null +++ b/lib/dkhash.c @@ -0,0 +1,269 @@ +#include +#include +#include "dkhash.h" +#include "lnag-utils.h" +#include "nsutils.h" + +typedef struct dkhash_bucket { + const char *key; + const char *key2; + void *data; + struct dkhash_bucket *next; +} dkhash_bucket; + +struct dkhash_table { + dkhash_bucket **buckets; + unsigned int num_buckets; + unsigned int added, removed; + unsigned int entries; + unsigned int max_entries; + unsigned int collisions; +}; + +/* struct data access functions */ +unsigned int dkhash_collisions(dkhash_table *t) +{ + return t ? t->collisions : 0; +} + +unsigned int dkhash_num_entries(dkhash_table *t) +{ + return t ? t->entries : 0; +} + +unsigned int dkhash_num_entries_max(dkhash_table *t) +{ + return t ? t->max_entries : 0; +} + +unsigned int dkhash_num_entries_added(dkhash_table *t) +{ + return t ? t->added : 0; +} + +unsigned int dkhash_num_entries_removed(dkhash_table *t) +{ + return t ? t->removed : 0; +} + +unsigned int dkhash_table_size(dkhash_table *t) +{ + return t ? t->num_buckets : 0; +} + +/* + * polynomial conversion ignoring overflows. + * Pretty standard hash, once based on Ozan Yigit's sdbm() hash + * but later modified for Nagios to produce better results on our + * typical data. + */ +#define PRIME 509 +static inline unsigned int hash(register const char *k) +{ + register unsigned int h = 0x123; /* magic */ + + while (*k) + h = *k++ + PRIME * h; + + return h; +} + +static inline unsigned int dkhash_slot(dkhash_table *t, const char *k1, const char *k2) +{ + register unsigned int h; + h = hash(k1); + if (k2) + h ^= hash(k2); + return h % t->num_buckets; +} + +static dkhash_bucket *dkhash_get_bucket(dkhash_table *t, const char *key, unsigned int slot) +{ + dkhash_bucket *bkt; + + for (bkt = t->buckets[slot]; bkt; bkt = bkt->next) { + if (!strcmp(key, bkt->key)) + return bkt; + } + + return NULL; +} + +static dkhash_bucket *dkhash_get_bucket2(dkhash_table *t, const char *k1, const char *k2, unsigned int slot) +{ + dkhash_bucket *bkt; + + for (bkt = t->buckets[slot]; bkt; bkt = bkt->next) { + if (!strcmp(k1, bkt->key) && bkt->key2 && !strcmp(k2, bkt->key2)) + return bkt; + } + + return NULL; +} + +int dkhash_insert(dkhash_table *t, const char *k1, const char *k2, void *data) +{ + unsigned int slot; + dkhash_bucket *bkt; + + if (!t || !k1) + return DKHASH_EINVAL; + + slot = dkhash_slot(t, k1, k2); + bkt = k2 ? dkhash_get_bucket2(t, k1, k2, slot) : dkhash_get_bucket(t, k1, slot); + + if (bkt) + return DKHASH_EDUPE; + + if (!(bkt = malloc(sizeof(*bkt)))) + return DKHASH_ENOMEM; + + if (t->buckets[slot]) + t->collisions++; /* "soft" collision */ + + t->added++; + bkt->data = data; + bkt->key = k1; + bkt->key2 = k2; + bkt->next = t->buckets[slot]; + t->buckets[slot] = bkt; + + if (++t->entries > t->max_entries) + t->max_entries = t->entries; + + return DKHASH_OK; +} + +void *dkhash_get(dkhash_table *t, const char *k1, const char *k2) +{ + dkhash_bucket *bkt; + unsigned int slot; + + if (!t || !k1) + return NULL; + + slot = dkhash_slot(t, k1, k2); + bkt = k2 ? dkhash_get_bucket2(t, k1, k2, slot) : dkhash_get_bucket(t, k1, slot); + + return bkt ? bkt->data : NULL; +} + +dkhash_table *dkhash_create(unsigned int size) +{ + double ratio; + unsigned int sz; + dkhash_table *t; + + if (!size) + return NULL; + + if(!(t = calloc(1, sizeof(*t)))) + return NULL; + + sz = rup2pof2(size); + ratio = (double)sz / (double)size; + if (ratio < 1.4) + sz = rup2pof2(sz + 1); + + if (!(t->buckets = calloc(sz, sizeof(dkhash_bucket *)))) { + free(t); + return NULL; + } + + t->num_buckets = sz; + return t; +} + +int dkhash_destroy(dkhash_table *t) +{ + unsigned int i; + + if (!t) + return DKHASH_EINVAL; + + for (i = 0; i < t->num_buckets; i++) { + dkhash_bucket *b, *next; + for (b = t->buckets[i]; b; b = next) { + next = b->next; + free(b); + } + } + free(t->buckets); + free(t); + return DKHASH_OK; +} + +static inline void *dkhash_destroy_bucket(dkhash_bucket *bkt) +{ + void *data; + + data = bkt->data; + free(bkt); + return data; +} + +void *dkhash_remove(dkhash_table *t, const char *k1, const char *k2) +{ + unsigned int slot; + dkhash_bucket *bkt, *prev; + + if (!t || !k1) + return NULL; + + slot = dkhash_slot(t, k1, k2); + if (!(bkt = t->buckets[slot])) + return NULL; + + for (prev = bkt; bkt; prev = bkt, bkt = bkt->next) { + if (strcmp(k1, bkt->key)) + continue; + if ((!k2 && !bkt->key2) || !strcmp(k2, bkt->key2)) { + if (prev == bkt) { + /* first entry deleted */ + t->buckets[slot] = bkt->next; + } + else { + prev->next = bkt->next; + } + t->entries--; + t->removed++; + return dkhash_destroy_bucket(bkt); + } + } + + return NULL; +} + +void dkhash_walk_data(dkhash_table *t, int (*walker)(void *)) { + dkhash_bucket *bkt, *prev; + unsigned int i; + + if (!t->entries) + return; + + for (i = 0; i < t->num_buckets; i++) { + int depth = 0; + dkhash_bucket *next; + + prev = t->buckets[i]; + for (bkt = t->buckets[i]; bkt; bkt = next) { + next = bkt->next; + + if (walker(bkt->data) != DKHASH_WALK_REMOVE) { + /* only update prev if we don't remove current */ + prev = bkt; + depth++; + continue; + } + t->removed++; + t->entries--; + dkhash_destroy_bucket(bkt); + if (depth) { + prev->next = next; + } + else { + t->buckets[i] = next; + } + } + } +} diff --git a/lib/dkhash.h b/lib/dkhash.h new file mode 100644 index 0000000..b2e1ff3 --- /dev/null +++ b/lib/dkhash.h @@ -0,0 +1,134 @@ +#ifndef LIBNAGIOS_DKHASH_H_INCLUDED +#define LIBNAGIOS_DKHASH_H_INCLUDED +#include + +/** + * @file dkhash.h + * @brief Dual-key hash functions for Nagios + * + * Having a dual-key hash function is pretty unusual, but since so + * much data in Nagios pertains to services (which are uniquely + * identified based on both host_name and service_description), it + * makes sense here. + * + * @{ + */ + +/** return flags usable from the callback function of dkhash_walk_data() */ +#define DKHASH_WALK_REMOVE 1 /**< Remove the most recently visited object */ +#define DKHASH_WALK_STOP 2 /**< Cause walking to stop */ + +/** return values for dkhash_insert() */ +#define DKHASH_OK 0 /**< Success */ +#define DKHASH_EDUPE (-EPERM) /**< duplicate insert attempted */ +#define DKHASH_EPERM (-EPERM) /**< duplicate insert attempted */ +#define DKHASH_EINVAL (-EINVAL) /**< Invalid parameters passed */ +#define DKHASH_ENOMEM (-ENOMEM) /**< Memory allocation failed */ + +struct dkhash_table; +/** opaque type */ +typedef struct dkhash_table dkhash_table; + +/** + * Create a dual-keyed hash-table of the given size + * Note that it's generally useful to make the table 25-30% larger + * than the number of items you intend to store, and also note that + * the 'size' arguments gets rounded up to the nearest power of 2. + * @param size The desired size of the hash-table. + */ +extern dkhash_table *dkhash_create(unsigned int size); + +/** + * Destroy a dual-keyed hash table + * @param t The table to destroy + * @return 0 on success, -1 on errors + */ +extern int dkhash_destroy(dkhash_table *t); + +/** + * Fetch the data associated with a particular key + * @param t The table to get the data from + * @param k1 The first key + * @param k2 The second key + * @return The data on success, NULL on errors or if data isn't found + */ +extern void *dkhash_get(dkhash_table *t, const char *k1, const char *k2); + +/** + * Insert a new entry into the hash table + * @param t The hash table + * @param k1 The first key + * @param k2 The second key (may be null) + * @param data The data to insert + * @return 0 on success, < 0 on errors + */ +extern int dkhash_insert(dkhash_table *t, const char *k1, const char *k2, void *data); + +/** + * Remove data from the hash table + * Note that this does not free() the pointer to the data stored in the + * table. It just destroys containers for that data in the hash table. + * @param t The hash table + * @param k1 The first key + * @param k2 The second key + * @return The removed data on success, or NULL on errors + */ +extern void *dkhash_remove(dkhash_table *t, const char *k1, const char *k2); + +/** + * Call a function once for each item in the hash-table + * The callback function can return DKHASH_WALK_{REMOVE,STOP} or any + * OR'ed combination thereof to control the walking procedure, and + * should return 0 on the normal case. + * @param t The hash table + * @param walker The callback function to send the data to + */ +extern void dkhash_walk_data(dkhash_table *t, int (*walker)(void *data)); + + +/** + * Get number of collisions in hash table + * Many collisions is a sign of a too small hash table or + * poor hash-function. + * @param t The hash table to report on + * @return The total number of collisions (not duplicates) from inserts + */ +extern unsigned int dkhash_collisions(dkhash_table *t); + +/** + * Get number of items in the hash table + * @param t The hash table + * @return Number of items currently in the hash-table + */ +extern unsigned int dkhash_num_entries(dkhash_table *t); + +/** + * Get max number of items stored in the hash table + * @param t The hash table + * @return Max number of items stored in hash-table + */ +extern unsigned int dkhash_num_entries_max(dkhash_table *t); + +/** + * Get number of entries added to hash table + * Note that some of them may have been removed. + * @param t The hash table + * @return The number of items added to the table + */ +extern unsigned int dkhash_num_entries_added(dkhash_table *t); + +/** + * Get number of removed items from hash table + * @param t The hash table + * @return Number of items removed from hash table + */ +extern unsigned int dkhash_num_entries_removed(dkhash_table *t); + +/** + * Get actual table size (in number of buckets) + * @param t The hash table + * @return Number of bucket-slots in hash table + */ +extern unsigned int dkhash_table_size(dkhash_table *t); +/** @} */ +#endif /* LIBNAGIOS_DKHASH_H_INCLUDED */ diff --git a/lib/fanout.c b/lib/fanout.c new file mode 100644 index 0000000..9b581cd --- /dev/null +++ b/lib/fanout.c @@ -0,0 +1,115 @@ +#include +#include "fanout.h" + +struct fanout_entry { + unsigned long key; + void *data; + struct fanout_entry *next; +}; + +struct fanout_table { + unsigned long alloc; + struct fanout_entry **entries; +}; + +fanout_table *fanout_create(unsigned long size) +{ + fanout_table *t = calloc(1, sizeof(*t)); + if (!t) + return NULL; + t->entries = calloc(size, sizeof(struct fanout_entry *)); + if (!t->entries) { + free(t); + return NULL; + } + t->alloc = size; + return t; +} + +void fanout_destroy(fanout_table *t, void (*destructor)(void *)) +{ + unsigned long i; + struct fanout_entry **entries, *next; + + if (!t || !t->entries || !t->alloc) + return; + + /* protect against destructors calling fanout_remove() */ + entries = t->entries; + t->entries = NULL; + + for (i = 0; i < t->alloc; i++) { + struct fanout_entry *entry; + + for (entry = entries[i]; entry; entry = next) { + void *data = entry->data; + next = entry->next; + free(entry); + if (destructor) { + destructor(data); + } + } + } + free(entries); + free(t); +} + +int fanout_add(struct fanout_table *t, unsigned long key, void *data) +{ + struct fanout_entry *entry; + if (!t || !t->entries || !t->alloc || !data) + return -1; + + entry = calloc(1, sizeof(*entry)); + if (!entry) + return -1; + + entry->key = key; + entry->data = data; + entry->next = t->entries[key % t->alloc]; + t->entries[key % t->alloc] = entry; + + return 0; +} + +void *fanout_get(fanout_table *t, unsigned long key) +{ + struct fanout_entry *entry; + unsigned long slot; + + if (!t || !t->entries || !t->alloc) + return NULL; + + slot = key % t->alloc; + for (entry = t->entries[slot]; entry; entry = entry->next) { + if (entry->key == key) + return entry->data; + } + + return NULL; +} + +void *fanout_remove(fanout_table *t, unsigned long key) +{ + struct fanout_entry *entry, *next, *prev = NULL; + unsigned long slot; + + if (!t || !t->entries || !t->alloc) + return NULL; + + slot = key % t->alloc; + for (entry = t->entries[slot]; entry; prev = entry, entry = next) { + next = entry->next; + if (entry->key == key) { + void *data = entry->data; + if (prev) { + prev->next = entry->next; + } else { + t->entries[slot] = entry->next; + } + free(entry); + return data; + } + } + return NULL; +} diff --git a/lib/fanout.h b/lib/fanout.h new file mode 100644 index 0000000..d1164dd --- /dev/null +++ b/lib/fanout.h @@ -0,0 +1,73 @@ +#ifndef LIBNAGIOS_FANOUT_H_INCLUDED +#define LIBNAGIOS_FANOUT_H_INCLUDED +#include "lnag-utils.h" + +/** + * @file fanout.h + * @brief Simple fanout table implementation + * + * Fanouts are useful to hold short-lived integer-indexed data where + * the keyspan between smallest and largest key can be too large and + * change too often for it to be practical to maintain a growing array. + * If you think of it as a hash-table optimized for unsigned longs you've + * got the right idea. + * + * @{ + */ + +NAGIOS_BEGIN_DECL + +/** Primary (opaque) type for this api */ +typedef struct fanout_table fanout_table; + +/** + * Create a fanout table + * @param[in] size The size of the table. Preferably a power of 2 + * @return Pointer to a newly created table + */ +extern fanout_table *fanout_create(unsigned long size); + +/** + * Destroy a fanout table, with optional destructor. + * This function will iterate over all the entries in the fanout + * table and remove them, one by one. If 'destructor' is not NULL, + * it will be called on each and every object in the table. Note that + * 'free' is a valid destructor. + * + * @param[in] t The fanout table to destroy + * @param[in] destructor Function to call on data pointers in table + */ +extern void fanout_destroy(fanout_table *t, void (*destructor)(void *)); + +/** + * Return a pointer from the fanout table t + * + * @param[in] t table to fetch from + * @param[in] key key to fetch + * @return NULL on errors; Pointer to data on success + */ +extern void *fanout_get(fanout_table *t, unsigned long key); + +/** + * Add an entry to the fanout table. + * Note that we don't check if the key is unique. If it isn't, + * fanout_remove() will remove the latest added first. + * + * @param[in] t fanout table to add to + * @param[in] key Key for this entry + * @param[in] data Data to add. Must not be NULL + * @return 0 on success, -1 on errors + */ +extern int fanout_add(fanout_table *t, unsigned long key, void *data); + +/** + * Remove an entry from the fanout table and return its data. + * + * @param[in] t fanout table to look in + * @param[in] key The key whose data we should locate + * @return Pointer to the data stored on success; NULL on errors + */ +extern void *fanout_remove(fanout_table *t, unsigned long key); +NAGIOS_END_DECL +/** @} */ +#endif diff --git a/lib/iobroker.c b/lib/iobroker.c new file mode 100644 index 0000000..633f307 --- /dev/null +++ b/lib/iobroker.c @@ -0,0 +1,440 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "iobroker.h" + +#ifdef IOBROKER_USES_EPOLL +#include +/* these were added later */ +#ifndef EPOLLRDHUP +# define EPOLLRDHUP 0 +#endif +#ifndef EPOLLONESHOT +# define EPOLLONESHOT 0 +#endif +#elif !defined(IOBROKER_USES_SELECT) +#include +#else +#include +#endif + +#if defined(IOBROKER_USES_EPOLL) && defined(IOBROKER_USES_POLL) +# error "iobroker can't use both epoll() and poll()" +#elif defined(IOBROKER_USES_EPOLL) && defined(IOBROKER_USES_SELECT) +# error "iobroker can't use both epoll() and select()" +#elif defined(IOBROKER_USEES_POLL) && defined(IOBROKER_USES_SELECT) +# error "iobroker can't use both poll() and select()" +#endif + +typedef struct { + int fd; /* the file descriptor */ + int events; /* events the caller is interested in */ + int (*handler)(int, int, void *); /* where we send data */ + void *arg; /* the argument we send to the input handler */ +} iobroker_fd; + + +struct iobroker_set { + iobroker_fd **iobroker_fds; + int max_fds; /* max number of sockets we can accept */ + int num_fds; /* number of sockets we're currently brokering for */ +#ifdef IOBROKER_USES_EPOLL + int epfd; + struct epoll_event *ep_events; +#elif !defined(IOBROKER_USES_SELECT) + struct pollfd *pfd; +#endif +}; + +static struct { + int code; + const char *string; +} iobroker_errors[] = { + { IOBROKER_SUCCESS, "Success" }, + { IOBROKER_ENOSET, "IOB set is NULL" }, + { IOBROKER_ENOINIT, "IOB set not initialized" }, +}; +static const char *iobroker_unknown_error = "unknown error"; + +#ifndef ARRAY_SIZE +# define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) +#endif +const char *iobroker_strerror(int error) +{ + if (error == IOBROKER_ELIB) + return strerror(errno); + error = (~error) + 1; + if (error < 0) { + return iobroker_unknown_error; + } + if (error >= (int)ARRAY_SIZE(iobroker_errors)) + return strerror(error); + + return iobroker_errors[error].string; +} + + +int iobroker_max_usable_fds(void) +{ +#if defined(RLIMIT_NOFILE) + struct rlimit rlim; + getrlimit(RLIMIT_NOFILE, &rlim); + return (unsigned long)rlim.rlim_cur; +#elif defined(_SC_OPEN_MAX) + return (unsigned long)sysconf(_SC_OPEN_MAX); +#elif defined(OPEN_MAX) + return (unsigned long)OPEN_MAX; +#elif defined(_POSIX_OPEN_MAX) + return (unsigned long)_POSIX_OPEN_MAX; +#else + /* + * No sysconf macros, no rlimit and no hopefully-sane + * defaults so we just guess. This might be completely + * wrong and could cause segfaults + */ + return 256UL; +#endif +} + + +int iobroker_get_max_fds(iobroker_set *iobs) +{ + if (!iobs) + return IOBROKER_ENOSET; + return iobs->max_fds; +} + +int iobroker_get_num_fds(iobroker_set *iobs) +{ + if (!iobs) + return IOBROKER_ENOSET; + return iobs->num_fds; +} + +struct iobroker_set *iobroker_create(void) +{ + iobroker_set *iobs = NULL; + + iobs = calloc(1, sizeof(*iobs)); + if (!iobs) { + goto error_out; + } + + iobs->max_fds = iobroker_max_usable_fds(); + iobs->iobroker_fds = calloc(iobs->max_fds, sizeof(iobroker_fd *)); + if (!iobs->iobroker_fds) { + goto error_out; + } + +#ifdef IOBROKER_USES_EPOLL + { + int flags; + + iobs->ep_events = calloc(iobs->max_fds, sizeof(struct epoll_event)); + if (!iobs->ep_events) { + goto error_out; + } + + iobs->epfd = epoll_create(iobs->max_fds); + if (iobs->epfd < 0) { + goto error_out; + } + + flags = fcntl(iobs->epfd, F_GETFD); + flags |= FD_CLOEXEC; + fcntl(iobs->epfd, F_SETFD, flags); + } +#elif !defined(IOBROKER_USES_SELECT) + iobs->pfd = calloc(iobs->max_fds, sizeof(struct pollfd)); + if (!iobs->pfd) + goto error_out; +#endif + + return iobs; + +error_out: + if (iobs) { +#ifdef IOBROKER_USES_EPOLL + close(iobs->epfd); + if (iobs->ep_events) + free(iobs->ep_events); +#endif + if (iobs->iobroker_fds) + free(iobs->iobroker_fds); + free(iobs); + } + return NULL; +} + +static int reg_one(iobroker_set *iobs, int fd, int events, void *arg, int (*handler)(int, int, void *)) +{ + iobroker_fd *s; + + if (!iobs) { + return IOBROKER_ENOSET; + } + if (fd < 0 || fd >= iobs->max_fds) + return IOBROKER_EINVAL; + + /* + * Re-registering a socket is an error, as multiple input + * handlers for a single socket makes no sense at all + */ + if (iobs->iobroker_fds[fd] != NULL) + return IOBROKER_EALREADY; + +#ifdef IOBROKER_USES_EPOLL + { + struct epoll_event ev; + ev.events = events; + ev.data.ptr = arg; + ev.data.fd = fd; + if (epoll_ctl(iobs->epfd, EPOLL_CTL_ADD, fd, &ev) < 0) { + return IOBROKER_ELIB; + } + } +#endif + + s = calloc(1, sizeof(iobroker_fd)); + s->handler = handler; + s->fd = fd; + s->arg = arg; + s->events = events; + iobs->iobroker_fds[fd] = s; + iobs->num_fds++; + + return 0; +} + +int iobroker_register(iobroker_set *iobs, int fd, void *arg, int (*handler)(int, int, void *)) +{ +#ifdef IOBROKER_USES_EPOLL + return reg_one(iobs, fd, EPOLLIN | EPOLLRDHUP, arg, handler); +#else + return reg_one(iobs, fd, POLLIN, arg, handler); +#endif +} + +int iobroker_register_out(iobroker_set *iobs, int fd, void *arg, int (*handler)(int, int, void *)) +{ +#ifdef IOBROKER_USES_EPOLL + return reg_one(iobs, fd, EPOLLOUT, arg, handler); +#else + return reg_one(iobs, fd, POLLOUT, arg, handler); +#endif +} + +int iobroker_is_registered(iobroker_set *iobs, int fd) +{ + if (!iobs || fd < 0 || fd > iobs->max_fds || !iobs->iobroker_fds[fd]) + return 0; + + return iobs->iobroker_fds[fd]->fd == fd; +} + +int iobroker_unregister(iobroker_set *iobs, int fd) +{ + if (!iobs) + return IOBROKER_ENOSET; + + if (!iobs->iobroker_fds) + return IOBROKER_ENOINIT; + + if (fd < 0 || fd >= iobs->max_fds || !iobs->iobroker_fds[fd]) + return IOBROKER_EINVAL; + + free(iobs->iobroker_fds[fd]); + iobs->iobroker_fds[fd] = NULL; + if (iobs->num_fds > 0) + iobs->num_fds--; + +#ifdef IOBROKER_USES_EPOLL + { + /* + * This needs to be set for linux <= 2.6.9 even though + * it's ignored even then. + */ + struct epoll_event ev; + + return epoll_ctl(iobs->epfd, EPOLL_CTL_DEL, fd, &ev); + } +#endif + return 0; +} + + +int iobroker_deregister(iobroker_set *iobs, int fd) +{ + return iobroker_unregister(iobs, fd); +} + + +int iobroker_close(iobroker_set *iobs, int fd) +{ + int result; + + result = iobroker_unregister(iobs, fd); + (void)close(fd); + return result; +} + + +void iobroker_destroy(iobroker_set *iobs, int flags) +{ + int i; + int (*dereg)(iobroker_set *, int) = iobroker_unregister; + + if (!iobs) + return; + + if (flags & IOBROKER_CLOSE_SOCKETS) { + dereg = iobroker_close; + } + +#ifdef IOBROKER_USES_EPOLL + if (iobs->epfd >= 0) + close(iobs->epfd); +#elif !defined(IOBROKER_USES_SELECT) + if (iobs->pfd) + free(iobs->pfd); +#endif + + if (!iobs->iobroker_fds) + return; + + for (i = 0; i < iobs->max_fds; i++) { + if (iobs->iobroker_fds[i] == NULL) + continue; + dereg(iobs, i); + } + free(iobs->iobroker_fds); + iobs->iobroker_fds = NULL; +#ifdef IOBROKER_USES_EPOLL + free(iobs->ep_events); + close(iobs->epfd); +#endif + free(iobs); +} + + +int iobroker_poll(iobroker_set *iobs, int timeout) +{ + int i, nfds, ret = 0; + + if (!iobs) + return IOBROKER_ENOSET; + + if (!iobs->num_fds) + return IOBROKER_ENOINIT; + +#if defined(IOBROKER_USES_EPOLL) + nfds = epoll_wait(iobs->epfd, iobs->ep_events, iobs->num_fds, timeout); + if (nfds < 0) { + return IOBROKER_ELIB; + } + + for (i = 0; i < nfds; i++) { + int fd; + iobroker_fd *s = NULL; + + fd = iobs->ep_events[i].data.fd; + if (fd < 0 || fd > iobs->max_fds) { + continue; + } + s = iobs->iobroker_fds[fd]; + + if (s) { + s->handler(fd, iobs->ep_events[i].events, s->arg); + ret++; + } + } +#elif defined(IOBROKER_USES_SELECT) + /* + * select() is the (last) fallback, as it's the least + * efficient by quite a huge margin, so it has to be + * specified specially (in CFLAGS) and should only be + * used if epoll() or poll() doesn't work properly. + */ + { + fd_set read_fds; + int num_fds = 0; + struct timeval tv; + + FD_ZERO(&read_fds); + for (i = 0; i < iobs->max_fds; i++) { + if (!iobs->iobroker_fds[i]) + continue; + num_fds++; + FD_SET(iobs->iobroker_fds[i]->fd, &read_fds); + if (num_fds == iobs->num_fds) + break; + } + if (timeout >= 0) { + tv.tv_sec = timeout / 1000; + tv.tv_usec = (timeout % 1000) * 1000; + nfds = select(iobs->max_fds, &read_fds, NULL, NULL, &tv); + } else { /* timeout of -1 means poll indefinitely */ + nfds = select(iobs->max_fds, &read_fds, NULL, NULL, NULL); + } + if (nfds < 0) { + return IOBROKER_ELIB; + } + num_fds = 0; + for (i = 0; i < iobs->max_fds; i++) { + if (!iobs->iobroker_fds[i]) + continue; + if (FD_ISSET(iobs->iobroker_fds[i]->fd, &read_fds)) { + iobroker_fd *s = iobs->iobroker_fds[i]; + if (!s) { + /* this should be logged somehow */ + continue; + } + s->handler(s->fd, POLLIN, s->arg); + ret++; + } + } + } +#else + /* + * poll(2) is an acceptable fallback if level-triggered epoll() + * isn't available. + */ + { + int p = 0; + + for (i = 0; i < iobs->max_fds; i++) { + if (!iobs->iobroker_fds[i]) + continue; + iobs->pfd[p].fd = iobs->iobroker_fds[i]->fd; + iobs->pfd[p].events = POLLIN; + p++; + } + nfds = poll(iobs->pfd, p, timeout); + if (nfds < 0) { + return IOBROKER_ELIB; + } + for (i = 0; i < p; i++) { + iobroker_fd *s; + if (iobs->pfd[i].revents == 0) { + continue; + } + + s = iobs->iobroker_fds[iobs->pfd[i].fd]; + if (!s) { + /* this should be logged somehow */ + continue; + } + s->handler(s->fd, (int)iobs->pfd[i].revents, s->arg); + ret++; + } + } +#endif + + return ret; +} diff --git a/lib/iobroker.h.in b/lib/iobroker.h.in new file mode 100644 index 0000000..65daa51 --- /dev/null +++ b/lib/iobroker.h.in @@ -0,0 +1,174 @@ +#ifndef LIBNAGIOS_iobroker_h__ +#define LIBNAGIOS_iobroker_h__ + +/** + * @file iobroker.h + * @brief I/O broker library function declarations + * + * The I/O broker library handles multiplexing between hundreds or + * thousands of sockets with a few simple calls. It's designed to + * be as lightweight as possible so as to not cause memory bloat, + * and is therefore highly suitable for use by processes that are + * fork()-intensive. + * + * @{ + */ + +#undef IOBROKER_USES_EPOLL +#undef IOBROKER_USES_POLL +#undef IOBROKER_USES_SELECT + +#if (_POSIX_C_SOURCE - 0) >= 200112L +#include +# define IOBROKER_POLLIN POLLIN +# define IOBROKER_POLLPRI POLLPRI +# define IOBROKER_POLLOUT POLLOUT + +# define IOBROKER_POLLERR POLLERR +# define IOBROKER_POLLHUP POLLHUP +# define IOBROKER_POLLNVAL POLLNVAL +#else +# define IOBROKER_POLLIN 0x001 /* there is data to read */ +# define IOBROKER_POLLPRI 0x002 /* there is urgent data to read */ +# define IOBROKER_POLLOUT 0x004 /* writing now will not block */ + +# define IOBROKER_POLLERR 0x008 /* error condition */ +# define IOBROKER_POLLHUP 0x010 /* hung up */ +# define IOBROKER_POLLNVAL 0x020 /* invalid polling request */ +#endif + +/** return codes */ +#define IOBROKER_SUCCESS 0 +#define IOBROKER_ENOSET (-1) +#define IOBROKER_ENOINIT (-2) +#define IOBROKER_ELIB (-3) +#define IOBROKER_EALREADY (-EALREADY) +#define IOBROKER_EINVAL (-EINVAL) + + +/** Flags for iobroker_destroy() */ +#define IOBROKER_CLOSE_SOCKETS 1 + +/* Opaque type. Callers needn't worry about this */ +struct iobroker_set; +typedef struct iobroker_set iobroker_set; + +/** + * Get a string describing the error in the last iobroker call. + * The returned string must not be free()'d. + * @param error The error code + * @return A string describing the meaning of the error code + */ +extern const char *iobroker_strerror(int error); + +/** + * Create a new socket set + * @return An iobroker_set on success. NULL on errors. + */ +extern iobroker_set *iobroker_create(void); + +/** + * Published utility function used to determine the max number of + * file descriptors this process can keep open at any one time. + * @return Max number of filedescriptors we can keep open + */ +extern int iobroker_max_usable_fds(void); + +/** + * Register a socket for input polling with the broker. + * + * @param iobs The socket set to add the socket to. + * @param sd The socket descriptor to add + * @param arg Argument passed to input handler on available input + * @param handler The callback function to call when input is available + * + * @return 0 on succes. < 0 on errors. + */ +extern int iobroker_register(iobroker_set *iobs, int sd, void *arg, int (*handler)(int, int, void *)); + + +/** + * Register a socket for output polling with the broker + * @note There's no guarantee that *ALL* data is writable just + * because the socket won't block you completely. + * + * @param iobs The socket set to add the socket to. + * @param sd The socket descriptor to add + * @param arg Argument passed to output handler on ready-to-write + * @param handler The function to call when output won't block + * + * @return 0 on success. < 0 on errors + */ +extern int iobroker_register_out(iobroker_set *iobs, int sd, void *arg, int (*handler)(int, int, void *)); + +/** + * Check if a particular filedescriptor is registered with the iobroker set + * @param[in] iobs The iobroker set the filedescriptor should be member of + * @param[in] fd The filedescriptor to check for + * @return 1 if the filedescriptor is registered and 0 otherwise + */ +extern int iobroker_is_registered(iobroker_set *iobs, int fd); + +/** + * Getter function for number of file descriptors registered in + * the set specified. + * @param iobs The io broker set to query + * @return Number of file descriptors registered in the set + */ +extern int iobroker_get_num_fds(iobroker_set *iobs); + +/** + * Getter function for the maximum amount of file descriptors this + * set can handle. + * @param iobs The io broker set to query + * @return Max file descriptor capacity for the set + */ +extern int iobroker_get_max_fds(iobroker_set *iobs); + +/** + * Unregister a socket for input polling with the broker. + * + * @param iobs The socket set to remove the socket from + * @param sd The socket descriptor to remove + * @return 0 on succes. < 0 on errors. + */ +extern int iobroker_unregister(iobroker_set *iobs, int sd); + +/** + * Deregister a socket for input polling with the broker + * (this is identical to iobroker_unregister()) + * @param iobs The socket set to remove the socket from + * @param sd The socket descriptor to remove + * @return 0 on success. < 0 on errors. + */ +extern int iobroker_deregister(iobroker_set *iobs, int sd); + +/** + * Unregister and close(2) a socket registered for input with the + * broker. This is a convenience function which exists only to avoid + * doing multiple calls when read() returns 0, as closed sockets must + * always be removed from the socket set to avoid consuming tons of + * cpu power from iterating "too fast" over the file descriptors. + * + * @param iobs The socket set to remove the socket from + * @param sd The socket descriptor to remove and close + * @return 0 on success. < 0 on errors + */ +extern int iobroker_close(iobroker_set *iobs, int sd); + +/** + * Destroy a socket set as created by iobroker_create + * @param iobs The socket set to destroy + * @param flags If set, close(2) all registered sockets + */ +extern void iobroker_destroy(iobroker_set *iobs, int flags); + +/** + * Wait for input on any of the registered sockets. + * @param iobs The socket set to wait for. + * @param timeout Timeout in milliseconds. -1 is "wait indefinitely" + * @return -1 on errors, or number of filedescriptors with input + */ +extern int iobroker_poll(iobroker_set *iobs, int timeout); +#endif /* INCLUDE_iobroker_h__ */ +/** @} */ diff --git a/lib/iocache.c b/lib/iocache.c new file mode 100644 index 0000000..3d39be0 --- /dev/null +++ b/lib/iocache.c @@ -0,0 +1,254 @@ +#include "iocache.h" +#include +#include +#include +#include + +struct iocache { + char *ioc_buf; /* the data */ + unsigned long ioc_offset; /* where we're reading in the buffer */ + unsigned long ioc_buflen; /* the amount of data read into the buffer */ + unsigned long ioc_bufsize; /* size of the buffer */ +}; + +void iocache_destroy(iocache *ioc) +{ + if (!ioc) + return; + + if (ioc->ioc_buf) + free(ioc->ioc_buf); + + free(ioc); +} + +/** + * Attempts to move data from the end to the beginning + * of the ioc_buf, expelling old data to make more room + * for new reads. + */ +static inline void iocache_move_data(iocache *ioc) +{ + unsigned long available; + + if (!ioc->ioc_offset) + return; /* nothing to do */ + + /* if we're fully read, we only have to reset the counters */ + if (ioc->ioc_buflen <= ioc->ioc_offset) { + iocache_reset(ioc); + return; + } + available = ioc->ioc_buflen - ioc->ioc_offset; + memmove(ioc->ioc_buf, ioc->ioc_buf + ioc->ioc_offset, available); + ioc->ioc_offset = 0; + ioc->ioc_buflen = available; +} + +void iocache_reset(iocache *ioc) +{ + if (ioc) + ioc->ioc_offset = ioc->ioc_buflen = 0; +} + +int iocache_resize(iocache *ioc, unsigned long new_size) +{ + char *buf; + + if (!ioc) + return -1; + + iocache_move_data(ioc); + + buf = realloc(ioc->ioc_buf, new_size); + if (!buf) + return -1; + ioc->ioc_buf = buf; + ioc->ioc_bufsize = new_size; + return 0; +} + +int iocache_grow(iocache *ioc, unsigned long increment) +{ + return iocache_resize(ioc, iocache_size(ioc) + increment); +} + +unsigned long iocache_size(iocache *ioc) +{ + return ioc ? ioc->ioc_bufsize : 0; +} + +unsigned long iocache_capacity(iocache *ioc) +{ + if (!ioc || !ioc->ioc_buf || !ioc->ioc_bufsize) + return 0; + + iocache_move_data(ioc); + + return ioc->ioc_bufsize - ioc->ioc_buflen; +} + +unsigned long iocache_available(iocache *ioc) +{ + if (!ioc || !ioc->ioc_buf || !ioc->ioc_bufsize || !ioc->ioc_buflen) + return 0; + + return ioc->ioc_buflen - ioc->ioc_offset; +} + +char *iocache_use_size(iocache *ioc, unsigned long size) +{ + char *ret; + + if (!ioc || !ioc->ioc_buf) + return NULL; + if (ioc->ioc_bufsize < size || iocache_available(ioc) < size) + return NULL; + + ret = ioc->ioc_buf + ioc->ioc_offset; + ioc->ioc_offset += size; + + return ret; +} + +int iocache_unuse_size(iocache *ioc, unsigned long size) +{ + if (!ioc || !ioc->ioc_buf) + return -1; + if (size > ioc->ioc_offset) + return -1; + + ioc->ioc_offset -= size; + + return 0; +} + + +char *iocache_use_delim(iocache *ioc, const char *delim, size_t delim_len, unsigned long *size) +{ + char *ptr = NULL; + char *buf; + unsigned long remains; + + if (!ioc || !ioc->ioc_buf || !ioc->ioc_bufsize || !ioc->ioc_buflen) + return NULL; + + *size = 0; + if (ioc->ioc_offset >= ioc->ioc_buflen) { + iocache_move_data(ioc); + return NULL; + } + + buf = &ioc->ioc_buf[ioc->ioc_offset]; + remains = iocache_available(ioc); + while (remains >= delim_len) { + unsigned long jump; + ptr = memchr(buf, *delim, remains - (delim_len - 1)); + if (!ptr) { + return NULL; + } + if (delim_len == 1 || !memcmp(ptr, delim, delim_len)) { + unsigned long ioc_start; + + ioc_start = (unsigned long)ioc->ioc_buf + ioc->ioc_offset; + *size = (unsigned long)ptr - ioc_start; + + /* make sure we use up all of the delimiter as well */ + return iocache_use_size(ioc, delim_len + *size); + } + jump = 1 + (unsigned long)ptr - (unsigned long)buf; + remains -= jump; + buf += jump; + } + return NULL; +} + +iocache *iocache_create(unsigned long size) +{ + iocache *ioc; + + ioc = calloc(1, sizeof(*ioc)); + if (ioc && size) { + ioc->ioc_buf = calloc(1, size); + if (!ioc->ioc_buf) { + free(ioc); + return NULL; + } + ioc->ioc_bufsize = size; + } + + return ioc; +} + +int iocache_read(iocache *ioc, int fd) +{ + int to_read, bytes_read; + + if (!ioc || !ioc->ioc_buf || fd < 0) + return -1; + + /* we make sure we've got as much room as possible */ + iocache_move_data(ioc); + + /* calculate the size we should read */ + to_read = ioc->ioc_bufsize - ioc->ioc_buflen; + + bytes_read = read(fd, ioc->ioc_buf + ioc->ioc_buflen, to_read); + if (bytes_read > 0) { + ioc->ioc_buflen += bytes_read; + } + + return bytes_read; +} + + +int iocache_add(iocache *ioc, char *buf, unsigned int len) +{ + if (!ioc || iocache_capacity(ioc) < len) + return -1; + + memcpy(ioc->ioc_buf + ioc->ioc_offset, buf, len); + ioc->ioc_buflen += len; + return ioc->ioc_buflen - ioc->ioc_offset; +} + +/* + * Three cases to handle: + * - buf has data, iocache doesn't. + * - iocache has data, buf doesn't. + * - both buf and iocache has data. + */ +int iocache_sendto(iocache *ioc, int fd, char *buf, unsigned int len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen) +{ + int sent; + + errno = 0; + if (!ioc) + return -1; + + if (!ioc->ioc_buflen && !len) + return 0; + + if (ioc->ioc_buf && iocache_available(ioc)) { + if (buf && len) { + /* copy buf and len to iocache buffer to use just one write */ + if (iocache_capacity(ioc) < len) { + if (iocache_grow(ioc, iocache_size(ioc)) < 0) + return -1; + } + if (iocache_add(ioc, buf, len) < 0) + return -1; + } + buf = ioc->ioc_buf; + len = iocache_available(ioc); + } + + sent = sendto(fd, buf, len, flags, dest_addr, addrlen); + if (sent < 1) + return -errno; + + if (iocache_available(ioc)) + iocache_use_size(ioc, sent); + + return sent; +} diff --git a/lib/iocache.h b/lib/iocache.h new file mode 100644 index 0000000..821acca --- /dev/null +++ b/lib/iocache.h @@ -0,0 +1,181 @@ +#ifndef LIBNAGIOS_IOCACHE_H_INCLUDED +#define LIBNAGIOS_IOCACHE_H_INCLUDED +#include +#include +#include + +/** + * @file iocache.h + * @brief I/O cache function declarations + * + * The I/O cache library is useful for reading large chunks of data + * from sockets and utilizing parts of that data based on either + * size or a magic delimiter. + * + * @{ + */ + +/** opaque type for iocache operations */ +struct iocache; +typedef struct iocache iocache; + +/** + * Destroys an iocache object, freeing all memory allocated to it. + * @param ioc The iocache object to destroy + */ +extern void iocache_destroy(iocache *ioc); + +/** + * Resets an iocache struct, discarding all data in it without free()'ing + * any memory. + * + * @param[in] ioc The iocache struct to reset + */ +extern void iocache_reset(iocache *ioc); + +/** + * Resizes the buffer in an io cache + * @param ioc The io cache to resize + * @param new_size The new size of the io cache + * @return 0 on success, -1 on errors + */ +extern int iocache_resize(iocache *ioc, unsigned long new_size); + +/** + * Grows an iocache object + * This uses iocache_resize() internally + * @param[in] ioc The iocache to grow + * @param[in] increment How much to increase it + * @return 0 on success, -1 on errors + */ +extern int iocache_grow(iocache *ioc, unsigned long increment); + +/** + * Returns the total size of the io cache + * @param[in] ioc The iocache to inspect + * @return The size of the io cache. If ioc is null, 0 is returned + */ +extern unsigned long iocache_size(iocache *ioc); + +/** + * Returns remaining read capacity of the io cache + * @param ioc The io cache to operate on + * @return The number of bytes available to read + */ +extern unsigned long iocache_capacity(iocache *ioc); + +/** + * Return the amount of unread but stored data in the io cache + * @param ioc The io cache to operate on + * @return Number of bytes available to read + */ +extern unsigned long iocache_available(iocache *ioc); + +/** + * Use a chunk of data from iocache based on size. The caller + * must take care not to write beyond the end of the requested + * buffer, or Bad Things(tm) will happen. + * + * @param ioc The io cache we should use data from + * @param size The size of the data we want returned + * @return NULL on errors (insufficient data, fe). pointer on success + */ +extern char *iocache_use_size(iocache *ioc, unsigned long size); + +/** + * Use a chunk of data from iocache based on delimiter. The + * caller must take care not to write beyond the end of the + * requested buffer, if any is returned, or Bad Things(tm) will + * happen. + * + * @param ioc The io cache to use data from + * @param delim The delimiter + * @param delim_len Length of the delimiter + * @param size Length of the returned buffer + * @return NULL on errors (delimiter not found, insufficient data). pointer on success + */ +extern char *iocache_use_delim(iocache *ioc, const char *delim, size_t delim_len, unsigned long *size); + +/** + * Forget that a specified number of bytes have been used. + * @param ioc The io cache that you want to un-use data in + * @param size The number of bytes you want to forget you've seen + * @return -1 if there was an error, 0 otherwise. + */ +extern int iocache_unuse_size(iocache *ioc, unsigned long size); + +/** + * Creates the iocache object, initializing it with the given size + * @param size Initial size of the iocache buffer + * @return Pointer to a valid iocache object + */ +extern iocache *iocache_create(unsigned long size); + +/** + * Read data into the iocache buffer + * @param ioc The io cache we should read into + * @param fd The filedescriptor we should read from + * @return The number of bytes read on success. < 0 on errors + */ +extern int iocache_read(iocache *ioc, int fd); + +/** + * Add data to the iocache buffer + * The data is copied, so it can safely be taken from the stack in a + * function that returns before the data is used. + * If the io cache is too small to hold the data, -1 will be returned. + * + * @param[in] ioc The io cache to add to + * @param[in] buf Pointer to the data we should add + * @param[in] len Length (in bytes) of data pointed to by buf + * @return iocache_available(ioc) on success, -1 on errors + */ +extern int iocache_add(iocache *ioc, char *buf, unsigned int len); + +/** + * Like sendto(), but sends all cached data prior to the requested + * + * @param[in] ioc The iocache to send, or cache data in + * @param[in] fd The file descriptor to send to + * @param[in] buf Pointer to the data to send + * @param[in] len Length (in bytes) of data to send + * @param[in] flags Flags passed to sendto(2) + * @param[in] dest_addr Destination address + * @param[in] addrlen size (in bytes) of dest_addr + * @return bytes sent on success, -ERRNO on errors + */ +extern int iocache_sendto(iocache *ioc, int fd, char *buf, unsigned int len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen); + +/** + * Like send(2), but sends all cached data prior to the requested + * This function uses iocache_sendto() internally, but can only be + * used on connected sockets or open()'ed files. + * + * @param[in] ioc The iocache to send, or cache data in + * @param[in] fd The file descriptor to send to + * @param[in] buf Pointer to the data to send + * @param[in] len Length (in bytes) of data to send + * @param[in] flags Flags passed to sendto(2) + * @return bytes sent on success, -ERRNO on errors + */ +static inline int iocache_send(iocache *ioc, int fd, char *buf, unsigned int len, int flags) +{ + return iocache_sendto(ioc, fd, buf, len, flags, NULL, 0); +} + +/** + * Like write(2), but sends all cached data prior to the requested + * This function uses iocache_send() internally. + * + * @param[in] ioc The iocache to send, or cache data in + * @param[in] fd The file descriptor to send to + * @param[in] buf Pointer to the data to send + * @param[in] len Length (in bytes) of data to send + * @return bytes sent on success, -ERRNO on errors + */ +static inline int iocache_write(iocache *ioc, int fd, char *buf, unsigned int len) +{ + return iocache_send(ioc, fd, buf, len, 0); +} +#endif /* INCLUDE_iocache_h__ */ +/** @} */ diff --git a/lib/kvvec.c b/lib/kvvec.c new file mode 100644 index 0000000..2208b81 --- /dev/null +++ b/lib/kvvec.c @@ -0,0 +1,344 @@ +/* + * key+value vector library + * + * Small and simple, but pretty helpful when parsing configurations + * from random formats into something a program can easily make sense + * of. + * + * The main type (struct kvvec *) should possibly be opaque since + * all callers should use the kvvec_foreach() variable to trudge + * around in the key/value vector. + */ +#include +#include +#include "kvvec.h" + +struct kvvec *kvvec_init(struct kvvec *kvv, int hint) +{ + if (!kvv) + return NULL; + + kvv->kv_pairs = 0; + if (kvv->kv_alloc < hint && kvvec_resize(kvv, hint) < 0) + return NULL; + + return kvv; +} + +struct kvvec *kvvec_create(int hint) +{ + struct kvvec *kvv = calloc(1, sizeof(*kvv)); + if (kvv && !kvvec_init(kvv, hint)) { + free(kvv); + return NULL; + } + return kvv; +} + +int kvvec_resize(struct kvvec *kvv, int hint) +{ + struct key_value *kv; + + if (!kvv) + return -1; + + if (hint <= kvv->kv_alloc) + return 0; + + kv = realloc(kvv->kv, sizeof(struct key_value) * hint); + if (!kv) + return -1; + + memset(&kv[kvv->kv_alloc], 0, (hint - kvv->kv_alloc) * sizeof(*kv)); + kvv->kv = kv; + kvv->kv_alloc = hint; + return 0; +} + +int kvvec_grow(struct kvvec *kvv, int hint) +{ + if (!kvv) + return -1; + + /* grow reasonably when we don't have a hint */ + if (!hint) + hint = (kvv->kv_alloc / 3) + 15; + + return kvvec_resize(kvv, kvv->kv_alloc + hint); +} + +int kvvec_addkv_wlen(struct kvvec *kvv, const char *key, int keylen, const char *value, int valuelen) +{ + struct key_value *kv; + + if (!kvv || !key) + return -1; + + if (kvv->kv_pairs >= kvv->kv_alloc - 1) { + if (kvvec_grow(kvv, 0)) + return -1; + } + + kv = &kvv->kv[kvv->kv_pairs++]; + kv->key = (char *)key; + kv->key_len = keylen; + kv->value = (char *)value; + kv->value_len = valuelen; + + if (!keylen) { + kv->key_len = strlen(key); + } + if (value) { + if (!valuelen) { + kv->value_len = strlen(value); + } + } else { + kv->value_len = 0; + kv->value = '\0'; + } + kvv->kvv_sorted = 0; + + return 0; +} + +static int kv_compare(const void *a_, const void *b_) +{ + const struct key_value *a = (const struct key_value *)a_; + const struct key_value *b = (const struct key_value *)b_; + int ret = 0; + + ret = strcmp(a->key, b->key); + if (ret) + return ret; + + if (!a->value && !b->value) { + return 0; + } + if (a->value && !b->value) + return -1; + if (!a->value && b->value) + return 1; + + return strcmp(a->value, b->value); +} + +int kvvec_sort(struct kvvec *kvv) +{ + qsort(kvv->kv, kvv->kv_pairs, sizeof(struct key_value), kv_compare); + kvv->kvv_sorted = 1; + return 0; +} + +int kvvec_foreach(struct kvvec *kvv, void *arg, int (*callback)(struct key_value *,void *)) +{ + int i; + + if (!kvv) + return 0; + + for (i = 0; i < kvv->kv_pairs; i++) { + callback(&kvv->kv[i], arg); + } + return 0; +} + +void kvvec_free_kvpairs(struct kvvec *kvv, int flags) +{ + int i; + + if (flags == KVVEC_FREE_ALL) { + for (i = 0; i < kvv->kv_pairs; i++) { + free(kvv->kv[i].key); + free(kvv->kv[i].value); + } + } else if (flags == KVVEC_FREE_KEYS) { + for (i = 0; i < kvv->kv_pairs; i++) { + free(kvv->kv[i].key); + } + } else if (flags == KVVEC_FREE_VALUES) { + for (i = 0; i < kvv->kv_pairs; i++) { + free(kvv->kv[i].value); + } + } + + kvv->kv_pairs = 0; +} + + +int kvvec_destroy(struct kvvec *kvv, int flags) +{ + kvvec_free_kvpairs(kvv, flags); + free(kvv->kv); + free(kvv); + return 0; +} + +/* + * Caller can tell us to over-allocate the buffer if he/she wants + * to put extra stuff at the end of it. + */ +struct kvvec_buf *kvvec2buf(struct kvvec *kvv, char kv_sep, char pair_sep, int overalloc) +{ + struct kvvec_buf *kvvb; + int i; + unsigned long len = 0; + + if (!kvv) + return NULL; + + kvvb = malloc(sizeof(struct kvvec_buf)); + if (!kvvb) + return NULL; + + /* overalloc + (kv_sep_size * kv_pairs) + (pair_sep_size * kv_pairs) */ + kvvb->bufsize = overalloc + (kvv->kv_pairs * 2); + for (i = 0; i < kvv->kv_pairs; i++) { + struct key_value *kv = &kvv->kv[i]; + kvvb->bufsize += kv->key_len + kv->value_len; + } + + kvvb->buf = malloc(kvvb->bufsize); + if (!kvvb->buf) { + free(kvvb); + return NULL; + } + + for (i = 0; i < kvv->kv_pairs; i++) { + struct key_value *kv = &kvv->kv[i]; + memcpy(kvvb->buf + len, kv->key, kv->key_len); + len += kv->key_len; + kvvb->buf[len++] = kv_sep; + if (kv->value_len) { + memcpy(kvvb->buf + len, kv->value, kv->value_len); + len += kv->value_len; + } + kvvb->buf[len++] = pair_sep; + } + memset(kvvb->buf + len, 0, kvvb->bufsize - len); + kvvb->buflen = len; + return kvvb; +} + +unsigned int kvvec_capacity(struct kvvec *kvv) +{ + if (!kvv) + return 0; + + return kvv->kv_alloc - kvv->kv_pairs; +} + +/* + * Converts a buffer of random bytes to a key/value vector. + * This requires a fairly rigid format in the input data to be of + * much use, but it's nifty for ipc where only computers are + * involved, and it will parse the kvvec2buf() produce nicely. + */ +int buf2kvvec_prealloc(struct kvvec *kvv, char *str, + unsigned int len, const char kvsep, + const char pair_sep, int flags) +{ + unsigned int num_pairs = 0, i, offset = 0; + + if (!str || !len || !kvv) + return -1; + + /* first we count the number of key/value pairs */ + while (offset < len) { + const char *ptr; + + /* keys can't start with nul bytes */ + if (*(str + offset)) { + num_pairs++; + } + + ptr = memchr(str + offset, pair_sep, len - offset); + ptr++; + if (!ptr) + break; + offset += (unsigned long)ptr - ((unsigned long)str + offset); + } + + if (!num_pairs) { + return 0; + } + + /* make sure the key/value vector is large enough */ + if (!(flags & KVVEC_APPEND)) { + kvvec_init(kvv, num_pairs); + } else if (kvvec_capacity(kvv) < num_pairs && kvvec_resize(kvv, num_pairs) < 0) { + return -1; + } + + offset = 0; + for (i = 0; i < num_pairs; i++) { + struct key_value *kv; + char *key_end_ptr, *kv_end_ptr; + + /* keys can't begin with nul bytes */ + if (offset && str[offset] == '\0') { + return kvv->kv_pairs; + } + + key_end_ptr = memchr(str + offset, kvsep, len - offset); + if (!key_end_ptr) { + break; + } + kv_end_ptr = memchr(key_end_ptr + 1, pair_sep, len - ((unsigned long)key_end_ptr - (unsigned long)str)); + if (!kv_end_ptr) { + if (i != num_pairs - 1) + break; + /* last pair doesn't need a pair separator */ + kv_end_ptr = str + len; + } + + kv = &kvv->kv[kvv->kv_pairs++]; + kv->key_len = (unsigned long)key_end_ptr - ((unsigned long)str + offset); + if (flags & KVVEC_COPY) { + kv->key = malloc(kv->key_len + 1); + memcpy(kv->key, str + offset, kv->key_len); + } else { + kv->key = str + offset; + } + kv->key[kv->key_len] = 0; + + offset += kv->key_len + 1; + + if (str[offset] == pair_sep) { + kv->value_len = 0; + if (flags & KVVEC_COPY) { + kv->value = strdup(""); + } else { + kv->value = (char *)""; + } + } else { + kv->value_len = (unsigned long)kv_end_ptr - ((unsigned long)str + offset); + if (flags & KVVEC_COPY) { + kv->value = malloc(kv->value_len + 1); + memcpy(kv->value, str + offset, kv->value_len); + } else { + kv->value = str + offset; + } + kv->value[kv->value_len] = 0; + } + + offset += kv->value_len + 1; + } + + return i; +} + +struct kvvec *buf2kvvec(char *str, unsigned int len, const char kvsep, + const char pair_sep, int flags) +{ + struct kvvec *kvv; + + kvv = kvvec_create(len / 20); + if (!kvv) + return NULL; + + if (buf2kvvec_prealloc(kvv, str, len, kvsep, pair_sep, flags) >= 0) + return kvv; + + free(kvv); + return NULL; +} diff --git a/lib/kvvec.h b/lib/kvvec.h new file mode 100644 index 0000000..49be959 --- /dev/null +++ b/lib/kvvec.h @@ -0,0 +1,207 @@ +#ifndef LIBNAGIOS_KVVEC_H_INCLUDED +#define LIBNAGIOS_KVVEC_H_INCLUDED + +/** + * @file kvvec.h + * @brief Key/value vector library function and type declarations + * + * The kvvec library is nifty as either a configuration meta-format + * or for IPC purposes. Take a look at the buf2kvvec() and kvvec2buf() + * pair of functions for the latter. + * @{ + */ + +/** + * key/value pair + * One of the two major components of the kvvec api + */ +struct key_value { + char *key; /**< The key */ + char *value; /**< The value */ + int key_len; /**< Length of key */ + int value_len; /**< Length of value */ +}; + +/** + * key/value vector buffer. Actually just a buffer, but one that gets + * used as return value and internal tracker for kvvec2buf() + */ +struct kvvec_buf { + char *buf; /**< The buffer */ + unsigned long buflen; /**< Length of buffer */ + unsigned long bufsize; /**< Size of buffer (includes overalloc) */ +}; + +/** + * key/value vector struct + * This is the main component of the kvvec library + * @note This should be made opaque, with a kvvec_foreach() using a + * callback to iterate over key/value pairs. + */ +struct kvvec { + struct key_value *kv; /**< The key/value array */ + int kv_alloc; /**< Allocated size of key/value array */ + int kv_pairs; /**< Number of key/value pairs */ + int kvv_sorted; /**< Determines if this kvvec has been sorted */ +}; + +/** Portable initializer for stack-allocated key/value vectors */ +#define KVVEC_INITIALIZER { NULL, 0, 0, 0 } + +/** Parameters for kvvec_destroy() */ +#define KVVEC_FREE_KEYS 1 /**< Free keys when destroying a kv vector */ +#define KVVEC_FREE_VALUES 2 /**< Free values when destroying a kv vector */ +/** Free both keys and values when destroying a kv vector */ +#define KVVEC_FREE_ALL (KVVEC_FREE_KEYS | KVVEC_FREE_VALUES) + +#define KVVEC_ASSIGN 0 /**< Assign from buf in buf2kvvec_prealloc() */ +#define KVVEC_COPY 1 /**< Copy from buf in buf2kvvec_prealloc() */ +#define KVVEC_APPEND 2 /**< Don't reset kvvec in buf2kvvec_prealloc() */ + +/** + * Initialize a previously allocated key/value vector + * + * @param kvv The key/value vector to initialize + * @param hint Number of key/value pairs we expect to store + * @return Pointer to a struct kvvec, properly initialized + */ +extern struct kvvec *kvvec_init(struct kvvec *kvv, int hint); + +/** + * Create a key/value vector + * + * @param hint Number of key/value pairs we expect to store + * @return Pointer to a struct kvvec, properly initialized + */ +extern struct kvvec *kvvec_create(int hint); + +/** + * Resize a key/value vector + * Used by kvvec_grow(). If size is smaller than the current number of + * used key/value slots, -1 is returned. + * + * @param[in] kvv The key/value vector to resize + * @param[in] size The size to grow to + * @return 0 on success, < 0 on errors + */ +extern int kvvec_resize(struct kvvec *kvv, int size); + +/** + * Grow a key/value vector. + * Used internally as needed by the kvvec api. If 'hint' is zero, the + * key/value capacity is increased by a third of the current capacity + * plus a small constant number. This uses kvvec_resize() internally. + * + * @param kvv The key/value vector to grow + * @param hint The amount of key/value slots we should grow by + * @return 0 on success, < 0 on errors + */ +extern int kvvec_grow(struct kvvec *kvv, int hint); + +/** + * Return remaining storage capacity of key/value vector + * @param[in] kvv The key/value vector to check + * @return Number of key/value pairs that can be stored without growing + */ +extern unsigned int kvvec_capacity(struct kvvec *kvv); + +/** + * Sort a key/value vector alphabetically by key name + * @param kvv The key/value vector to sort + * @return 0 + */ +extern int kvvec_sort(struct kvvec *kvv); + +/** + * Add a key/value pair to an existing key/value vector, with + * lengths of strings already calculated + * @param kvv The key/value vector to add this key/value pair to + * @param key The key + * @param keylen Length of the key + * @param value The value + * @param valuelen Length of the value + * @return 0 on success, < 0 on errors + */ +extern int kvvec_addkv_wlen(struct kvvec *kvv, const char *key, int keylen, const char *value, int valuelen); + +/** + * Shortcut to kvvec_addkv_wlen() when lengths aren't known + * @param kvv The key/value vector to add this key/value pair to + * @param key The key + * @param value The value + * @return 0 on success, < 0 on errors + */ +#define kvvec_addkv(kvv, key, value) kvvec_addkv_wlen(kvv, key, 0, value, 0) + +/** + * Walk each key/value pair in a key/value vector, sending them + * as arguments to a callback function. The callback function has + * no control over the iteration process and must not delete or + * modify the key/value vector it's operating on. + * @param kvv The key/value vector to walk + * @param arg Extra argument to the callback function + * @param callback Callback function + * @return 0 on success, < 0 on errors + */ +extern int kvvec_foreach(struct kvvec *kvv, void *arg, int (*callback)(struct key_value *, void *)); + +/** + * Destroy a key/value vector + * @param kvv The key/value vector to destroy + * @param flags or'ed combination of KVVEC_FREE_{KEYS,VALUES}, or KVVEC_FREE_ALL + * @return 0 on success, < 0 on errors + */ +extern int kvvec_destroy(struct kvvec *kvv, int flags); + +/** + * Free key/value pairs associated with a key/value vector + * @param kvv The key/value vector to operate on + * @param flags flags or'ed combination of KVVEC_FREE_{KEYS,VALUES}, or KVVEC_FREE_ALL + */ +void kvvec_free_kvpairs(struct kvvec *kvv, int flags); + +/** + * Create a linear buffer of all the key/value pairs and + * return it as a kvvec_buf. The caller must free() all + * pointers in the returned kvvec_buf + * (FIXME: add kvvec_buf_destroy(), or move this and its counterpart + * out of the kvvec api into a separate one) + * + * @param kvv The key/value vector to convert + * @param kv_sep Character separating keys and their values + * @param pair_sep Character separating key/value pairs + * @param overalloc Integer determining how much extra data we should + * allocate. The overallocated memory is filled with + * nul bytes. + * @return A pointer to a newly created kvvec_buf structure + */ +extern struct kvvec_buf *kvvec2buf(struct kvvec *kvv, char kv_sep, char pair_sep, int overalloc); + +/** + * Create a key/value vector from a pre-parsed buffer. Immensely + * useful for ipc in combination with kvvec2buf(). + * + * @param str The buffer to convert to a key/value vector + * @param len Length of buffer to convert + * @param kvsep Character separating key and value + * @param pair_sep Character separating key/value pairs + * @param flags bitmask. See KVVEC_{ASSIGN,COPY,APPEND} for values + * @return The created key/value vector + */ +extern struct kvvec *buf2kvvec(char *str, unsigned int len, const char kvsep, const char pair_sep, int flags); + +/** + * Parse a buffer into the pre-allocated key/value vector. Immensely + * useful for ipc in combination with kvvec2buf(). + * + * @param kvv A pre-allocated key/value vector to populate + * @param str The buffer to convert to a key/value vector + * @param len Length of buffer to convert + * @param kvsep Character separating key and value + * @param pair_sep Character separating key/value pairs + * @param flags bitmask. See KVVEC_{ASSIGN,COPY,APPEND} for values + * @return The number of pairs in the created key/value vector + */ +extern int buf2kvvec_prealloc(struct kvvec *kvv, char *str, unsigned int len, const char kvsep, const char pair_sep, int flags); +/** @} */ +#endif /* INCLUDE_kvvec_h__ */ diff --git a/lib/libnagios.h b/lib/libnagios.h new file mode 100644 index 0000000..1c78f05 --- /dev/null +++ b/lib/libnagios.h @@ -0,0 +1,26 @@ +#ifndef LIBNAGIOS_LIBNAGIOS_H_INCLUDED +#define LIBNAGIOS_LIBNAGIOS_H_INCLUDED +/** + * @file libnagios.h + * + * @brief Include this for all public parts of libnagios to be accessible + */ + +#include "lnag-utils.h" +#include "fanout.h" +#include "nsutils.h" +#include "pqueue.h" +#include "squeue.h" +#include "kvvec.h" +#include "iobroker.h" +#include "iocache.h" +#include "runcmd.h" +#include "bitmap.h" +#include "dkhash.h" +#include "worker.h" +#include "skiplist.h" +#include "nsock.h" +#include "nspath.h" +#include "snprintf.h" +#include "nwrite.h" +#endif /* LIB_libnagios_h__ */ diff --git a/lib/lnag-utils.h b/lib/lnag-utils.h new file mode 100644 index 0000000..443025e --- /dev/null +++ b/lib/lnag-utils.h @@ -0,0 +1,111 @@ +#ifndef LIBNAGIOS_LNAG_UTILS_H_INCLUDED +#define LIBNAGIOS_LNAG_UTILS_H_INCLUDED + +#include /* for sysconf() */ +#include /* for rand() */ + +/** + * @file lnag-utils.h + * @brief libnagios helper and compatibility macros that lack a "real" home. + * + * This is the home of random macros that must be present for compilation + * to succeed but are missing on some platforms. + * + * @{ + */ + +#define NAGIOS_MKVERSION(a, b, c) \ + (((a) * 10000) + ((b) * 100) + (c)) + +#ifdef __cplusplus +/** C++ compatibility macro that avoids confusing indentation programs */ +# define NAGIOS_BEGIN_DECL extern "C" { +/** + * Use at end of header file declarations to obtain C++ compatibility + * ... without confusing indentation programs + */ +# define NAGIOS_END_DECL } +#else +/** C++ compatibility macro that avoids confusing indentation programs */ +# define NAGIOS_BEGIN_DECL /* nothing */ +/** C++ compatibility macro that avoid confusing indentation programs */ +# define NAGIOS_END_DECL /* more of nothing */ +#endif + +#ifndef NODOXY /* doxy comments are useless here */ +# ifndef __GNUC__ +# define GCC_VERSION 0 +# define __attribute__(x) /* nothing */ +# else +# ifdef __GNUC_PATCHLEVEL__ +# define GCC_VERSION NAGIOS_MKVERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) +# else +# define GCC_VERSION NAGIOS_MKVERSION(__GNUC__, __GNUC_MINOR__, 0) +# endif /* __GNUC_PATCHLEVEL__ */ +# endif /* __GNUC__ */ +#endif /* NODOXY */ + +#if GCC_VERSION >= NAGIOS_MKVERSION(4, 5, 0) +# define NAGIOS_DEPRECATED(version, hint) \ + __attribute__((deprecated("This function will be removed in Nagios v" #version ". Please use " #hint " instead"))) +#else +/** Macro for alerting module authors to function deprecation */ +# define NAGIOS_DEPRECATED(version, hint) \ + __attribute__((deprecated)) +#endif + +/* + * These macros are widely used throughout Nagios + */ +#define OK 0 /**< Indicates successful function call in Nagios */ +#define ERROR -2 /**< Non-successful function call in Nagios */ + +#ifdef FALSE +#undef FALSE +#endif +#define FALSE 0 /**< Not true */ + +#ifdef TRUE +#undef TRUE +#endif +#define TRUE (!FALSE) /**< Not false */ + +/** Useful macro to safely avoid double-free memory corruption */ +#define my_free(ptr) do { if(ptr) { free(ptr); ptr = NULL; } } while(0) + +#ifndef ARRAY_SIZE +/** Useful for iterating over all elements in a static array */ +# define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) +#endif +#ifndef veclen +/** useful for iterating over all elements in a static array */ +# define veclen ARRAY_SIZE +#endif + +#ifndef offsetof +/** standard offsetof macro */ +# define offsetof(t, f) ((unsigned long)&((t *)0)->f) +#endif + +/** character map initialization for .bss-allocated char maps */ +#define CHAR_MAP_INIT(k) { \ + k, k, k, k, k, k, k, k, k, k, k, k, k, k, k, k, \ + k, k, k, k, k, k, k, k, k, k, k, k, k, k, k, k, \ + k, k, k, k, k, k, k, k, k, k, k, k, k, k, k, k, \ + k, k, k, k, k, k, k, k, k, k, k, k, k, k, k, k, \ + k, k, k, k, k, k, k, k, k, k, k, k, k, k, k, k, \ + k, k, k, k, k, k, k, k, k, k, k, k, k, k, k, k, \ + k, k, k, k, k, k, k, k, k, k, k, k, k, k, k, k, \ + k, k, k, k, k, k, k, k, k, k, k, k, k, k, k, k, \ + k, k, k, k, k, k, k, k, k, k, k, k, k, k, k, k, \ + k, k, k, k, k, k, k, k, k, k, k, k, k, k, k, k, \ + k, k, k, k, k, k, k, k, k, k, k, k, k, k, k, k, \ + k, k, k, k, k, k, k, k, k, k, k, k, k, k, k, k, \ + k, k, k, k, k, k, k, k, k, k, k, k, k, k, k, k, \ + k, k, k, k, k, k, k, k, k, k, k, k, k, k, k, k, \ + k, k, k, k, k, k, k, k, k, k, k, k, k, k, k, k, \ + k, k, k, k, k, k, k, k, k, k, k, k, k, k, k, k, \ + } + +/** @} */ +#endif diff --git a/lib/nsock.c b/lib/nsock.c new file mode 100644 index 0000000..b12ca1c --- /dev/null +++ b/lib/nsock.c @@ -0,0 +1,153 @@ +#define _GNU_SOURCE 1 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "snprintf.h" +#include "lnag-utils.h" +#include "nsock.h" +#include + +const char *nsock_strerror(int code) +{ + switch (code) { + case NSOCK_EBIND: return "bind() failed"; + case NSOCK_ELISTEN: return "listen() failed"; + case NSOCK_ESOCKET: return "socket() failed"; + case NSOCK_EUNLINK: return "unlink() failed"; + case NSOCK_ECONNECT: return "connect() failed"; + case NSOCK_EFCNTL: return "fcntl() failed"; + case NSOCK_EINVAL: return "Invalid arguments"; + } + + return "Unknown error"; +} + +int nsock_unix(const char *path, unsigned int flags) +{ + static int listen_backlog = INT_MAX; + struct sockaddr_un saun; + struct sockaddr *sa; + int sock = 0, mode; + socklen_t slen; + + if(!path) + return NSOCK_EINVAL; + + if(flags & NSOCK_TCP) + mode = SOCK_STREAM; + else if(flags & NSOCK_UDP) + mode = SOCK_DGRAM; + else + return NSOCK_EINVAL; + + if((sock = socket(AF_UNIX, mode, 0)) < 0) { + return NSOCK_ESOCKET; + } + + /* set up the sockaddr_un struct and the socklen_t */ + sa = (struct sockaddr *)&saun; + memset(&saun, 0, sizeof(saun)); + saun.sun_family = AF_UNIX; + slen = strlen(path); + memcpy(&saun.sun_path, path, slen); + slen += offsetof(struct sockaddr_un, sun_path); + + /* unlink if we're supposed to, but not if we're connecting */ + if(flags & NSOCK_UNLINK && !(flags & NSOCK_CONNECT)) { + if(unlink(path) < 0 && errno != ENOENT) + return NSOCK_EUNLINK; + } + + if(flags & NSOCK_CONNECT) { + if(connect(sock, sa, slen) < 0) { + close(sock); + return NSOCK_ECONNECT; + } + return sock; + } else { + if(bind(sock, sa, slen) < 0) { + close(sock); + return NSOCK_EBIND; + } + } + + if(!(flags & NSOCK_BLOCK) && fcntl(sock, F_SETFL, O_NONBLOCK) < 0) + return NSOCK_EFCNTL; + + if(flags & NSOCK_UDP) + return sock; + + /* Default the backlog number on listen() to INT_MAX. If INT_MAX fails, + * try using SOMAXCONN (usually 127) and if that fails, return an error */ + for (;;) { + if (listen(sock, listen_backlog)) { + if (listen_backlog == SOMAXCONN) { + close(sock); + return NSOCK_ELISTEN; + } else + listen_backlog = SOMAXCONN; + } + break; + } + + return sock; +} + +static inline int nsock_vprintf(int sd, const char *fmt, va_list ap, int plus) +{ + va_list ap_dup; + char stack_buf[4096]; + int len; + + va_copy(ap_dup, ap); + len = vsnprintf(stack_buf, sizeof(stack_buf), fmt, ap_dup); + va_end(ap_dup); + if (len < 0) + return len; + + if (len < sizeof(stack_buf)) { + stack_buf[len] = 0; + if (plus) ++len; /* Include the nul byte if requested. */ + return write(sd, stack_buf, len); + + } else { + char *heap_buf = NULL; + + len = vasprintf(&heap_buf, fmt, ap); + if (len < 0) + return len; + + if (plus) ++len; /* Include the nul byte if requested. */ + len = write(sd, heap_buf, len); + free(heap_buf); + return len; + } +} + +int nsock_printf_nul(int sd, const char *fmt, ...) +{ + va_list ap; + int ret; + + va_start(ap, fmt); + ret = nsock_vprintf(sd, fmt, ap, 1); + va_end(ap); + return ret; +} + +int nsock_printf(int sd, const char *fmt, ...) +{ + va_list ap; + int ret; + + va_start(ap, fmt); + ret = nsock_vprintf(sd, fmt, ap, 0); + va_end(ap); + return ret; +} diff --git a/lib/nsock.h b/lib/nsock.h new file mode 100644 index 0000000..4902971 --- /dev/null +++ b/lib/nsock.h @@ -0,0 +1,76 @@ +#ifndef LIBNAGIOS_NSOCK_H_INCLUDED +#define LIBNAGIOS_NSOCK_H_INCLUDED +#include + +/** + * @file nsock.h + * @brief Nagios socket helper library + * + * This is a pretty stupid library, but since so many addons and + * now Nagios core itself makes use of sockets, we might as well + * have some simple wrappers for it that handle the most common + * cases. + * + * @{ + */ + +#define NSOCK_EBIND (-1) /**< failed to bind() */ +#define NSOCK_ELISTEN (-2) /**< failed to listen() */ +#define NSOCK_ESOCKET (-3) /**< failed to socket() */ +#define NSOCK_EUNLINK (-4) /**< failed to unlink() */ +#define NSOCK_ECONNECT (-5) /**< failed to connect() */ +#define NSOCK_EFCNTL (-6) /**< failed to fcntl() */ +#define NSOCK_EINVAL (-EINVAL) /**< -22, normally */ + +/* flags for the various create calls */ +#define NSOCK_TCP (1 << 0) /**< use tcp mode */ +#define NSOCK_UDP (1 << 1) /**< use udp mode */ +#define NSOCK_UNLINK (1 << 2) /**< unlink existing path (only nsock_unix) */ +#define NSOCK_REUSE (1 << 2) /**< reuse existing address */ +#define NSOCK_CONNECT (1 << 3) /**< connect rather than create */ +#define NSOCK_BLOCK (1 << 4) /**< socket should be in blocking mode */ + +/** + * Grab an error string relating to nsock_unix() + * @param code The error code return by the nsock library + * @return An error string describing the error + */ +extern const char *nsock_strerror(int code); + +/** + * Create or connect to a unix socket + * To control permissions on sockets when NSOCK_LISTEN is specified, + * callers will have to modify their umask() before (and possibly + * after) the nsock_unix() call. + * + * @param path The path to connect to or create + * @param flags Various options controlling the mode of the socket + * @return An NSOCK_E macro on errors, the created socket on succes + */ +extern int nsock_unix(const char *path, unsigned int flags); + +/** + * Write a nul-terminated message to the socket pointed to by sd. + * This isn't quite the same as dprintf(), which doesn't include + * the terminating nul byte. + * @note This function may block, so poll(2) for writability + * @param sd The socket to write to + * @param fmt The format string + * @return Whatever write() returns + */ +extern int nsock_printf_nul(int sd, const char *fmt, ...) + __attribute__((__format__(__printf__, 2, 3))); + +/** + * Write a printf()-formatted string to the socket pointed to by sd. + * This is identical to dprintf(), which is unfortunately GNU only. + * @note This function may block, so poll(2) for writability + * @param sd The socket to write to + * @param fmt The format string + * @return Whatever write() returns + */ +extern int nsock_printf(int sd, const char *fmt, ...) + __attribute__((__format__(__printf__, 2, 3))); + +/** @} */ +#endif /* LIBNAGIOS_NSOCK_H_INCLUDED */ diff --git a/lib/nspath.c b/lib/nspath.c new file mode 100644 index 0000000..cb05e61 --- /dev/null +++ b/lib/nspath.c @@ -0,0 +1,232 @@ +#define _GNU_SOURCE 1 +#include +#include +#include +#include +#include +#include +#include +#include +#include "nspath.h" + +#ifndef PATH_MAX +# define PATH_MAX 4096 +#endif + +#define PCOMP_IGNORE (1 << 0) /* marks negated or ignored components */ +#define PCOMP_ALLOC (1 << 1) /* future used for symlink resolutions */ + +/* path component struct */ +struct pcomp { + char *str; /* file- or directoryname */ + unsigned int len; /* length of this component */ + int flags; +}; + +static inline int path_components(const char *path) +{ + char *slash; + int comps = 1; + if (!path) + return 0; + for (slash = strchr(path, '/'); slash; slash = strchr(slash + 1, '/')) + comps++; + return comps; +} + +static char *pcomp_construct(struct pcomp *pcomp, int comps) +{ + int i, plen = 0, offset = 0; + char *path; + + for (i = 0; i < comps; i++) { + if(pcomp[i].flags & PCOMP_IGNORE) + continue; + plen += pcomp[i].len + 1; + } + + path = malloc(plen + 2); + + for (i = 0; i < comps; i++) { + if(pcomp[i].flags & PCOMP_IGNORE) + continue; + memcpy(path + offset, pcomp[i].str, pcomp[i].len); + offset += pcomp[i].len; + if (i < comps - 1) + path[offset++] = '/'; + } + path[offset] = 0; + + return path; +} + +/* + * Converts "foo/bar/.././lala.txt" to "foo/lala.txt". + * "../../../../../bar/../foo/" becomes "/foo/" + */ +char *nspath_normalize(const char *orig_path) +{ + struct pcomp *pcomp = NULL; + int comps, i = 0, m, depth = 0, have_slash = 0; + char *path, *rpath, *p, *slash; + + if (!orig_path || !*orig_path) + return NULL; + + rpath = strdup(orig_path); + comps = path_components(rpath); + pcomp = calloc(comps, sizeof(struct pcomp)); + if (pcomp == NULL) + return NULL; + + p = pcomp[0].str = rpath; + for (; p; p = slash, i++) { + slash = strchr(p, '/'); + if (slash) { + have_slash = 1; + *slash = 0; + slash++; + } + pcomp[i].len = strlen(p); + pcomp[i].str = p; + + if (*p == '.') { + if (p[1] == 0) { + /* dot-slash is always just ignored */ + pcomp[i].flags |= PCOMP_IGNORE; + continue; + } + if ((*orig_path == '/' || depth) && p[1] == '.' && p[2] == 0) { + /* dot-dot-slash negates the previous non-negated component */ + pcomp[i].flags |= PCOMP_IGNORE; + for(m = 0; depth && m <= i; m++) { + if (pcomp[i - m].flags & PCOMP_IGNORE) { + continue; + } + pcomp[i - m].flags |= PCOMP_IGNORE; + depth--; + break; /* we only remove one level at most */ + } + continue; + } + } + /* convert multiple slashes to one */ + if (i && !*p) { + pcomp[i].flags |= PCOMP_IGNORE; + continue; + } + depth++; + } + + /* + * If we back up all the way to the root we need to add a slash + * as the first path component. + */ + if (have_slash && depth == 1) { + pcomp[0].flags &= ~(PCOMP_IGNORE); + pcomp[0].str[0] = 0; + pcomp[0].len = 0; + } + path = pcomp_construct(pcomp, comps); + free(rpath); + free(pcomp); + return path; +} + +char *nspath_absolute(const char *rel_path, const char *base) +{ + char cwd[PATH_MAX]; + int len; + char *path = NULL, *normpath; + + if (*rel_path == '/') + return nspath_normalize(rel_path); + + if (!base) { + if (getcwd(cwd, sizeof(cwd)) == NULL) + return NULL; + base = cwd; + } + + len = asprintf(&path, "%s/%s", base, rel_path); + if (len <= 0) { + if (path) + free(path); + return NULL; + } + + normpath = nspath_normalize(path); + free(path); + + return normpath; +} + +char *nspath_real(const char *rel_path, const char *base) +{ + char *abspath, *ret; + + if (!(abspath = nspath_absolute(rel_path, base))) + return NULL; + + ret = realpath(abspath, NULL); + free(abspath); + return ret; +} + +/* we must take care not to destroy the original buffer here */ +char *nspath_absolute_dirname(const char *path, const char *base) +{ + char *buf, *ret; + + if (!(buf = nspath_absolute(path, base))) + return NULL; + + ret = strdup(dirname(buf)); + free(buf); + return ret; +} + +int nspath_mkdir_p(const char *orig_path, mode_t mode, int options) +{ + char *sep, *path; + int ret = 0, mkdir_start = 0; + + if (!orig_path) { + errno = EFAULT; + return -1; + } + + sep = path = strdup(orig_path); + if (!sep) + return -1; + + for (;;) { + struct stat st; + + if ((sep = strchr(sep + 1, '/'))) { + *sep = 0; /* nul-terminate path */ + } else if (options & NSPATH_MKDIR_SKIP_LAST) { + break; + } + + /* stat() our way up the tree and start mkdir() on ENOENT */ + if (!mkdir_start && (ret = stat(path, &st)) < 0) { + if (errno != ENOENT) { + break; + } + mkdir_start = 1; + } + + if (mkdir_start && (ret = mkdir(path, mode)) < 0) { + break; + } + + /* end of path or trailing slash? */ + if (!sep || !sep[1]) + break; + *sep = '/'; + } + + free(path); + return ret; +} diff --git a/lib/nspath.h b/lib/nspath.h new file mode 100644 index 0000000..ba0be1b --- /dev/null +++ b/lib/nspath.h @@ -0,0 +1,91 @@ +#ifndef LIBNAGIOS_NSPATH_H_INCLUDED +#define LIBNAGIOS_NSPATH_H_INCLUDED +#ifndef _GNU_SOURCE +# ifndef NODOXY +# define _GNU_SOURCE 1 +# endif +#endif +#include +#include +#include "snprintf.h" + +/** + * @file nspath.h + * @brief path handling functions + * + * This library handles path normalization and resolution. It's nifty + * if you want to turn relative paths into absolute ones, or if you + * want to make insane ones sane, but without chdir()'ing your way + * around the filesystem. + * + * @{ + */ + +/** + * Normalize a path + * By "normalize", we mean that we convert dot-slash and dot-dot-slash + * embedded components into a legible continuous string of characters. + * Leading and trailing slashes are kept exactly as they are in input, + * but with sequences of slashes reduced to a single one. + * + * "foo/bar/.././lala.txt" becomes "foo/lala.txt" + * "../../../../bar/../foo/" becomes "/foo/" + * "////foo////././bar" becomes "/foo/bar" + * @param orig_path The path to normalize + * @return A newly allocated string containing the normalized path + */ +extern char *nspath_normalize(const char *orig_path); + +/** + * Make the "base"-relative path "rel_path" absolute. + * Turns the relative path "rel_path" into an absolute path and + * resolves it as if we were currently in "base". If "base" is + * NULL, the current working directory is used. If "base" is not + * null, it should be an absolute path for the result to make + * sense. + * + * @param rel_path The relative path to convert + * @param base The base directory (if NULL, we use current working dir) + * @return A newly allocated string containing the absolute path + */ +extern char *nspath_absolute(const char *rel_path, const char *base); + +/** + * Canonicalize the "base"-relative path "rel_path". + * errno gets properly set in case of errors. + * @param rel_path The path to transform + * @param base The base we should operate relative to + * @return Newly allocated canonical path on succes, NULL on errors + */ +extern char *nspath_real(const char *rel_path, const char *base); + +/** + * Get absolute dirname of "path", relative to "base" + * @param path Full path to target object (file or subdir) + * @param base The base directory (if NULL, we use current working dir) + * @return NULL on errors, allocated absolute directory name on success + */ +extern char *nspath_absolute_dirname(const char *path, const char *base); + + +/** + * Recursively create a directory, just like mkdir_p would. + * @note This function *will* taint errno with ENOENT if any path + * component has to be created. + * @note If "path" has a trailing slash, NSPATH_MKDIR_SKIP_LAST + * won't have any effect. That's considered a feature, since the + * option is designed so one can send a file-path to the function + * and have it create the directory structure for it. + * @param path Path to create, in normalized form + * @param mode Filemode (same as mkdir() takes) + * @param options Options flag. See NSPATH_MKDIR_* for or-able options + * @return 0 on success, -1 on errors and errno will hold error code + * from either stat() or mkdir(). + */ +extern int nspath_mkdir_p(const char *path, mode_t mode, int options); + +/** Don't mkdir() last element of path when calling nspath_mkdir_p() */ +#define NSPATH_MKDIR_SKIP_LAST (1 << 0) + +/** @} */ +#endif diff --git a/lib/nsutils.c b/lib/nsutils.c new file mode 100644 index 0000000..8bd9139 --- /dev/null +++ b/lib/nsutils.c @@ -0,0 +1,94 @@ +#include "lnag-utils.h" +#include "nsutils.h" +#include +#include +#include + +#if defined(hpux) || defined(__hpux) || defined(_hpux) +# include +#endif + +/* + * By doing this in two steps we can at least get + * the function to be somewhat coherent, even + * with this disgusting nest of #ifdefs. + */ +#ifndef _SC_NPROCESSORS_ONLN +# ifdef _SC_NPROC_ONLN +# define _SC_NPROCESSORS_ONLN _SC_NPROC_ONLN +# elif defined _SC_CRAY_NCPU +# define _SC_NPROCESSORS_ONLN _SC_CRAY_NCPU +# endif +#endif + +int real_online_cpus(void) +{ +#ifdef _SC_NPROCESSORS_ONLN + long ncpus; + + if ((ncpus = (long)sysconf(_SC_NPROCESSORS_ONLN)) > 0) + return (int)ncpus; +#elif defined(hpux) || defined(__hpux) || defined(_hpux) + struct pst_dynamic psd; + + if (!pstat_getdynamic(&psd, sizeof(psd), (size_t)1, 0)) + return (int)psd.psd_proc_cnt; +#endif + + return 0; +} + +int online_cpus(void) +{ + int ncpus = real_online_cpus(); + return ncpus > 0 ? ncpus : 1; +} + +int tv_delta_msec(const struct timeval *start, const struct timeval *stop) +{ + int msecs; + unsigned long usecs = 0; + + msecs = (stop->tv_sec - start->tv_sec) * 1000; + if (stop->tv_usec < start->tv_usec) { + msecs -= 1000; + usecs += 1000000; + } + usecs += stop->tv_usec - start->tv_usec; + msecs += (usecs / 1000); + + return msecs; +} + +float tv_delta_f(const struct timeval *start, const struct timeval *stop) +{ +#define DIVIDER 1000000 + float ret; + time_t usecs, stop_usec; + + ret = stop->tv_sec - start->tv_sec; + stop_usec = stop->tv_usec; + if (stop_usec < start->tv_usec) { + ret -= 1.0; + stop_usec += DIVIDER; + } + usecs = stop_usec - start->tv_usec; + + ret += (float)((float)usecs / DIVIDER); + return ret; +} + +#define MKSTR_BUFS 256 /* should be plenty */ +const char *mkstr(const char *fmt, ...) +{ + static char buf[MKSTR_BUFS][32]; /* 8k statically on the stack */ + static int slot = 0; + char *ret; + + va_list ap; + va_start(ap, fmt); + ret = buf[slot++ % MKSTR_BUFS]; + vsnprintf(ret, sizeof(buf[0]), fmt, ap); + va_end(ap); + return ret; +} diff --git a/lib/nsutils.h b/lib/nsutils.h new file mode 100644 index 0000000..a003535 --- /dev/null +++ b/lib/nsutils.h @@ -0,0 +1,112 @@ +#ifndef LIBNAGIOS_NSUTILS_H_INCLUDED +#define LIBNAGIOS_NSUTILS_H_INCLUDED +#include +#include + +/** + * @file nsutils.h + * @brief Non-Standard (or Nagios) utility functions and macros. + * + * This is where we house all helpers and macros that fall outside + * the "standard-ish" norm. The prefixes "nsu_" and NSU_ are + * reserved for this purpose, so we avoid clashing with other + * applications that may have similarly-acting functions with + * identical names. + * + * The functions already here lack the nsu_ prefix for backwards + * compatibility reasons. It's possible we'll have to fix that + * some day, but let's leave that for later. + * + * @{ + */ + +/** Macro for dynamically increasing vector lengths */ +#define alloc_nr(x) (((x)+16)*3/2) + +/** + * Check if a number is a power of 2 + * @param x The number to check + * @return 1 if the number is a power of 2, 0 if it's not + */ +static inline int nsu_ispow2(unsigned int x) +{ + return x > 1 ? !(x & (x - 1)) : 0; +} + +/** + * Round up to a power of 2 + * Yes, this is the most cryptic function name in all of Nagios, but I + * like it, so shush. + * @param r The number to round up + * @return r, rounded up to the nearest power of 2. + */ +static inline unsigned int rup2pof2(unsigned int r) +{ + r--; + if (!r) + return 2; + r |= r >> 1; + r |= r >> 2; + r |= r >> 4; + r |= r >> 8; + r |= r >> 16; + + return r + 1; +} + +/** + * Grab a random unsigned int in the range between low and high. + * Note that the PRNG has to be seeded prior to calling this. + * @param low The lower bound, inclusive + * @param high The higher bound, inclusive + * @return An unsigned integer in the mathematical range [low, high] + */ +static inline unsigned int ranged_urand(unsigned int low, unsigned int high) +{ + return low + (rand() * (1.0 / (RAND_MAX + 1.0)) * (high - low)); +} + +/** + * Get number of online cpus + * @return Active cpu cores detected on success. 0 on failure. + */ +extern int real_online_cpus(void); + +/** + * Wrapper for real_online_cpus(), returning 1 in case we can't + * detect any active cpus. + * @return Number of active cpu cores on success. 1 on failure. + */ +extern int online_cpus(void); + +/** + * Create a short-lived string in stack-allocated memory + * The number and size of strings is limited (currently to 256 strings of + * 32 bytes each), so beware and use this sensibly. Intended for + * number-to-string conversion and other short strings. + * @note The returned string must *not* be free()'d! + * @param[in] fmt The format string + * @return A pointer to the formatted string on success. Undefined on errors + */ +extern const char *mkstr(const char *fmt, ...) + __attribute__((__format__(__printf__, 1, 2))); + +/** + * Calculate the millisecond delta between two timeval structs + * @param[in] start The start time + * @param[in] stop The stop time + * @return The millisecond delta between the two structs + */ +extern int tv_delta_msec(const struct timeval *start, const struct timeval *stop); + + +/** + * Get timeval delta as seconds + * @param start The start time + * @param stop The stop time + * @return time difference in fractions of seconds + */ +extern float tv_delta_f(const struct timeval *start, const struct timeval *stop); + +/** @} */ +#endif /* LIBNAGIOS_NSUTILS_H_INCLUDED */ diff --git a/lib/nwrite.h b/lib/nwrite.h new file mode 100644 index 0000000..a8089a7 --- /dev/null +++ b/lib/nwrite.h @@ -0,0 +1,52 @@ +#ifndef LIBNAGIOS_NWRITE_H_INCLUDED +#define LIBNAGIOS_NWRITE_H_INCLUDED + +/** + * @file nwrite.h + * @brief Functions that properly handle incomplete write()'s + * + * Some functions simply use write() to send data through a socket. + * These calls are sometimes interrupted, especially in the case of + * an overly large buffer. Even though the write() _could_ finish, + * the incomplete write is treated as an error. The functions here + * properly handle those cases. + * + * @{ + */ + +/** + * Send data through a socket + * This function will send data through a socket and return + * the number of bytes written. + * @param sock The socket to write to + * @param data The data to write + * @param lth The length of the data + * @param sent The number of bytes written (can be NULL) + * @return The number of bytes written or -1 if error + */ +static inline ssize_t nwrite(int fd, const void *buf, size_t count, ssize_t *written) +{ + ssize_t out, tot = 0; + + if (!buf || count == 0) + return 0; + + while (tot < count) { + out = write(fd, buf + tot, count - tot); + if (out > 0) + tot += out; + else if(errno == EAGAIN || errno == EINTR) + continue; + else { + if (written) + *written = tot; + return out; + } + } + if (written) + *written = tot; + return tot; +} + +/** @} */ +#endif /* LIBNAGIOS_NWRITE_H_INCLUDED */ diff --git a/lib/pqueue.c b/lib/pqueue.c new file mode 100644 index 0000000..32401e1 --- /dev/null +++ b/lib/pqueue.c @@ -0,0 +1,303 @@ +/* + * Copyright 2010 Volkan Yazıcı + * Copyright 2006-2010 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + + +#include +#include +#include + +#include "pqueue.h" + + +#define left(i) (unsigned long)((i) << 1) +#define right(i) (unsigned long)(((i) << 1) + 1) +#define parent(i) (unsigned long)((i) >> 1) + + +pqueue_t * +pqueue_init(unsigned int n, + pqueue_cmp_pri_f cmppri, + pqueue_get_pri_f getpri, + pqueue_set_pri_f setpri, + pqueue_get_pos_f getpos, + pqueue_set_pos_f setpos) +{ + pqueue_t *q; + + if (!(q = calloc(1, sizeof(pqueue_t)))) { + return NULL; + } + + /* Need to allocate n+1 elements since element 0 isn't used. */ + if (!(q->d = calloc(n + 1, sizeof(void *)))) { + free(q); + return NULL; + } + + q->size = 1; + q->avail = q->step = (n + 1); /* see comment above about n+1 */ + q->cmppri = cmppri; + q->setpri = setpri; + q->getpri = getpri; + q->getpos = getpos; + q->setpos = setpos; + + return q; +} + + +void +pqueue_free(pqueue_t *q) +{ + free(q->d); + free(q); +} + + +unsigned int +pqueue_size(pqueue_t *q) +{ + /* queue element 0 exists but doesn't count since it isn't used. */ + return (q->size - 1); +} + + +static void +bubble_up(pqueue_t *q, unsigned int i) +{ + unsigned int parent_node; + void *moving_node = q->d[i]; + pqueue_pri_t moving_pri = q->getpri(moving_node); + + for (parent_node = parent(i); + ((i > 1) && q->cmppri(q->getpri(q->d[parent_node]), moving_pri)); + i = parent_node, parent_node = parent(i)) { + q->d[i] = q->d[parent_node]; + q->setpos(q->d[i], i); + } + + q->d[i] = moving_node; + q->setpos(moving_node, i); +} + + +static unsigned int +maxchild(pqueue_t *q, unsigned int i) +{ + unsigned int child_node = left(i); + + if (child_node >= q->size) { + return 0; + } + + if ((child_node + 1) < q->size && q->cmppri(q->getpri(q->d[child_node]), q->getpri(q->d[child_node + 1]))) { + child_node++; /* use right child instead of left */ + } + + return child_node; +} + + +static void +percolate_down(pqueue_t *q, unsigned int i) +{ + unsigned int child_node; + void *moving_node = q->d[i]; + pqueue_pri_t moving_pri = q->getpri(moving_node); + + while ((child_node = maxchild(q, i)) && + q->cmppri(moving_pri, q->getpri(q->d[child_node]))) { + q->d[i] = q->d[child_node]; + q->setpos(q->d[i], i); + i = child_node; + } + + q->d[i] = moving_node; + q->setpos(moving_node, i); +} + + +int +pqueue_insert(pqueue_t *q, void *d) +{ + void *tmp; + unsigned int i; + unsigned int newsize; + + if (!q) { + return 1; + } + + /* allocate more memory if necessary */ + if (q->size >= q->avail) { + newsize = q->size + q->step; + if (!(tmp = realloc(q->d, sizeof(void *) * newsize))) { + return 1; + } + q->d = tmp; + q->avail = newsize; + } + + /* insert item */ + i = q->size++; + q->d[i] = d; + bubble_up(q, i); + + return 0; +} + + +void +pqueue_change_priority(pqueue_t *q, pqueue_pri_t new_pri, void *d) +{ + unsigned int posn; + pqueue_pri_t old_pri = q->getpri(d); + + q->setpri(d, new_pri); + posn = q->getpos(d); + if (q->cmppri(old_pri, new_pri)) { + bubble_up(q, posn); + } else { + percolate_down(q, posn); + } +} + + +int +pqueue_remove(pqueue_t *q, void *d) +{ + unsigned int posn = q->getpos(d); + q->d[posn] = q->d[--q->size]; + if (q->cmppri(q->getpri(d), q->getpri(q->d[posn]))) { + bubble_up(q, posn); + } else { + percolate_down(q, posn); + } + + return 0; +} + + +void * +pqueue_pop(pqueue_t *q) +{ + void *head; + + if (!q || q->size == 1) { + return NULL; + } + + head = q->d[1]; + q->d[1] = q->d[--q->size]; + percolate_down(q, 1); + + return head; +} + + +void * +pqueue_peek(pqueue_t *q) +{ + if (!q || q->size == 1) { + return NULL; + } + return q->d[1]; +} + +#if 0 +void +pqueue_dump(pqueue_t *q, FILE *out, pqueue_print_entry_f print) +{ + int i; + + fprintf(out, "posn\tleft\tright\tparent\tmaxchild\t...\n"); + for (i = 1; i < q->size ; i++) { + fprintf(out, "%d\t%d\t%d\t%d\t%ul\t", + i, + left(i), right(i), parent(i), + (unsigned int)maxchild(q, i)); + print(out, q->d[i]); + } +} + + +static void +set_pos(void *d, unsigned int val) +{ + /* do nothing */ +} + + +static void +set_pri(void *d, pqueue_pri_t pri) +{ + /* do nothing */ +} + + +void +pqueue_print(pqueue_t *q, FILE *out, pqueue_print_entry_f print) +{ + pqueue_t *dup; + void *e; + + dup = pqueue_init(q->size, q->cmppri, q->getpri, set_pri, + q->getpos, set_pos); + dup->size = q->size; + dup->avail = q->avail; + dup->step = q->step; + + memcpy(dup->d, q->d, (q->size * sizeof(void *))); + + while ((e = pqueue_pop(dup))) { + print(out, e); + } + + pqueue_free(dup); +} +#endif + +static int +subtree_is_valid(pqueue_t *q, int pos) +{ + if (left(pos) < q->size) { + /* has a left child */ + if (q->cmppri(q->getpri(q->d[pos]), q->getpri(q->d[left(pos)]))) { + return 0; + } + if (!subtree_is_valid(q, left(pos))) { + return 0; + } + } + if (right(pos) < q->size) { + /* has a right child */ + if (q->cmppri(q->getpri(q->d[pos]), q->getpri(q->d[right(pos)]))) { + return 0; + } + if (!subtree_is_valid(q, right(pos))) { + return 0; + } + } + return 1; +} + + +int +pqueue_is_valid(pqueue_t *q) +{ + return subtree_is_valid(q, 1); +} diff --git a/lib/pqueue.h b/lib/pqueue.h new file mode 100644 index 0000000..59b4fc4 --- /dev/null +++ b/lib/pqueue.h @@ -0,0 +1,185 @@ +/* + * Copyright 2010 Volkan Yazıcı + * Copyright 2006-2010 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +#ifndef LIBNAGIOS_PQUEUE_H_INCLUDED +#define LIBNAGIOS_PQUEUE_H_INCLUDED +#include + +/** + * @file pqueue.h + * @brief Priority Queue function declarations + * + * This priority queue library was originally written by Volkan Yazici + * . It was lated adapted for Nagios by + * Andreas Ericsson . Changes compared to the original + * version are pretty much limited to changing pqueue_pri_t to be + * an unsigned long long instead of a double, since ULL comparisons + * are 107 times faster on my 64-bit laptop. + * + * @{ + */ + + +/** priority data type (used to be double, but ull is 107 times faster) */ +typedef unsigned long long pqueue_pri_t; + +/** callback functions to get/set/compare the priority of an element */ +typedef pqueue_pri_t (*pqueue_get_pri_f)(void *a); +typedef void (*pqueue_set_pri_f)(void *a, pqueue_pri_t pri); +typedef int (*pqueue_cmp_pri_f)(pqueue_pri_t next, pqueue_pri_t curr); + + +/** callback functions to get/set the position of an element */ +typedef unsigned int (*pqueue_get_pos_f)(void *a); +typedef void (*pqueue_set_pos_f)(void *a, unsigned int pos); + + +/** debug callback function to print a entry */ +typedef void (*pqueue_print_entry_f)(FILE *out, void *a); + + +/** the priority queue handle */ +typedef struct pqueue_t +{ + unsigned int size; /**< number of elements in this queue */ + unsigned int avail; /**< slots available in this queue */ + unsigned int step; /**< growth stepping setting */ + pqueue_cmp_pri_f cmppri; /**< callback to compare nodes */ + pqueue_get_pri_f getpri; /**< callback to get priority of a node */ + pqueue_set_pri_f setpri; /**< callback to set priority of a node */ + pqueue_get_pos_f getpos; /**< callback to get position of a node */ + pqueue_set_pos_f setpos; /**< callback to set position of a node */ + void **d; /**< The actual queue in binary heap form */ +} pqueue_t; + + +/** + * initialize the queue + * + * @param n the initial estimate of the number of queue items for which memory + * should be preallocated + * @param cmppri The callback function to run to compare two elements + * This callback should return 0 for 'lower' and non-zero + * for 'higher', or vice versa if reverse priority is desired + * @param setpri the callback function to run to assign a score to an element + * @param getpri the callback function to run to set a score to an element + * @param getpos the callback function to get the current element's position + * @param setpos the callback function to set the current element's position + * + * @return the handle or NULL for insufficent memory + */ +pqueue_t * +pqueue_init(unsigned int n, + pqueue_cmp_pri_f cmppri, + pqueue_get_pri_f getpri, + pqueue_set_pri_f setpri, + pqueue_get_pos_f getpos, + pqueue_set_pos_f setpos); + + +/** + * free all memory used by the queue + * @param q the queue + */ +void pqueue_free(pqueue_t *q); + + +/** + * return the size of the queue. + * @param q the queue + */ +unsigned int pqueue_size(pqueue_t *q); + + +/** + * insert an item into the queue. + * @param q the queue + * @param d the item + * @return 0 on success + */ +int pqueue_insert(pqueue_t *q, void *d); + + +/** + * move an existing entry to a different priority + * @param q the queue + * @param new_pri the new priority + * @param d the entry + */ +void +pqueue_change_priority(pqueue_t *q, + pqueue_pri_t new_pri, + void *d); + + +/** + * pop the highest-ranking item from the queue. + * @param q the queue + * @return NULL on error, otherwise the entry + */ +void *pqueue_pop(pqueue_t *q); + + +/** + * remove an item from the queue. + * @param q the queue + * @param d the entry + * @return 0 on success + */ +int pqueue_remove(pqueue_t *q, void *d); + + +/** + * access highest-ranking item without removing it. + * @param q the queue + * @return NULL on error, otherwise the entry + */ +void *pqueue_peek(pqueue_t *q); + + +/** + * print the queue + * @internal + * DEBUG function only + * @param q the queue + * @param out the output handle + * @param the callback function to print the entry + */ +void +pqueue_print(pqueue_t *q, FILE *out, pqueue_print_entry_f print); + + +/** + * dump the queue and it's internal structure + * @internal + * debug function only + * @param q the queue + * @param out the output handle + * @param the callback function to print the entry + */ +void pqueue_dump(pqueue_t *q, FILE *out, pqueue_print_entry_f print); + + +/** + * checks that the pq is in the right order, etc + * @internal + * debug function only + * @param q the queue + */ +int pqueue_is_valid(pqueue_t *q); + +#endif +/** @} */ diff --git a/lib/runcmd.c b/lib/runcmd.c new file mode 100644 index 0000000..93f1dd1 --- /dev/null +++ b/lib/runcmd.c @@ -0,0 +1,639 @@ +/* + * A simple interface to executing programs from other programs, using an + * optimized and safer popen()-like implementation. It is considered safer in + * that no shell needs to be spawned for simple commands, and the environment + * passed to the execve()'d program is essentially empty. + * + * This code is based on popen.c, which in turn was taken from + * "Advanced Programming in the UNIX Environment" by W. Richard Stevens. + * + * Care has been taken to make sure the functions are async-safe. The exception + * is runcmd_init() which multithreaded applications or plugins must call in a + * non-reentrant manner before calling any other runcmd function. + */ + +#define NAGIOSPLUG_API_C 1 + +/* includes **/ +#include +#include +#include +#include +#include +#include +#include +#include +#include "runcmd.h" + + +/** macros **/ +#ifndef WEXITSTATUS +# define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8) +#endif + +#ifndef WIFEXITED +# define WIFEXITED(stat_val) (((stat_val) & 255) == 0) +#endif + +/* Determine whether we have setenv()/unsetenv() (see setenv(3) on Linux) */ +#if _BSD_SOURCE || _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600 +# define HAVE_SETENV +#endif + +/* + * This variable must be global, since there's no way the caller + * can forcibly slay a dead or ungainly running program otherwise. + * + * The check for initialized values and allocation is not atomic, and can + * potentially occur in any number of threads simultaneously. + * + * Multithreaded apps and plugins must initialize it (via runcmd_init()) + * in an async safe manner before calling any other runcmd function. + */ +static pid_t *pids = NULL; + +/* If OPEN_MAX isn't defined, we try the sysconf syscall first. + * If that fails, we fall back to an educated guess which is accurate + * on Linux and some other systems. There's no guarantee that our guess is + * adequate and the program will die with SIGSEGV if it isn't and the + * upper boundary is breached. */ +#ifdef OPEN_MAX +# define maxfd OPEN_MAX +#else +# ifndef _SC_OPEN_MAX /* sysconf macro unavailable, so guess */ +# define maxfd 256 +# else +static int maxfd = 0; +# endif /* _SC_OPEN_MAX */ +#endif /* OPEN_MAX */ + + +const char *runcmd_strerror(int code) +{ + switch (code) { + case RUNCMD_EFD: + return "pipe() or open() failed"; + case RUNCMD_EALLOC: + return "memory allocation failed"; + case RUNCMD_ECMD: + return "command too complicated"; + case RUNCMD_EFORK: + return "failed to fork()"; + case RUNCMD_EINVAL: + return "invalid parameters"; + case RUNCMD_EWAIT: + return "wait() failed"; + } + return "unknown"; +} + +/* yield the pid belonging to a particular file descriptor */ +pid_t runcmd_pid(int fd) +{ + if(!pids || fd >= maxfd || fd < 0) + return 0; + + return pids[fd]; +} + +/* + * Simple command parser which is still tolerably accurate for our + * simple needs. It might serve as a useful example on how to program + * a state-machine though. + * + * It's up to the caller to handle output redirection, job control, + * conditional statements, variable substitution, nested commands and + * function execution. We do mark such occasions with the return code + * though, which is to be interpreted as a bitfield with potentially + * multiple flags set. + */ +#define STATE_NONE 0 +#define STATE_WHITE (1 << 0) +#define STATE_INARG (1 << 1) +#define STATE_INSQ (1 << 2) +#define STATE_INDQ (1 << 3) +#define STATE_SPECIAL (1 << 4) +#define STATE_BSLASH (1 << 5) +#define in_quotes (state & (STATE_INSQ | STATE_INDQ)) +#define is_state(s) (state == s) +#define set_state(s) (state = s) +#define have_state(s) ((state & s) == s) +#define add_state(s) (state |= s) +#define del_state(s) (state &= ~s) +#define add_ret(r) (ret |= r) +int runcmd_cmd2strv(const char *str, int *out_argc, char **out_argv) +{ + int arg = 0; + int a = 0; + unsigned int i; + int state; + int ret = 0; + size_t len; + char *argz; + + set_state(STATE_NONE); + + if (!str || !*str || !out_argc || !out_argv) + return RUNCMD_EINVAL; + + len = strlen(str); + argz = malloc(len + 1); + if (!argz) + return RUNCMD_EALLOC; + + /* Point argv[0] at the parsed argument string argz so we don't leak. */ + out_argv[0] = argz; + out_argv[1] = NULL; + + for (i = 0; i < len; i++) { + const char *p = &str[i]; + + switch (*p) { + case 0: + if (arg == 0) free(out_argv[0]); + out_argv[arg] = NULL; + *out_argc = arg; + return ret; + + case ' ': case '\t': case '\r': case '\n': + if (is_state(STATE_INARG)) { + set_state(STATE_NONE); + argz[a++] = 0; + continue; + } + if (!in_quotes) + continue; + + break; + + case '\\': + /* single-quoted strings never interpolate backslashes */ + if (have_state(STATE_INSQ) || have_state(STATE_BSLASH)) { + break; + } + /* + * double-quoted strings let backslashes escape + * a few, but not all, shell specials + */ + if (have_state(STATE_INDQ)) { + const char next = str[i + 1]; + switch (next) { + case '"': case '\\': case '$': case '`': + add_state(STATE_BSLASH); + continue; + } + break; + } + /* + * unquoted strings remove unescaped backslashes, + * but backslashes escape anything and everything + */ + i++; + break; + + case '\'': + if (have_state(STATE_INDQ)) + break; + if (have_state(STATE_INSQ)) { + del_state(STATE_INSQ); + continue; + } + + /* + * quotes can come inside arguments or + * at the start of them + */ + if (is_state(STATE_NONE) || is_state(STATE_INARG)) { + if (is_state(STATE_NONE)) { + /* starting a new argument */ + out_argv[arg++] = &argz[a]; + } + set_state(STATE_INSQ | STATE_INARG); + continue; + } + case '"': + if (have_state(STATE_INSQ)) + break; + if (have_state(STATE_INDQ)) { + del_state(STATE_INDQ); + continue; + } + if (is_state(STATE_NONE) || is_state(STATE_INARG)) { + if (is_state(STATE_NONE)) { + out_argv[arg++] = &argz[a]; + } + set_state(STATE_INDQ | STATE_INARG); + continue; + } + break; + + case '|': + case '<': + case '>': + if (!in_quotes) { + add_ret(RUNCMD_HAS_REDIR); + } + break; + case '&': case ';': + if (!in_quotes) { + set_state(STATE_SPECIAL); + add_ret(RUNCMD_HAS_JOBCONTROL); + } + break; + + case '`': + if (!have_state(STATE_INSQ) && !have_state(STATE_BSLASH)) { + add_ret(RUNCMD_HAS_SUBCOMMAND); + } + break; + + case '(': case ')': + if (!in_quotes) { + add_ret(RUNCMD_HAS_PAREN); + } + break; + + case '$': + if (!have_state(STATE_INSQ) && !have_state(STATE_BSLASH)) { + if (p[1] == '(') + add_ret(RUNCMD_HAS_SUBCOMMAND); + else + add_ret(RUNCMD_HAS_SHVAR); + } + break; + + case '*': case '?': + if (!in_quotes) { + add_ret(RUNCMD_HAS_WILDCARD); + } + break; + + default: + break; + } + + /* here, we're limited to escaped backslashes, so remove STATE_BSLASH */ + del_state(STATE_BSLASH); + + if (is_state(STATE_NONE)) { + set_state(STATE_INARG); + out_argv[arg++] = &argz[a]; + } + + /* by default we simply copy the byte */ + argz[a++] = str[i]; + } + + /* make sure we nul-terminate the last argument */ + argz[a++] = 0; + + if (have_state(STATE_INSQ)) + add_ret(RUNCMD_HAS_UBSQ); + if (have_state(STATE_INDQ)) + add_ret(RUNCMD_HAS_UBDQ); + + out_argv[arg] = NULL; + *out_argc = arg; + + return ret; +} + + +/* This function is NOT async-safe. It is exported so multithreaded + * plugins (or other apps) can call it prior to running any commands + * through this API and thus achieve async-safeness throughout the API. */ +void runcmd_init(void) +{ +#if defined(RLIMIT_NOFILE) + if (!maxfd) { + struct rlimit rlim; + getrlimit(RLIMIT_NOFILE, &rlim); + maxfd = rlim.rlim_cur; + } +#elif !defined(OPEN_MAX) && !defined(IOV_MAX) && defined(_SC_OPEN_MAX) + if(!maxfd) { + if((maxfd = sysconf(_SC_OPEN_MAX)) < 0) { + /* possibly log or emit a warning here, since there's no + * guarantee that our guess at maxfd will be adequate */ + maxfd = 256; + } + } +#endif + + if (!pids) + pids = calloc(maxfd, sizeof(pid_t)); +} + + +static int runcmd_setenv(const char *name, const char *value); +int update_environment(char *name, char *value, int set); + +/* Start running a command */ +int runcmd_open(const char *cmd, int *pfd, int *pfderr, char **env, + void (*iobreg)(int, int, void *), void *iobregarg) +{ + char **argv = NULL; + int argc = 0; + int cmd2strv_errors; + size_t cmdlen; + pid_t pid; + + int i = 0; + + if(!pids) + runcmd_init(); + + /* We can't do anything without a command, or FD arrays. */ + if (!cmd || !*cmd || !pfd || !pfderr) + return RUNCMD_EINVAL; + + cmdlen = strlen(cmd); + argv = calloc((cmdlen / 2) + 5, sizeof(char *)); + if (!argv) + return RUNCMD_EALLOC; + + cmd2strv_errors = runcmd_cmd2strv(cmd, &argc, argv); + + if (cmd2strv_errors == RUNCMD_EALLOC) { + /* We couldn't allocate the parsed argument array. */ + free(argv); + return RUNCMD_EALLOC; + } + + if (cmd2strv_errors) { + /* Run complex commands via the shell. */ + free(argv[0]); + argv[0] = "/bin/sh"; + argv[1] = "-c"; + argv[2] = strdup(cmd); + if (!argv[2]) { + free(argv); + return RUNCMD_EALLOC; + } + argv[3] = NULL; + } + + if (pipe(pfd) < 0) { + free(!cmd2strv_errors ? argv[0] : argv[2]); + free(argv); + return RUNCMD_EFD; + } + if (pipe(pfderr) < 0) { + free(!cmd2strv_errors ? argv[0] : argv[2]); + free(argv); + close(pfd[0]); + close(pfd[1]); + return RUNCMD_EFD; + } + + if (iobreg) iobreg(pfd[0], pfderr[0], iobregarg); + + pid = fork(); + if (pid < 0) { + free(!cmd2strv_errors ? argv[0] : argv[2]); + free(argv); + close(pfd[0]); + close(pfd[1]); + close(pfderr[0]); + close(pfderr[1]); + return RUNCMD_EFORK; /* errno set by the failing function */ + } + + /* Child runs excevp() and _exit(). */ + if (pid == 0) { + int exit_status = EXIT_SUCCESS; /* To preserve errno when _exit()ing. */ + + /* Make our children their own process group leaders so they are killable + * by their parent (word of the day: filicide / prolicide). */ + if (setpgid(getpid(), getpid()) == -1) { + exit_status = errno; + fprintf(stderr, "setpgid(...) errno %d: %s\n", errno, strerror(errno)); + goto child_error_exit; + } + + close (pfd[0]); + if (pfd[1] != STDOUT_FILENO) { + if (dup2(pfd[1], STDOUT_FILENO) == -1) { + exit_status = errno; + fprintf(stderr, "dup2(pfd[1], STDOUT_FILENO) errno %d: %s\n", errno, strerror(errno)); + goto child_error_exit; + } + close(pfd[1]); + } + + close (pfderr[0]); + if (pfderr[1] != STDERR_FILENO) { + if (dup2(pfderr[1], STDERR_FILENO) == -1) { + exit_status = errno; + fprintf(stderr, "dup2(pfderr[1], STDERR_FILENO) errno %d: %s\n", errno, strerror(errno)); + goto child_error_exit; + } + close(pfderr[1]); + } + + /* Close all descriptors in pids[], the child shouldn't see these. */ + for (i = 0; i < maxfd; i++) { + if (pids[i] > 0) + close(i); + } + + /* Export the environment. */ + if (env) { + for (; env[0] && env[1]; env += 2) { + if (runcmd_setenv(env[0], env[1]) == -1) { + exit_status = errno; + fprintf(stderr, "runcmd_setenv(%s, ...) errno %d: %s\n", + env[0], errno, strerror(errno) + ); + goto child_error_exit; + } + } + } + + /* Add VAR=value arguments from simple commands to the environment. */ + i = 0; + if (!cmd2strv_errors) { + char *ev; + for (; i < argc && (ev = strchr(argv[i], '=')); ++i) { + if (*ev) *ev++ = '\0'; + if (runcmd_setenv(argv[i], ev) == -1) { + exit_status = errno; + fprintf(stderr, "runcmd_setenv(%s, ev) errno %d: %s\n", + argv[i], errno, strerror(errno) + ); + goto child_error_exit; + } + } + if (i == argc) { + exit_status = EXIT_FAILURE; + fprintf(stderr, "No command after variables.\n"); + goto child_error_exit; + } + } + + execvp(argv[i], argv + i); + + exit_status = errno; + fprintf(stderr, "execvp(%s, ...) failed. errno is %d: %s\n", argv[i], errno, strerror(errno)); + +child_error_exit: + /* Free argv memory before exiting so valgrind doesn't see it as a leak. */ + free(!cmd2strv_errors ? argv[0] : argv[2]); + free(argv); + _exit(exit_status); + } + + /* parent picks up execution here */ + /* + * close childs file descriptors in our address space and + * release the memory we used that won't get passed to the + * caller. + */ + close(pfd[1]); + close(pfderr[1]); + free(!cmd2strv_errors ? argv[0] : argv[2]); + free(argv); + + /* tag our file's entry in the pid-list and return it */ + pids[pfd[0]] = pid; + + return pfd[0]; +} + + +int runcmd_close(int fd) +{ + int status; + pid_t pid; + + /* make sure this fd was opened by runcmd_open() */ + if(fd < 0 || fd > maxfd || !pids || (pid = pids[fd]) == 0) + return RUNCMD_EINVAL; + + pids[fd] = 0; + if (close(fd) == -1) + return -1; + + /* EINTR is ok (sort of), everything else is bad */ + while (waitpid(pid, &status, 0) < 0) + if (errno != EINTR) + return RUNCMD_EWAIT; + + /* return child's termination status */ + return (WIFEXITED(status)) ? WEXITSTATUS(status) : -1; +} + + +int runcmd_try_close(int fd, int *status, int sig) +{ + pid_t pid; + int result; + + /* make sure this fd was opened by popen() */ + if(fd < 0 || fd > maxfd || !pids || !pids[fd]) + return RUNCMD_EINVAL; + + pid = pids[fd]; + while((result = waitpid(pid, status, WNOHANG)) != pid) { + if(!result) return 0; + if(result == -1) { + switch(errno) { + case EINTR: + continue; + case EINVAL: + return -1; + case ECHILD: + if(sig) { + result = kill(pid, sig); + sig = 0; + continue; + } + else return -1; + } /* switch */ + } + } + + pids[fd] = 0; + close(fd); + return result; +} + +/** + * Sets an environment variable. + * This is for runcmd_open() to set the child environment. + * @param naem Variable name to set. + * @param value Value to set. + * @return 0 on success, -1 on error with errno set to: EINVAL if name is NULL; + * or the value set by setenv() or asprintf()/putenv(). + * @note If setenv() is unavailable (e.g. Solaris), a "name=vale" string is + * allocated to pass to putenv(), which is retained by the environment. This + * 'leaked' memory will be on the heap at program exit. + */ +static int runcmd_setenv(const char *name, const char *value) { +#ifndef HAVE_SETENV + char *env_string = NULL; +#endif + + /* We won't mess with null variable names or values. */ + if (!name || !value) { + errno = EINVAL; + return -1; + } + + errno = 0; +#ifdef HAVE_SETENV + return setenv(name, value, 1); +#else + /* For Solaris and systems that don't have setenv(). + * This will leak memory, but in a "controlled" way, since the memory + * should be freed when the child process exits. */ + if (asprintf(&env_string, "%s=%s", name, value) == -1) return -1; + if (!env_string) { + errno = ENOMEM; + return -1; + } + return putenv(env_string); +#endif +} + +/* sets or unsets an environment variable */ +int update_environment(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 -1; + + /* set the environment variable */ + if(set == 1) { + +#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 */ + 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 0; +} + +/** + * This will free pids if non-null + * Useful for external applications that rely on libnagios to + * keep a lid on potential memory leaks + */ +void runcmd_free_pids(void) { + if (pids) + free(pids); +} + diff --git a/lib/runcmd.h b/lib/runcmd.h new file mode 100644 index 0000000..f0a1804 --- /dev/null +++ b/lib/runcmd.h @@ -0,0 +1,117 @@ +#ifndef NDO_LIBNAGIOS_RUNCMD_H_INCLUDED +#define NDO_LIBNAGIOS_RUNCMD_H_INCLUDED +#include + +/** + * @file runcmd.h + * @brief runcmd library function declarations + * + * A simple interface to executing programs from other programs, using an + * optimized and safer popen()-like implementation. It is considered safer in + * that no shell needs to be spawned for simple commands, and the environment + * passed to the execve()'d program is essentially empty. + * + * This code is based on popen.c, which in turn was taken from + * "Advanced Programming in the UNIX Environment" by W. Richard Stevens. + * + * Care has been taken to make sure the functions are async-safe. The exception + * is runcmd_init() which multithreaded applications or plugins must call in a + * non-reentrant manner before calling any other runcmd function. + * + * @note This is inherited from the nagiosplugins project, although + * it might need refactoring for performance later. + * @{ + */ + +/** Return code bitflags for runcmd_cmd2strv() */ +#define RUNCMD_HAS_REDIR (1 << 0) /**< I/O redirection */ +#define RUNCMD_HAS_SUBCOMMAND (1 << 1) /**< subcommands present */ +#define RUNCMD_HAS_PAREN (1 << 2) /**< parentheses present in command */ +#define RUNCMD_HAS_JOBCONTROL (1 << 3) /**< job control stuff present */ +#define RUNCMD_HAS_UBSQ (1 << 4) /**< unbalanced single quotes */ +#define RUNCMD_HAS_UBDQ (1 << 5) /**< unbalanced double quotes */ +#define RUNCMD_HAS_WILDCARD (1 << 6) /**< wildcards present */ +#define RUNCMD_HAS_SHVAR (1 << 7) /**< shell variables present */ + + +#define RUNCMD_EFD (-1) /**< Failed to pipe() or open() */ +#define RUNCMD_EALLOC (-2) /**< Failed to alloc */ +#define RUNCMD_ECMD (-3) /**< Bad command */ +#define RUNCMD_EFORK (-4) /**< Failed to fork() */ +#define RUNCMD_EINVAL (-5) /**< Invalid parameters */ +#define RUNCMD_EWAIT (-6) /**< Failed to wait() */ + +/** + * Initialize the runcmd library. + * + * Only multi-threaded programs that might launch the first external + * program from multiple threads simultaneously need to bother with + * this, and they must ensure this is called at least once in a non-reentrant + * manner before calling any other runcmd function. + */ +extern void runcmd_init(void); + +/** + * Return pid of a command with a specific file descriptor + * @param[in] fd stdout filedescriptor of the child to get pid from + * @return pid of the child, or 0 on errors + */ +extern pid_t runcmd_pid(int fd); + +/** + * Return explanation of which system call or operation failed + * @param code Error code returned by a library function + * @return A non-free()'able string explaining where the error occurred + */ +extern const char *runcmd_strerror(int code); + +/** + * Start a command from a command string + * @param[in] cmd The command to launch + * @param[out] pfd Child's stdout filedescriptor + * @param[out] pfderr Child's stderr filedescriptor + * @param[in] env Currently ignored for portability + * @param[in] iobreg The callback function to register the iobrokers for the read ends of the pipe + * @param[in] iobregarg The "arg" value to pass to iobroker_register() + */ +extern int runcmd_open(const char *cmd, int *pfd, int *pfderr, char **env, + void (*iobreg)(int, int, void *), void *iobregarg) + __attribute__((__nonnull__(1, 2, 3, 5, 6))); + +/** + * Close a command and return its exit status + * @note Don't use this. It's a retarded way to reap children suitable + * only for launching a one-shot program. + * + * @param[in] fd The child's stdout filedescriptor + * @return exit-status of the child, or -1 in case of errors + */ +extern int runcmd_close(int fd); + +/** + * Convert a string to a vector of arguments like a shell would + * @note This might have bugs and is only tested to behave similar + * to how /bin/sh does things. For csh or other non bash-ish shells + * there are no guarantees. + * @note The out_argv array has to be large enough to hold all strings + * found in the command. + * @param[in] str The string to convert to an argument vector + * @param[out] out_argc The number of arguments found + * @param[out] out_argv The argument vector + * @return 0 on (great) success, or a bitmask of failure-codes + * representing f.e. unclosed quotes, job control or output redirection. + * See the RUNCMD_HAS_* and their ilk to find out about the flag. + */ +extern int runcmd_cmd2strv(const char *str, int *out_argc, char **out_argv); + +/** + * If you're using libnagios to execute a remote command, the + * static pid_t pids is not freed after runcmd_open + * You can call this function when you're sure pids is no longer + * in use, to keep down memory leaks + */ +extern void runcmd_free_pids(void); + +/** @} */ +/* INCLUDE_runcmd_h__ */ +#endif diff --git a/common/skiplist.c b/lib/skiplist.c similarity index 94% rename from common/skiplist.c rename to lib/skiplist.c index 02bfaf3..247ca89 100644 --- a/common/skiplist.c +++ b/lib/skiplist.c @@ -2,8 +2,6 @@ * * SKIPLIST.C - Skiplist functions for use in Nagios event/object lists * - * Copyright (c) 2008 Ethan Galstad - * Last Modified: 02-28-2008 * * Notes: * @@ -33,11 +31,54 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ************************************************************************/ -#include "../include/config.h" -#include "../include/common.h" +#include +#include +#include "skiplist.h" -#include "../include/skiplist.h" +typedef struct skiplistnode_struct { + void *data; + struct skiplistnode_struct *forward[1]; /* this must be the last element of the struct, as we allocate # of elements during runtime*/ + } skiplistnode; + +struct skiplist_struct { + int current_level; + int max_levels; + float level_probability; + unsigned long items; + int allow_duplicates; + int append_duplicates; + int (*compare_function)(void *, void *); + skiplistnode *head; + }; + +unsigned long skiplist_num_items(skiplist *list) { + return list ? list->items : 0; + } + +static skiplistnode *skiplist_new_node(skiplist *list, int node_levels) { + skiplistnode *newnode = NULL; + register int x = 0; + + if(list == NULL) + return NULL; + + if(node_levels < 0 || node_levels > list->max_levels) + return NULL; + + /* allocate memory for node + variable number of level pointers */ + if((newnode = (skiplistnode *)malloc(sizeof(skiplistnode) + (node_levels * sizeof(skiplistnode *))))) { + + /* initialize forward pointers */ + for(x = 0; x < node_levels; x++) + newnode->forward[x] = NULL; + + /* initialize data pointer */ + newnode->data = NULL; + } + + return newnode; + } skiplist *skiplist_new(int max_levels, float level_probability, int allow_duplicates, int append_duplicates, int (*compare_function)(void *, void *)) { @@ -63,6 +104,23 @@ skiplist *skiplist_new(int max_levels, float level_probability, int allow_duplic } +static int skiplist_random_level(skiplist *list) { + int level = 0; + float r = 0.0; + + if(list == NULL) + return -1; + + for(level = 0; level < list->max_levels; level++) { + r = ((float)rand() / (float)RAND_MAX); + if(r > list->level_probability) + break; + } + + return (level >= list->max_levels) ? list->max_levels - 1 : level; + } + + int skiplist_insert(skiplist *list, void *data) { skiplistnode **update = NULL; skiplistnode *thisnode = NULL; @@ -75,13 +133,6 @@ int skiplist_insert(skiplist *list, void *data) { return SKIPLIST_ERROR_ARGS; } - /* initialize update vector */ - if((update = (skiplistnode **)malloc(sizeof(skiplistnode *) * list->max_levels)) == NULL) { - return SKIPLIST_ERROR_MEMORY; - } - for(x = 0; x < list->max_levels; x++) - update[x] = NULL; - /* check to make sure we don't have duplicates */ /* NOTE: this could made be more efficient */ if(list->allow_duplicates == FALSE) { @@ -89,6 +140,13 @@ int skiplist_insert(skiplist *list, void *data) { return SKIPLIST_ERROR_DUPLICATE; } + /* initialize update vector */ + if((update = (skiplistnode **)malloc(sizeof(skiplistnode *) * list->max_levels)) == NULL) { + return SKIPLIST_ERROR_MEMORY; + } + for(x = 0; x < list->max_levels; x++) + update[x] = NULL; + /* find proper position for insert, remember pointers with an update vector */ thisnode = list->head; for(level = list->current_level; level >= 0; level--) { @@ -110,7 +168,6 @@ int skiplist_insert(skiplist *list, void *data) { /* get a random level the new node should be inserted at */ level = skiplist_random_level(list); - /*printf("INSERTION LEVEL: %d\n",level);*/ /* we're adding a new level... */ if(level > list->current_level) { @@ -148,48 +205,6 @@ int skiplist_insert(skiplist *list, void *data) { -skiplistnode *skiplist_new_node(skiplist *list, int node_levels) { - skiplistnode *newnode = NULL; - register int x = 0; - - if(list == NULL) - return NULL; - - if(node_levels < 0 || node_levels > list->max_levels) - return NULL; - - /* allocate memory for node + variable number of level pointers */ - if((newnode = (skiplistnode *)malloc(sizeof(skiplistnode) + (node_levels * sizeof(skiplistnode *))))) { - - /* initialize forward pointers */ - for(x = 0; x < node_levels; x++) - newnode->forward[x] = NULL; - - /* initialize data pointer */ - newnode->data = NULL; - } - - return newnode; - } - - -int skiplist_random_level(skiplist *list) { - int level = 0; - float r = 0.0; - - if(list == NULL) - return -1; - - for(level = 0; level < list->max_levels; level++) { - r = ((float)rand() / (float)RAND_MAX); - if(r > list->level_probability) - break; - } - - return (level >= list->max_levels) ? list->max_levels - 1 : level; - } - - int skiplist_empty(skiplist *list) { skiplistnode *this = NULL; skiplistnode *next = NULL; @@ -392,14 +407,6 @@ void *skiplist_find_next(skiplist *list, void *data, void **node_ptr) { -/* delete (all) matching item(s) from list */ -int skiplist_delete(skiplist *list, void *data) { - - return skiplist_delete_all(list, data); - } - - - /* delete first matching item from list */ int skiplist_delete_first(skiplist *list, void *data) { skiplistnode **update = NULL; @@ -466,7 +473,7 @@ int skiplist_delete_first(skiplist *list, void *data) { /* delete all matching items from list */ -int skiplist_delete_all(skiplist *list, void *data) { +int skiplist_delete(skiplist *list, void *data) { int deleted = 0; int total_deleted = 0; diff --git a/lib/skiplist.h b/lib/skiplist.h new file mode 100644 index 0000000..17d49e7 --- /dev/null +++ b/lib/skiplist.h @@ -0,0 +1,162 @@ +/************************************************************************ + * + * SKIPLIST.H - Skiplist data structures and functions + * + * + * License: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + ************************************************************************/ + +#ifndef LIBNAGIOS_SKIPLIST_H_INCLUDED +#define LIBNAGIOS_SKIPLIST_H_INCLUDED +#include "lnag-utils.h" + +/** + * @file skiplist.h + * @brief Skiplist library functions + * + * http://en.wikipedia.org/wiki/Skiplist + * + * @{ + */ + +#define SKIPLIST_OK 0 /**< A ok */ +#define SKIPLIST_ERROR_ARGS 1 /**< Bad arguments */ +#define SKIPLIST_ERROR_MEMORY 2 /**< Memory error */ +#define SKIPLIST_ERROR_DUPLICATE 3 /**< Trying to insert non-unique item */ + +NAGIOS_BEGIN_DECL + +struct skiplist_struct; +typedef struct skiplist_struct skiplist; + +/** + * Return number of items currently in the skiplist + * @param list The list to investigate + * @return number of items in list + */ +unsigned long skiplist_num_items(skiplist *list); + +/** + * Create a new skiplist + * @param max_levels Number of "ups" we have. + * This Should be kept close to lg2 of the number of items to store. + * @param level_probability Ignored + * @param allow_duplicates Allow duplicates in this list + * @param append_duplicates Append rather than prepend duplicates + * @param compare_function Comparison function for data entries + * @return pointer to a new skiplist on success, NULL on errors + */ +skiplist *skiplist_new(int max_levels, float level_probability, int allow_duplicates, int append_duplicates, int (*compare_function)(void *, void *)); + +/** + * Insert an item into a skiplist + * @param list The list to insert to + * @param data The data to insert + * @return SKIPLIST_OK on success, or an error code + */ +int skiplist_insert(skiplist *list, void *data); + +/** + * Empty the skiplist of all data + * @param list The list to empty + * @return ERROR on failures. OK on success + */ +int skiplist_empty(skiplist *list); + +/** + * Free all nodes (but not all data) in a skiplist + * This is similar to skiplist_empty(), but also free()'s the head node + * @param list The list to free + * @return OK on success, ERROR on failures + */ +int skiplist_free(skiplist **list); + +/** + * Get the first item in the skiplist + * @param list The list to peek into + * @return The first item, or NULL if there is none + */ +void *skiplist_peek(skiplist *list); + +/** + * Pop the first item from the skiplist + * @param list The list to pop from + */ +void *skiplist_pop(skiplist *list); + +/** + * Get first node of skiplist + * @param list The list to search + * @param[out] node_ptr State variable for skiplist_get_next() + * @return The data-item of the first node on success, NULL on errors + */ +void *skiplist_get_first(skiplist *list, void **node_ptr); + +/** + * Get next item from node_ptr + * @param[out] node_ptr State variable primed from an earlier call to + * skiplist_get_first() or skiplist_get_next() + * @return The next data-item matching node_ptr on success, NULL on errors + */ +void *skiplist_get_next(void **node_ptr); + +/** + * Find first entry in skiplist matching data + * @param list The list to search + * @param data Comparison object used to search + * @param[out] node_ptr State variable for future lookups with + * skiplist_find_next() + * @return The first found data-item, of NULL if none could be found + */ +void *skiplist_find_first(skiplist *list, void *data, void **node_ptr); + +/** + * Find next entry in skiplist matching data + * @param list The list to search + * @param data The data to compare against + * @param[out] node_ptr State var primed from earlier call to + * skiplist_find_next() or skiplist_find_first() + * @return The next found data-item, or NULL if none could be found + */ +void *skiplist_find_next(skiplist *list, void *data, void **node_ptr); + +/** + * Delete all items matching 'data' from skiplist + * @param list The list to delete from + * @param data Comparison object used to find the real node + * @return OK on success, ERROR on errors + */ +int skiplist_delete(skiplist *list, void *data); + +/** + * Delete first item matching 'data' from skiplist + * @param list The list to delete from + * @param data Comparison object used to search the list + * @return OK on success, ERROR on errors. + */ +int skiplist_delete_first(skiplist *list, void *data); + +/** + * Delete a particular node from the skiplist + * @param list The list to search + * @param node_ptr The node to delete + * @return OK on success, ERROR on errors. + */ +int skiplist_delete_node(skiplist *list, void *node_ptr); + +NAGIOS_END_DECL +/* @} */ +#endif diff --git a/common/snprintf.c b/lib/snprintf.c similarity index 99% rename from common/snprintf.c rename to lib/snprintf.c index d7018eb..d327903 100644 --- a/common/snprintf.c +++ b/lib/snprintf.c @@ -77,7 +77,7 @@ * Fix incorrect zpadlen handling in fmtfp. * Thanks to Ollie Oldham for spotting it. * few mods to make it easier to compile the tests. - * addedd the "Ollie" test to the floating point ones. + * added the "Ollie" test to the floating point ones. * * Martin Pool (mbp@samba.org) April 2003 * Remove NO_CONFIG_H so that the test case can be built within a source @@ -551,7 +551,7 @@ static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args } } - /* retieve the format arguments */ + /* retrieve the format arguments */ for(pnum = 0; pnum < max_pos; pnum++) { int i; @@ -857,7 +857,7 @@ static void fmtint(char *buffer, size_t *currlen, size_t maxlen, spadlen = 0; } if(flags & DP_F_MINUS) - spadlen = -spadlen; /* Left Justifty */ + spadlen = -spadlen; /* Left Justify */ #ifdef DEBUG_SNPRINTF printf("zpad: %d, spad: %d, min: %d, max: %d, place: %d\n", @@ -1063,7 +1063,7 @@ static void fmtfp(char *buffer, size_t *currlen, size_t maxlen, if(padlen < 0) padlen = 0; if(flags & DP_F_MINUS) - padlen = -padlen; /* Left Justifty */ + padlen = -padlen; /* Left Justify */ if((flags & DP_F_ZERO) && (padlen > 0)) { if(signvalue) { diff --git a/lib/snprintf.h.in b/lib/snprintf.h.in new file mode 100644 index 0000000..bbe2736 --- /dev/null +++ b/lib/snprintf.h.in @@ -0,0 +1,6 @@ +/* -*- C -*- */ +#ifndef LIBNAGIOS_snprintf_h__ +#define LIBNAGIOS_snprintf_h__ +#undef HAVE_SNPRINTF +#undef NEED_VA_LIST +#endif diff --git a/lib/squeue.c b/lib/squeue.c new file mode 100644 index 0000000..643d3a1 --- /dev/null +++ b/lib/squeue.c @@ -0,0 +1,260 @@ +/** + * @file squeue.c + * @brief pqeue wrapper library + * + * This library wraps the libpqueue library and handles the boring + * parts for all manner of events that want to use it, while hiding + * the implementation details of the pqueue's binary heap from the + * callers. + * + * peek() is O(1) + * add(), pop() and remove() are O(lg n), although remove() is + * impossible unless caller maintains the pointer to the scheduled + * event. + */ + +#include +#include +#include +#include +#include +#include "squeue.h" +#include "pqueue.h" + +struct squeue_event { + unsigned int pos; + pqueue_pri_t pri; + struct timeval when; + void *data; +}; + +/* + * 21 bits has enough data for systems that can have the usec + * field of a struct timeval move into the 1-second range, but + * not enough to let them to (far) beyond 2. If the system libs + * are too buggy, we really can't save it. + * This little twiddling operation lets us use dates beyond + * 2038 on 64-bit systems, while retaining the fast priority + * comparisons. + */ +#define SQ_BITS 21 +static pqueue_pri_t evt_compute_pri(struct timeval *tv) +{ + pqueue_pri_t ret; + + /* keep weird compilers on 32-bit systems from doing wrong */ + if(sizeof(pqueue_pri_t) < 8) { + ret = tv->tv_sec; + ret += !!tv->tv_usec; + } else { + ret = tv->tv_sec; + ret <<= SQ_BITS; + ret |= tv->tv_usec & ((1 << SQ_BITS) - 1); + } + + return ret; +} + +static int sq_cmp_pri(pqueue_pri_t next, pqueue_pri_t cur) +{ + return next > cur; +} + +static unsigned long long sq_get_pri(void *a) +{ + return ((squeue_event *)a)->pri; +} + +static void sq_set_pri(void *a, pqueue_pri_t pri) +{ + ((squeue_event *)a)->pri = pri; +} + +static unsigned int sq_get_pos(void *a) +{ + return ((squeue_event *)a)->pos; +} + +static void sq_set_pos(void *a, unsigned int pos) +{ + ((squeue_event *)a)->pos = pos; +} + +const struct timeval *squeue_event_runtime(squeue_event *evt) +{ + if (evt) + return &evt->when; + return NULL; +} + +void *squeue_event_data(squeue_event *evt) +{ + if (evt) + return evt->data; + return NULL; +} + +squeue_t *squeue_create(unsigned int horizon) +{ + if (!horizon) + horizon = 127; /* makes pqueue allocate 128 elements */ + + return pqueue_init(horizon, sq_cmp_pri, sq_get_pri, sq_set_pri, sq_get_pos, sq_set_pos); +} + +squeue_event *squeue_add_tv(squeue_t *q, struct timeval *tv, void *data) +{ + squeue_event *evt; + + if (!q) + return NULL; + + evt = calloc(1, sizeof(*evt)); + if (!evt) + return NULL; + + /* we can't schedule events in the past */ + if (tv->tv_sec < time(NULL)) + tv->tv_sec = time(NULL); + evt->when.tv_sec = tv->tv_sec; + if (sizeof(evt->when.tv_sec) > 4) { + /* + * Only use bottom sizeof(pqueue_pri_t)-SQ_BITS bits on + * 64-bit systems, or we may get entries at the head + * of the queue are actually scheduled to run several + * hundred thousand years from now. + */ + evt->when.tv_sec &= (1ULL << ((sizeof(pqueue_pri_t) * 8) - SQ_BITS)) - 1; + } + evt->when.tv_usec = tv->tv_usec; + evt->data = data; + + evt->pri = evt_compute_pri(&evt->when); + + if (!pqueue_insert(q, evt)) + return evt; + + free(evt); + return NULL; +} + +squeue_event *squeue_add(squeue_t *q, time_t when, void *data) +{ + struct timeval tv; + + /* + * we fetch real microseconds first, so events with same + * timestamp get different priorities for FIFO ordering. + */ + gettimeofday(&tv, NULL); + tv.tv_sec = when; + + return squeue_add_tv(q, &tv, data); +} + +squeue_event *squeue_add_usec(squeue_t *q, time_t when, time_t usec, void *data) +{ + struct timeval tv; + tv.tv_sec = when; + tv.tv_usec = usec; + assert(usec < 1000000); + return squeue_add_tv(q, &tv, data); +} + +squeue_event *squeue_add_msec(squeue_t *q, time_t when, time_t msec, void *data) +{ + return squeue_add_usec(q, when, msec * 1000, data); +} + +void squeue_change_priority_tv(squeue_t *q, squeue_event *evt, struct timeval *tv) +{ + if (!q || !evt || !tv) return; + + evt->when.tv_sec = tv->tv_sec; + if (sizeof(evt->when.tv_sec) > 4) { + /* Only use bottom sizeof(pqueue_pri_t)-SQ_BITS bits on 64-bit systems, + * or we may get entries at the head of the queue are actually + * scheduled to run several hundred thousand years from now. */ + evt->when.tv_sec &= (1ULL << ((sizeof(pqueue_pri_t) * 8) - SQ_BITS)) - 1; + } + evt->when.tv_usec = tv->tv_usec; + + pqueue_change_priority(q, evt_compute_pri(&evt->when), evt); +} + +void *squeue_peek(squeue_t *q) +{ + squeue_event *evt = pqueue_peek(q); + if (evt) + return evt->data; + return NULL; +} + +void *squeue_pop(squeue_t *q) +{ + squeue_event *evt; + void *ptr = NULL; + + evt = pqueue_pop(q); + if (evt) { + ptr = evt->data; + free(evt); + } + return ptr; +} + +int squeue_remove(squeue_t *q, squeue_event *evt) +{ + int ret; + + if (!q || !evt) + return -1; + ret = pqueue_remove(q, evt); + if (evt) + free(evt); + + return ret; +} + +void squeue_destroy(squeue_t *q, int flags) +{ + unsigned int i; + + if (!q || pqueue_size(q) < 1) + return; + + /* + * Using two separate loops is a lot faster than + * doing 1 cmp+branch for every queued item + */ + if (flags & SQUEUE_FREE_DATA) { + for (i = 0; i < pqueue_size(q); i++) { + free(((squeue_event *)q->d[i + 1])->data); + free(q->d[i + 1]); + } + } else { + for (i = 0; i < pqueue_size(q); i++) { + free(q->d[i + 1]); + } + } + pqueue_free(q); +} + +unsigned int squeue_size(squeue_t *q) +{ + if (!q) + return 0; + return pqueue_size(q); +} + +int squeue_evt_when_is_after(squeue_event *evt, struct timeval *reftime) { + if(!evt) return -1; + + if((reftime->tv_sec > evt->when.tv_sec) || + ((reftime->tv_sec == evt->when.tv_sec) && + (reftime->tv_usec > evt->when.tv_usec))) { + return 1; + } + return 0; + +} diff --git a/lib/squeue.h b/lib/squeue.h new file mode 100644 index 0000000..9819c03 --- /dev/null +++ b/lib/squeue.h @@ -0,0 +1,170 @@ +#ifndef LIBNAGIOS_SQUEUE_H_INCLUDED +#define LIBNAGIOS_SQUEUE_H_INCLUDED +#include +#include +#include "pqueue.h" +/** + * @file squeue.h + * @brief Scheduling queue function declarations + * + * This library is based on the pqueue api, which implements a + * priority queue based on a binary heap, providing O(lg n) times + * for insert() and remove(), and O(1) time for peek(). + * @note There is no "find". Callers must maintain pointers to their + * scheduled events if they wish to be able to remove them. + * + * @{ + */ + +/* + * All opaque types here. + * The pqueue library can be useful on its own though, so we + * don't block that from user view. + */ +typedef pqueue_t squeue_t; +struct squeue_event; +typedef struct squeue_event squeue_event; + +/** + * Options for squeue_destroy()'s flag parameter + */ +#define SQUEUE_FREE_DATA (1 << 0) /** Call free() on all data pointers */ + +/** + * Get the scheduled runtime of this event + * @param[in] evt The event to get runtime of + * @return struct timeval on success, NULL on errors + */ +extern const struct timeval *squeue_event_runtime(squeue_event *evt); + +/** + * Get data of an squeue_event struct + * @param[in] evt The event to operate on + * @return The data object pointed to by the event + */ +extern void *squeue_event_data(squeue_event *evt); + +/** + * Creates a scheduling queue optimized for handling events within + * the given timeframe. Callers should take care to create a queue + * of a decent but not overly large size, as too small or too large + * a queue will impact performance negatively. A queue can hold any + * number of events. A good value for "horizon" would be the max + * seconds into the future one expects to schedule things, although + * with few scheduled items in that timeframe you'd be better off + * using a more narrow horizon. + * + * @param size Hint about how large this queue will get + * @return A pointer to a scheduling queue + */ +extern squeue_t *squeue_create(unsigned int size); + +/** + * Destroys a scheduling queue completely + * @param[in] q The doomed queue + * @param[in] flags Flags determining the the level of destruction + */ +extern void squeue_destroy(squeue_t *q, int flags); + +/** + * Enqueue an event with microsecond precision. + * It's up to the caller to keep the event pointer in case he/she + * wants to remove the event from the queue later. + * + * @param q The scheduling queue to add to + * @param tv When this event should occur + * @param data Pointer to any kind of data + * @return The complete scheduled event + */ +extern squeue_event *squeue_add_tv(squeue_t *q, struct timeval *tv, void *data); + +/** + * Adds an event to the scheduling queue. + * See notes for squeue_add_tv() for details + * + * @param q The scheduling queue to add to + * @param when The unix timestamp when this event is to occur + * @param data Pointer to any kind of data + * @return The complete scheduled event + */ +extern squeue_event *squeue_add(squeue_t *q, time_t when, void *data); + +/** + * Adds an event to the scheduling queue with millisecond precision + * See notes on squeue_add_tv() for details + * + * @param[in] q The scheduling queue to add to + * @param[in] when Unix timestamp when this event should occur + * @param[in] usec Millisecond of above this event should occur + * @param[in] data Pointer to any kind of data + * @return NULL on errors. squeue_event pointer on success + */ +extern squeue_event *squeue_add_usec(squeue_t *q, time_t when, time_t usec, void *data); + +/** + * Adds an event to the scheduling queue with millisecond precision + * See notes on squeue_add_tv() for details + * + * @param[in] q The scheduling queue to add to + * @param[in] when Unix timestamp when this event should occur + * @param[in] msec Millisecond of above this event should occur + * @param[in] data Pointer to any kind of data + * @return NULL on errors. squeue_event pointer on success + */ +extern squeue_event *squeue_add_msec(squeue_t *q, time_t when, time_t msec, void *data); + +/** + * Change an event's priority to a new time. + * + * @param q The scheduling queue holding the event. + * @param evt The event to reschedule. + * @param tv When the event should be rescheduled to. + */ +extern void squeue_change_priority_tv(squeue_t *q, squeue_event *evt, struct timeval *tv); + +/** + * Returns the data of the next scheduled event from the scheduling + * queue without removing it from the queue. + * + * @param q The scheduling queue to peek into + */ +extern void *squeue_peek(squeue_t *q); + +/** + * Pops the next scheduled event from the scheduling queue and + * returns the data for it. + * This is equivalent to squeue_peek() + squeue_pop() + * @note This causes the squeue_event to be free()'d. + * + * @param q The scheduling queue to pop from + */ +extern void *squeue_pop(squeue_t *q); + +/** + * Removes the given event from the scheduling queue + * @note This causes the associated squeue_event() to be free()'d. + * @param[in] q The scheduling queue to remove from + * @param[in] evt The event to remove + */ +extern int squeue_remove(squeue_t *q, squeue_event *evt); + +/** + * Returns the number of events in the scheduling queue. This + * function never fails. + * + * @param[in] q The scheduling queue to inspect + * @return number of events in the inspected queue + */ +extern unsigned int squeue_size(squeue_t *q); + + +/** + * Returns true if passed timeval is after the time for the event + * + * @param[in] evt The queue event to inspect + * @param[in] reftime The reference time to compare to the queue event time + * @return 1 if reftime > event time, 0 otherwise + */ +extern int squeue_evt_when_is_after(squeue_event *evt, struct timeval *reftime); +#endif +/** @} */ diff --git a/lib/t-utils.c b/lib/t-utils.c new file mode 100644 index 0000000..4e1c415 --- /dev/null +++ b/lib/t-utils.c @@ -0,0 +1,173 @@ +#include "t-utils.h" + +const char *cyan = "", *red = "", *green = "", *yellow = "", *reset = ""; +uint passed, failed, t_verbose = 0; +static uint t_depth; +static const char *indent_str = " "; + +/* can't be used when a or b has side-effects, but we don't care here */ +#define max(a, b) (a > b ? a : b) +#define min(a, b) (a < b ? a : b) +#define delta(a, b) ((max(a, b) - (min(a, b)))) + + +void t_reset(void) +{ + passed = failed = 0; +} + +void t_set_colors(int force) +{ + if (force == 1 || isatty(fileno(stdout))) { + cyan = CLR_CYAN; + red = CLR_RED; + yellow = CLR_YELLOW; + green = CLR_GREEN; + reset = CLR_RESET; + } +} + +static void t_indent(uint depth) +{ + uint i; + for (i = 0; i < depth; i++) { + printf("%s", indent_str); + } +} + +void t_start(const char *fmt, ...) +{ + va_list ap; + + t_indent(t_depth++); + va_start(ap, fmt); + printf("%s### ", cyan); + vfprintf(stdout, fmt, ap); + printf("%s\n", reset); + va_end(ap); +} + +int t_end(void) +{ + if (t_depth) + t_depth--; + if (!t_depth || failed) { + t_indent(t_depth); + printf("Test results: %s%u passed%s, %s%u failed%s\n", + green, passed, reset, failed ? red : "", failed, failed ? reset : ""); + } + + return failed ? EXIT_FAILURE : EXIT_SUCCESS; +} + +static int t_okv(int success, const char *fmt, va_list ap) +{ + passed += !!success; + failed += !success; + + if (fmt && (!success || t_verbose || (t_verbose = !!getenv("TEST_VERBOSE")))) { + t_indent(t_depth); + if (success) { + printf("%sPASS%s ", green, reset); + } else { + printf("%sFAIL%s ", red, reset); + } + vfprintf(stdout, fmt, ap); + putchar('\n'); + } + + return success; +} + +int t_ok(int success, const char *fmt, ...) +{ + va_list ap; + + if (fmt) { + va_start(ap, fmt); + t_okv(success, fmt, ap); + va_end(ap); + } + else + t_okv(success, NULL, NULL); + + return success; +} + +void t_pass(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + t_okv(TEST_PASS, fmt, ap); + va_end(ap); +} + +void t_fail(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + t_okv(TEST_FAIL, fmt, ap); + va_end(ap); +} + +void t_diag(const char *fmt, ...) +{ + if (fmt) { + va_list ap; + t_indent(t_depth + 1); + va_start(ap, fmt); + vfprintf(stdout, fmt, ap); + va_end(ap); + putchar('\n'); + } +} + +int ok_int(int a, int b, const char *name) +{ + if (a == b) { + t_pass("%s", name); + return TEST_PASS; + } + + t_fail("%s", name); + t_diag("%d != %d. delta: %d", a, b, delta(a, b)); + return TEST_FAIL; +} + +int ok_uint(uint a, uint b, const char *name) +{ + if (a == b) { + t_pass("%s", name); + return TEST_PASS; + } + + t_fail("%s", name); + t_diag("%u != %u. delta: %u", a, b, delta(a, b)); + return TEST_FAIL; +} + +int ok_str(const char *a, const char *b, const char *name) +{ + if ((!a && !b) || (a && b && !strcmp(a, b))) { + t_pass("%s", name); + return TEST_PASS; + } + + t_fail("%s", name); + t_diag("'%s' != '%s'", a, b); + return TEST_FAIL; +} + +void __attribute__((__noreturn__)) crash(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + fputc('\n', stderr); + + exit(1); +} diff --git a/lib/t-utils.h b/lib/t-utils.h new file mode 100644 index 0000000..1fa25de --- /dev/null +++ b/lib/t-utils.h @@ -0,0 +1,64 @@ +#ifndef NAGIOS_T_UTILS_H_INCLUDED +#define NAGIOS_T_UTILS_H_INCLUDED +#include +#include +#include +#include +#include + +#ifndef ARRAY_SIZE +# define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) +#endif + +#define TEST_PASS 1 +#define TEST_FAIL 0 + +#define CLR_RESET "\033[m" +#define CLR_BOLD "\033[1m" +#define CLR_RED "\033[31m" +#define CLR_GREEN "\033[32m" +#define CLR_BROWN "\033[33m" +#define CLR_YELLOW "\033[33m\033[1m" +#define CLR_BLUE "\033[34m" +#define CLR_MAGENTA "\033[35m" +#define CLR_CYAN "\033[36m" +#define CLR_BG_RED "\033[41m" +#define CLR_BRIGHT_RED "\033[31m\033[1m" +#define CLR_BRIGHT_GREEN "\033[32m\033[1m" +#define CLR_BRIGHT_BLUE "\033[34m\033[1m" +#define CLR_BRIGHT_MAGENTA "\033[35m\033[1m" +#define CLR_BRIGHT_CYAN "\033[36m\033[1m" + +extern const char *red, *green, *yellow, *cyan, *reset; +extern unsigned int passed, failed, t_verbose; + +#define CHECKPOINT() \ + do { \ + fprintf(stderr, "ALIVE @ %s:%s:%d\n", __FILE__, __func__, __LINE__); \ + } while(0) + +#define t_assert(expr) \ + +extern void t_set_colors(int force); +extern void t_start(const char *fmt, ...) + __attribute__((__format__(__printf__, 1, 2))); +extern void t_pass(const char *fmt, ...) + __attribute__((__format__(__printf__, 1, 2))); +extern void t_fail(const char *fmt, ...) + __attribute__((__format__(__printf__, 1, 2))); +extern void t_diag(const char *fmt, ...) + __attribute__((__format__(__printf__, 1, 2))); +extern int t_ok(int success, const char *fmt, ...) + __attribute__((__format__(__printf__, 2, 3))); +#define test t_ok +#define t_req(expr) \ + if (!(expr)) \ + crash("No further testing is possible: " #expr " @%s:%d", __FILE__, __LINE__) +extern int ok_int(int a, int b, const char *name); +extern int ok_uint(unsigned int a, unsigned int b, const char *name); +extern int ok_str(const char *a, const char *b, const char *name); +extern int t_end(void); +extern void t_reset(void); +extern void crash(const char *fmt, ...) + __attribute__((__format__(__printf__, 1, 2), __noreturn__)); +#endif diff --git a/lib/test-bitmap.c b/lib/test-bitmap.c new file mode 100644 index 0000000..0940e0e --- /dev/null +++ b/lib/test-bitmap.c @@ -0,0 +1,92 @@ +#include "t-utils.h" +#include "lnag-utils.h" +#include "bitmap.c" + +#define PRIME 2089 +int main(int argc, char **argv) +{ + bitmap *a = NULL, *b, *r_union, *r_diff, *r_symdiff, *r_intersect; + unsigned int i; + int sa[] = { 2, 3, 4, 1783, 1784, 1785 }; + int sb[] = { 1, 2, 3, 1784, 1785, 1786, 1790, 1791, 1792 }; + + t_set_colors(0); + t_start("bitmap tests"); + + /* + * intersect: 2, 3, 1784, 1785 + * union: 1, 2, 3, 4, 1783, 1784, 1785, 1786, 1790, 1791, 1792 + * diff A/B: 4, 1783 + * diff B/A: 1, 1786, 1790, 1791, 1792 + * symdiff: 1, 1783, 1786, 1790, 1791, 1792 + */ + + ok_int(bitmap_count_set_bits(a), 0, "counting set bits in null vector a"); + ok_int(bitmap_count_unset_bits(a), 0, "counting unset bits in null vector a"); + a = bitmap_create(PRIME); + b = bitmap_create(PRIME); + ok_int(bitmap_count_set_bits(b), 0, "counting set bits in empty vector b"); + ok_int(bitmap_count_unset_bits(b), bitmap_cardinality(b), "counting unset bits in empty vector b"); + + t_set_colors(0); + ok_int(bitmap_cardinality(a) > PRIME, 1, "bitmap cardinality test"); + for (i = 0; i < veclen(sa); i++) { + bitmap_set(a, sa[i]); + } + ok_int(bitmap_count_set_bits(a), veclen(sa), "counting set bits for a"); + + for (i = 0; i < veclen(sb); i++) { + ok_int(0, bitmap_isset(b, sb[i]), "checking unset bit"); + bitmap_set(b, sb[i]); + if (!ok_int(1, bitmap_isset(b, sb[i]), "set and isset should work")) + printf("sb[i]: %d\n", sb[i]); + } + if (!ok_int(bitmap_count_set_bits(b), veclen(sb), "counting set bits for b")) { + for (i = 0; i < PRIME; i++) { + if (bitmap_isset(b, i)) { + ; + } + } + } + + r_union = bitmap_union(a, b); + ok_int(bitmap_count_set_bits(r_union), 11, "bitmap union sets the right amount of bits"); + for (i = 0; i < veclen(sa); i++) { + ok_int(1, bitmap_isset(r_union, sa[i]), "union should have bits from a"); + } + for (i = 0; i < veclen(sb); i++) { + ok_int(1, bitmap_isset(r_union, sb[i]), "union should have bits from b"); + } + + r_diff = bitmap_diff(a, b); + ok_int(bitmap_count_set_bits(r_diff), 2, "diff must set right amount of bits"); + + r_symdiff = bitmap_symdiff(a, b); + ok_int(bitmap_count_set_bits(r_symdiff), 7, "symdiff must set right amount of bits"); + + r_intersect = bitmap_intersect(a, b); + ok_int(bitmap_count_set_bits(r_intersect), 4, "intersect must set right amount of bits"); + for (i = 0; i < veclen(sa); i++) { + if (bitmap_isset(a, sa[i]) && bitmap_isset(b, sa[i])) { + ok_int(bitmap_isset(r_intersect, sa[i]), 1, "intersect must have bits in both"); + } else { + ok_int(bitmap_isset(r_intersect, sa[i]), 0, "Intersect must not have bits in only one or none"); + } + } + + ok_int(bitmap_count_unset_bits(NULL), 0, "There are no unset bits in a NULL bitmap"); + ok_int(bitmap_count_set_bits(NULL), 0, "No set bits in a NULL map"); + + bitmap_set(a, 0); + ok_int(bitmap_isset(a, 0), 1, "bitmap_set()"); + bitmap_unset(a, 0); + ok_int(bitmap_isset(a, 0), 0, "bitmap_unset()"); + bitmap_set(a, 0); + bitmap_clear(a); + ok_int(bitmap_isset(a, 0), 0, "bitmap_clear()"); + ok_int(bitmap_count_unset_bits(a), bitmap_cardinality(a), "bitmap_clear() must clear all"); + ok_int(bitmap_count_set_bits(a), 0, "bitmap_clear() must clear all (part 2)"); + + t_end(); + return 0; +} diff --git a/lib/test-dkhash.c b/lib/test-dkhash.c new file mode 100644 index 0000000..967561e --- /dev/null +++ b/lib/test-dkhash.c @@ -0,0 +1,194 @@ +#include +#include +#include +#include "dkhash.c" +#include "t-utils.h" + +static struct { + char *k1, *k2; +} keys[] = { + { "nisse", "banan" }, + { "foo", "bar" }, + { "kalle", "penslar" }, + { "hello", "world" }, + { "test", "fnurg" }, + { "barsk", "nitfol" }, + { "andreas", "regerar" }, + { "Nagios", "rules" }, +}; + +static int removed; +static struct test_data { + int x, i, j; +} del; + +unsigned int dkhash_count_entries(dkhash_table *table) +{ + unsigned int i, count = 0; + + for (i = 0; i < table->num_buckets; i++) { + dkhash_bucket *bkt; + for (bkt = table->buckets[i]; bkt; bkt = bkt->next) + count++; + } + + return count; +} + +int dkhash_check_table(dkhash_table *t) +{ + return t ? t->entries - dkhash_count_entries(t) : 0; +} + +void dkhash_debug_print_table(dkhash_table *t, const char *name, int force) +{ + int delta = dkhash_check_table(t); + unsigned int count; + if (!delta && !force) + return; + + count = dkhash_count_entries(t); + printf("debug data for dkhash table '%s'\n", name); + printf(" entries: %u; counted: %u; delta: %d\n", + t->entries, count, delta); + printf(" added: %u; removed: %u; delta: %d\n", + t->added, t->removed, t->added - t->removed); +} +#define dkhash_debug_table(t, force) dkhash_debug_print_table(t, #t, force) + +static struct test_data *ddup(int x, int i, int j) +{ + struct test_data *d; + + d = malloc(sizeof(*d)); + d->x = x; + d->i = i; + d->j = j; + return d; +} + +struct dkhash_check { + uint entries, count, max, added, removed; + int ent_delta, addrm_delta; +}; + +static int del_matching(void *data) +{ + struct test_data *d = (struct test_data *)data; + + if (!memcmp(d, &del, sizeof(del))) { + removed++; + return DKHASH_WALK_REMOVE; + } + + return 0; +} + +int main(int argc, char **argv) +{ + dkhash_table *tx, *t; + unsigned int x; + int ret, r2; + struct test_data s; + char *p1, *p2; + char *strs[10]; + char tmp[32]; + + t_set_colors(0); + t_start("dkhash basic test"); + t = dkhash_create(512); + + p1 = strdup("a not-so secret value"); + dkhash_insert(t, "nisse", NULL, p1); + ok_int(dkhash_num_entries_max(t), 1, "Added one entry, so that's max"); + ok_int(dkhash_num_entries_added(t), 1, "Added one entry, so one added"); + ok_int(dkhash_table_size(t), 512, "Table must be sized properly"); + ok_int(dkhash_collisions(t), 0, "One entry, so zero collisions"); + p2 = dkhash_get(t, "nisse", NULL); + test(p1 == p2, "get should get what insert set"); + dkhash_insert(t, "kalle", "bananas", p1); + p2 = dkhash_get(t, "kalle", "bezinga"); + test(p1 != p2, "we should never get the wrong key"); + ok_int(2, dkhash_num_entries(t), "should be 2 entries after 2 inserts"); + p2 = dkhash_remove(t, "kalle", "bezinga"); + ok_int(2, dkhash_num_entries(t), "should be 2 entries after 2 inserts and 1 failed remove"); + ok_int(0, dkhash_num_entries_removed(t), "should be 0 removed entries after failed remove"); + p2 = dkhash_remove(t, "kalle", "bananas"); + test(p1 == p2, "dkhash_remove() should return removed data"); + ok_int(dkhash_num_entries(t), 1, "should be 1 entries after 2 inserts and 1 successful remove"); + p2 = dkhash_remove(t, "nisse", NULL); + test(p1 == p2, "dkhash_remove() should return removed data"); + ret = t_end(); + + t_reset(); + /* lots of tests below, so we shut up while they're running */ + t_verbose = 0; + + t_start("dkhash_walk_data() test"); + memset(&s, 0, sizeof(s)); + /* first we set up the dkhash-tables */ + tx = dkhash_create(16); + for (x = 0; x < ARRAY_SIZE(keys); x++) { + dkhash_insert(tx, keys[x].k1, NULL, ddup(x, 0, 0)); + dkhash_insert(tx, keys[x].k2, NULL, ddup(x, 0, 0)); + dkhash_insert(tx, keys[x].k1, keys[x].k2, ddup(x, 0, 0)); + s.x += 3; + ok_int(s.x, dkhash_num_entries(tx), "x table adding"); + } + + ok_int(s.x, dkhash_num_entries(tx), "x table done adding"); + + for (x = 0; x < ARRAY_SIZE(keys); x++) { + del.x = x; + del.i = del.j = 0; + + ok_int(s.x, dkhash_num_entries(tx), "x table pre-delete"); + s.x -= 3; + dkhash_walk_data(tx, del_matching); + ok_int(s.x, dkhash_num_entries(tx), "x table post-delete"); + } + + test(0 == dkhash_num_entries(tx), "x table post all ops"); + test(0 == dkhash_check_table(tx), "x table consistency post all ops"); + dkhash_debug_table(tx, 0); + r2 = t_end(); + ret = r2 ? r2 : ret; + + t_reset(); + for(x = 0; x < 10; x++) { + sprintf(tmp, "string %d", x); + strs[x] = strdup(tmp); + } + + t_start("dkhash single bucket add remove forward"); + + t = dkhash_create(1); + for(x = 0; x < 10; x++) { + dkhash_insert(t, strs[x], NULL, strs[x]); + } + for(x = 0; x < 10; x++) { + p1 = strs[x]; + p2 = dkhash_remove(t, p1, NULL); + test(p1 == p2, "remove should return a value"); + } + r2 = t_end(); + ret = r2 ? r2 : ret; + t_reset(); + + t_start("dkhash single bucket add remove backward"); + + t = dkhash_create(1); + for(x = 0; x < 10; x++) { + dkhash_insert(t, strs[x], NULL, strs[x]); + } + for(x = 9; x; x--) { + p1 = strs[x]; + p2 = dkhash_remove(t, p1, NULL); + test(p1 == p2, "remove should return a value"); + } + + dkhash_destroy(t); + + r2 = t_end(); + return r2 ? r2 : ret; +} diff --git a/lib/test-fanout.c b/lib/test-fanout.c new file mode 100644 index 0000000..59d5831 --- /dev/null +++ b/lib/test-fanout.c @@ -0,0 +1,106 @@ +#define _GNU_SOURCE 1 +#include +#include "fanout.c" +#include "t-utils.h" + +struct tcase { + unsigned long key; + unsigned long value; +}; + +static int destroyed; + +static void destructor(void *ptr) +{ + destroyed++; +} + +static void run_tests(int ntests, int fo_size) +{ + struct tcase *tc; + unsigned long last_ptr, *ptr; + int i, added = 0, removed = 0; + fanout_table *fo; + + last_ptr = ntests; + + fo = fanout_create(fo_size); + tc = calloc(ntests, sizeof(*tc)); + for (i = 0; i < ntests; i++) { + tc[i].value = i; + if (!fanout_add(fo, tc[i].key, &tc[i].value)) + added++; + } + ok_int(added, ntests, "Adding stuff must work"); + + while ((ptr = (unsigned long *)fanout_remove(fo, 0))) { + ok_int((int)*ptr, (int)last_ptr - 1, "Removing a bunch of them"); + removed++; + last_ptr = *ptr; + } + ok_int(added, removed, "Removing should work as well as adding"); + fanout_destroy(fo, destructor); + ok_int(destroyed, 0, "Expected no entries in destructor"); + + fo = fanout_create(fo_size); + for (i = 0; i < ntests; i++) { + tc[i].value = i; + if (!fanout_add(fo, tc[i].key, &tc[i].value)) + added++; + } + fanout_destroy(fo, destructor); + ok_int(destroyed, ntests, "Expected ntest entries in destructor"); + destroyed = 0; + free(tc); +} + +struct test_data { + unsigned long key; + char *name; +}; + +static fanout_table *fot; +static void pdest(void *arg_) +{ + struct test_data *td = (struct test_data *)arg_; + fanout_remove(fot, td->key); + free(td->name); + free(td); + destroyed++; +} + +int main(int argc, char **argv) +{ + unsigned long k; + t_set_colors(0); + t_start("fanout tests"); + struct test_data *td; + + run_tests(10, 64); + run_tests(512, 64); + run_tests(64, 64); + run_tests(511, 17); + + destroyed = 0; + fot = fanout_create(512); + ok_int(fanout_remove(fot, 12398) == NULL, 1, + "remove on empty table must yield NULL"); + ok_int(fanout_get(fot, 123887987) == NULL, 1, + "get on empty table must yield NULL"); + for (k = 0; k < 16385; k++) { + struct test_data *tdata = calloc(1, sizeof(*td)); + tdata->key = k; + asprintf(&tdata->name, "%lu", k); + fanout_add(fot, k, tdata); + } + td = fanout_get(fot, k - 1); + ok_int(td != NULL, 1, "get must get what add inserts"); + ok_int(fanout_remove(fot, k + 1) == NULL, 1, + "remove on non-inserted key must yield NULL"); + ok_int(fanout_get(fot, k + 1) == NULL, 1, + "get on non-inserted must yield NULL"); + fanout_destroy(fot, pdest); + ok_int((int)destroyed, (int)k, "destroy counter while free()'ing"); + + return t_end(); +} diff --git a/lib/test-iobroker.c b/lib/test-iobroker.c new file mode 100644 index 0000000..af09549 --- /dev/null +++ b/lib/test-iobroker.c @@ -0,0 +1,207 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "iobroker.c" +#include "t-utils.h" + +static iobroker_set *iobs; + +static char *msg[] = { + "Welcome to the echo service!\n", + "test msg nr 2", + "random piece of string\nwith\nlots\nof\nnewlines\n\n\n\n\0", + "another totally random message\n", + "and this one's from emma. She's alright, really", + NULL, +}; + +static int echo_service(int fd, int events, void *arg) +{ + char buf[1024]; + int len; + + len = read(fd, buf, sizeof(buf)); + if (len < 0) { + perror("read"); + iobroker_close(iobs, fd); + ok_int(iobroker_is_registered(iobs, fd), 0, "Closing must deregister"); + return 0; + } + /* zero read means we're disconnected */ + if (!len) { + iobroker_close(iobs, fd); + ok_int(iobroker_is_registered(iobs, fd), 0, "Closing must deregister"); + return 0; + } + + write(fd, buf, len); + + return 0; +} + +static int connected_handler(int fd, int events, void *arg) +{ + int *counter = (int *)arg; + int i; + + i = *counter; + + if (events == IOBROKER_POLLIN) { + char buf[1024]; + int len = read(fd, buf, sizeof(buf)); + + buf[len] = 0; + + test(len == (int)strlen(msg[i]), "len match for message %d", i); + test(!memcmp(buf, msg[i], len), "data match for message %d", i); + } + + i++; + + if (i < 0 || i >= (int)ARRAY_SIZE(msg)) { + fprintf(stderr, "i = %d in connected_handler(). What's up with that?\n", i); + return 0; + } + + if (!msg[i]) { + iobroker_close(iobs, fd); + return 0; + } + + write(fd, msg[i], strlen(msg[i])); + *counter = i; + + return 0; +} + +static int listen_handler(int fd, int events, void *arg) +{ + int sock; + struct sockaddr_in sain; + socklen_t addrlen; + + if (!arg || arg != iobs) { + printf("Argument passing seems to fail spectacularly\n"); + } + + addrlen = sizeof(sain); + //printf("listen_handler(%d, %d, %p) called\n", fd, events, arg); + sock = accept(fd, (struct sockaddr *)&sain, &addrlen); + if (sock < 0) { + perror("accept"); + return -1; + } + + write(sock, msg[0], strlen(msg[0])); + iobroker_register(iobs, sock, iobs, echo_service); + ok_int(iobroker_is_registered(iobs, sock), 1, "is_registered must be true"); + return 0; +} + +void sighandler(int sig) +{ + /* test failed */ + t_fail("Caught signal %d", sig); + exit(t_end()); +} + + +#define NUM_PROCS 500 +static int proc_counter[NUM_PROCS]; +static int conn_spam(struct sockaddr_in *sain) +{ + int i; +#ifdef HAVE_SIGACTION + struct sigaction sig_action; + + sig_action.sa_sigaction = NULL; + sig_action.sa_handler = SIG_IGN; + sigemptyset(&sig_action.sa_mask); + sig_action.sa_flags = 0; + sigaction(SIGPIPE, &sig_action, NULL); + sig_action.sa_handler = sighandler; + sigfillset(&sig_action.sa_mask); + sig_action.sa_flags = SA_NODEFER|SA_RESTART; + sigaction(SIGQUIT, &sig_action, NULL); + sigaction(SIGINT, &sig_action, NULL); +#else /* HAVE_SIGACTION */ + signal(SIGALRM, sighandler); + signal(SIGINT, sighandler); + signal(SIGPIPE, SIG_IGN); +#endif /* HAVE_SIGACTION */ + + alarm(20); + + for (i = 0; i < NUM_PROCS; i++) { + int fd, sockopt = 1; + + fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + (void)setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof(sockopt)); + proc_counter[i] = 0; + iobroker_register(iobs, fd, (void *)&proc_counter[i], connected_handler); + if (connect(fd, (struct sockaddr *)sain, sizeof(*sain))) { + perror("connect"); + } + iobroker_poll(iobs, -1); + } + return 0; +} + +int main(int argc, char **argv) +{ + int listen_fd, flags, sockopt = 1; + struct sockaddr_in sain; + int error; + const char *err_msg; + + t_set_colors(0); + t_start("iobroker ipc test"); + + error = iobroker_get_max_fds(NULL); + ok_int(error, IOBROKER_ENOSET, "test errors when passing null"); + + err_msg = iobroker_strerror(error); + test(err_msg && !strcmp(err_msg, iobroker_errors[(~error) + 1].string), "iobroker_strerror() returns the right string"); + + iobs = iobroker_create(); + error = iobroker_get_max_fds(iobs); + test(iobs && error >= 0, "max fd's for real iobroker set must be > 0"); + + listen_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + flags = fcntl(listen_fd, F_GETFD); + flags |= FD_CLOEXEC; + fcntl(listen_fd, F_SETFD, flags); + + (void)setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof(sockopt)); + + memset(&sain, 0, sizeof(sain)); + sain.sin_port = ntohs(9123); + sain.sin_family = AF_INET; + bind(listen_fd, (struct sockaddr *)&sain, sizeof(sain)); + listen(listen_fd, 128); + iobroker_register(iobs, listen_fd, iobs, listen_handler); + + if (argc == 1) + conn_spam(&sain); + + for (;;) { + iobroker_poll(iobs, -1); + if (iobroker_get_num_fds(iobs) <= 1) { + break; + } + } + + iobroker_close(iobs, listen_fd); + iobroker_destroy(iobs, 0); + + t_end(); + return 0; +} diff --git a/lib/test-iocache.c b/lib/test-iocache.c new file mode 100644 index 0000000..e2cabec --- /dev/null +++ b/lib/test-iocache.c @@ -0,0 +1,81 @@ +#include +#include +#include "iocache.c" +#include "t-utils.h" + +struct strcode { + char *str; + unsigned int len; +}; +#define ADDSTR(str) { str, sizeof(str) - 1 } +static int test_delimiter(const char *delim, unsigned int delim_len) +{ + struct strcode sc[] = { + ADDSTR("Charlie Chaplin"), + ADDSTR("Madonna Something something"), + ADDSTR("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla turpis augue, laoreet eleifend ultricies et, tincidunt non felis. Suspendisse vitae accumsan dolor. Vivamus posuere venenatis dictum. Integer hendrerit est eget turpis scelerisque porttitor. Donec ullamcorper sodales purus, sed bibendum odio porttitor sit amet. Donec pretium sem ac sapien iaculis feugiat. Quisque commodo consequat quam, ac cursus est sodales euismod. Sed nec massa felis, sit amet varius dui. Morbi fermentum varius tellus, eget tempus felis imperdiet quis. Praesent congue auctor ligula, a tempor ipsum malesuada at. Proin pharetra tempor adipiscing. Aenean egestas tellus vitae arcu sagittis non ultrices turpis cursus."), + ADDSTR("Emma Blomqvist"), + ADDSTR("Random message"), + ADDSTR("Random\0message\0with\0nuls\0embedded"), + { NULL, 0, }, + }; + int i; + iocache *ioc; + + ioc = iocache_create(512 * 1024); + if (!test(ioc != NULL, "iocache_create must work")) + crash("can't test with no available memory"); + + for (i = 0; sc[i].str; i++) { + memcpy(&ioc->ioc_buf[ioc->ioc_buflen], sc[i].str, sc[i].len); + ioc->ioc_buflen += sc[i].len; + memcpy(ioc->ioc_buf + ioc->ioc_buflen, delim, delim_len); + ioc->ioc_buflen += delim_len; + } + + for (i = 0; sc[i].str; i++) { + char *ptr; + unsigned long len; + int error = 0; + ptr = iocache_use_delim(ioc, delim, delim_len, &len); + t_req(ptr != NULL); + if (!ptr) { + printf("Null pointer. What weird shit is this??\n"); + exit(1); + } + test(len == sc[i].len, "len check, string %d, delim_len %d", i, delim_len); + test(!memcmp(ptr, sc[i].str, len), "memcmp() check, string %d, delim_len %d", i, delim_len); + if (error) { + printf("delim_len: %d. i: %d; len: %lu; sc[i].len: %d\n", + delim_len, i, len, sc[i].len); + printf("sc[i].str: %s\n", sc[i].str); + printf("ptr : %s\n", ptr); + printf("strlen(sc[i].str): %lu\n", (unsigned long)strlen(sc[i].str)); + printf("strlen(ptr) : %lu\n", (unsigned long)strlen(ptr)); + exit(1); + } + } + iocache_destroy(ioc); + return 0; +} + +int main(int argc, char **argv) +{ + unsigned int i; + struct strcode sc[] = { + ADDSTR("\n"), + ADDSTR("\0\0"), + ADDSTR("XXXxXXX"), + ADDSTR("LALALALALALALAKALASBALLE\n"), + }; + + t_set_colors(0); + t_start("iocache_use_delim() test"); + for (i = 0; i < ARRAY_SIZE(sc); i++) { + t_start("Testing delimiter of len %d", sc[i].len); + test_delimiter(sc[i].str, sc[i].len); + t_end(); + } + + return t_end(); +} diff --git a/lib/test-kvvec.c b/lib/test-kvvec.c new file mode 100644 index 0000000..633d1a2 --- /dev/null +++ b/lib/test-kvvec.c @@ -0,0 +1,154 @@ +#include +#include +#include +#include +#include "kvvec.c" +#include "t-utils.h" + +static int walking_steps, walks; + +static int walker(struct key_value *kv, void *discard) +{ + static struct kvvec *vec = (void *)1; + static int step; + + walking_steps++; + + if (vec != discard) { + walks++; + vec = (struct kvvec *)discard; + step = 0; + } + + if (discard && vec) { + t_ok(!kv_compare(&vec->kv[step], kv), "step %d on walk %d", + step, walks); + } + + step++; + + return 0; +} + +#define KVSEP '=' +#define PAIRSEP '\0' +#define OVERALLOC 2 + +static const char *test_data[] = { + "lala=trudeldudel", + "foo=bar", + "LOTS AND LOTS OF CAPS WITH SPACES=weird", + "key=value", + "something-random=pre-determined luls", + "string=with\nnewlines\n\n\nand\nlots\nof\nthem\ntoo\n", + "tabs= this and that and three in a row", + NULL, +}; + +static const char *pair_term_missing[] = { + "foo=bar;lul=bar;haha=lulu", + "foo=bar;lul=bar;haha=lulu;", + "hobbit=palace;gandalf=wizard1", + "hobbit=palace;gandalf=wizard1;", + "0=0;1=1;2=2;3=3;4=4", + "0=0;1=1;2=2;3=3;4=4;", + NULL, +}; + +static void add_vars(struct kvvec *kvv, const char **ary, int len) +{ + int i; + + for (i = 0; i < len && ary[i]; i++) { + char *arg = strdup(test_data[i]); + char *eq = strchr(arg, '='); + if (eq) { + *eq++ = 0; + } + kvvec_addkv(kvv, strdup(arg), eq ? strdup(eq) : NULL); + free(arg); + } +} + +int main(int argc, char **argv) +{ + int i, j; + struct kvvec *kvv, *kvv2, *kvv3; + struct kvvec_buf *kvvb, *kvvb2; + struct kvvec k = KVVEC_INITIALIZER; + + t_set_colors(0); + + t_start("key/value vector tests"); + kvv = kvvec_create(1); + ok_int(kvvec_capacity(kvv), 1, "capacity of one should be guaranteed"); + kvv2 = kvvec_create(1); + kvv3 = kvvec_create(1); + add_vars(kvv, test_data, 1239819); + add_vars(kvv, (const char **)argv + 1, argc - 1); + + kvvec_sort(kvv); + kvvec_foreach(kvv, NULL, walker); + + /* kvvec2buf -> buf2kvvec -> kvvec2buf -> buf2kvvec conversion */ + kvvb = kvvec2buf(kvv, KVSEP, PAIRSEP, OVERALLOC); + kvv3 = buf2kvvec(kvvb->buf, kvvb->buflen, KVSEP, PAIRSEP, KVVEC_COPY); + kvvb2 = kvvec2buf(kvv3, KVSEP, PAIRSEP, OVERALLOC); + + buf2kvvec_prealloc(kvv2, kvvb->buf, kvvb->buflen, KVSEP, PAIRSEP, KVVEC_ASSIGN); + kvvec_foreach(kvv2, kvv, walker); + + kvvb = kvvec2buf(kvv, KVSEP, PAIRSEP, OVERALLOC); + + test(kvv->kv_pairs == kvv2->kv_pairs, "pairs should be identical"); + + for (i = 0; i < kvv->kv_pairs; i++) { + struct key_value *kv1, *kv2; + kv1 = &kvv->kv[i]; + if (i >= kvv2->kv_pairs) { + t_fail("missing var %d in kvv2", i); + printf("[%s=%s] (%d+%d)\n", kv1->key, kv1->value, kv1->key_len, kv1->value_len); + continue; + } + kv2 = &kvv2->kv[i]; + if (!test(!kv_compare(kv1, kv2), "kv pair %d must match", i)) { + printf("%d failed: [%s=%s] (%d+%d) != [%s=%s (%d+%d)]\n", + i, + kv1->key, kv1->value, kv1->key_len, kv1->value_len, + kv2->key, kv2->value, kv2->key_len, kv2->value_len); + } + } + + test(kvvb2->buflen == kvvb->buflen, "buflens must match"); + test(kvvb2->bufsize == kvvb->bufsize, "bufsizes must match"); + + if (kvvb2->buflen == kvvb->buflen && kvvb2->bufsize == kvvb->bufsize && + !memcmp(kvvb2->buf, kvvb->buf, kvvb->bufsize)) + { + t_pass("kvvec -> buf -> kvvec conversion works flawlessly"); + } else { + t_fail("kvvec -> buf -> kvvec conversion failed :'("); + } + + free(kvvb->buf); + free(kvvb); + free(kvvb2->buf); + free(kvvb2); + kvvec_destroy(kvv, 1); + kvvec_destroy(kvv3, KVVEC_FREE_ALL); + + for (j = 0; pair_term_missing[j]; j++) { + buf2kvvec_prealloc(&k, strdup(pair_term_missing[j]), strlen(pair_term_missing[j]), '=', ';', KVVEC_COPY); + for (i = 0; i < k.kv_pairs; i++) { + struct key_value *kv = &k.kv[i]; + test(kv->key_len == kv->value_len, "%d.%d; key_len=%d; value_len=%d (%s = %s)", + j, i, kv->key_len, kv->value_len, kv->key, kv->value); + test(kv->value_len == (int)strlen(kv->value), + "%d.%d; kv->value_len(%d) == strlen(%s)(%d)", + j, i, kv->value_len, kv->value, (int)strlen(kv->value)); + } + } + + t_end(); + return 0; +} diff --git a/lib/test-nsutils.c b/lib/test-nsutils.c new file mode 100644 index 0000000..4605201 --- /dev/null +++ b/lib/test-nsutils.c @@ -0,0 +1,41 @@ +#define _GNU_SOURCE +#include +#include "nsutils.c" +#include "t-utils.h" +#include +#include + +int main(int argc, char **argv) +{ + struct timeval start, stop; + float f_delta; + int msec_delta; + char *s1; + const char *s2; + + t_set_colors(0); + t_verbose = 1; + t_start("tv_delta tests"); + + stop.tv_sec = start.tv_sec = time(NULL); + stop.tv_usec = 2500; + start.tv_usec = 0; + msec_delta = tv_delta_msec(&start, &stop); + t_ok(msec_delta == 2, "tv_delta_msec()"); + f_delta = tv_delta_f(&start, &stop) * 1000; + t_ok((double)f_delta == (double)2.5, "tv_delta_f() * 1000 is %.2f and should be 2.5", f_delta); + gettimeofday(&start, NULL); + memcpy(&stop, &start, sizeof(start)); + stop.tv_sec += 100; + + asprintf(&s1, "arg varg foo %d", 12); + s2 = mkstr("arg varg foo %d", 12); + ok_str(s1, s2, "mkstr() must build proper strings"); + if (real_online_cpus() > 0) { + t_pass("%d online cpus detected", real_online_cpus()); + } else { + t_fail("Can't determine the number of online cpus"); + } + + return t_end(); +} diff --git a/lib/test-runcmd.c b/lib/test-runcmd.c new file mode 100644 index 0000000..5d3f644 --- /dev/null +++ b/lib/test-runcmd.c @@ -0,0 +1,176 @@ +#define _GNU_SOURCE +#include "runcmd.c" +#include "t-utils.h" +#include + +#define BUF_SIZE 1024 + +#if defined(__sun) && defined(__SVR4) +/* Assume we have GNU echo from OpenCSW at this location on Solaris. */ +#define ECHO_COMMAND "/opt/csw/gnu/echo" +#else +/* Otherwise we'll try to get away with a default. This is GNU echo on Leenooks. */ +#define ECHO_COMMAND "/bin/echo" +#endif + + +struct { + char *input; + char *output; +} cases[] = { + {"test0\\", "test0"}, + {"te\\st1", "test1"}, + {"te\\\\st2", "te\\st2"}, + {"te\\\\\\st3", "te\\st3"}, + {"te\\\\\\\\st4", "te\\\\st4"}, + + {"\"te\\st5\"", "te\\st5"}, + {"\"te\\\\st6\"", "te\\st6"}, + {"\"te\\\\\\st7\"", "te\\\\st7"}, + {"\"te\\\\\\\\st8\"", "te\\\\st8"}, + + {"'te\\st9'", "te\\st9"}, + {"'te\\\\st10'", "te\\\\st10"}, + {"'te\\\\\\st11'", "te\\\\\\st11"}, + {"'te\\\\\\\\st12'", "te\\\\\\\\st12"}, + + {"\\'te\\\\st13", "'te\\st13"}, + {"'test14\"'", "test14\""}, + {"\"\\\\test\"", "\\test"}, + {NULL, NULL}, +}; + +struct { + int ret; + char *cmd; +} anomaly[] = { + { RUNCMD_HAS_REDIR, "cat lala | grep foo" }, + { 0, "cat lala \\| grep foo" }, + { RUNCMD_HAS_REDIR, "cat lala > foo" }, + { 0, "cat lala \\> foo" }, + { RUNCMD_HAS_REDIR, "cat lala >> foo" }, + { 0, "cat lala \\>\\> foo" }, + { RUNCMD_HAS_REDIR, "something < bar" }, + { 0, "something \\< bar" }, + { RUNCMD_HAS_JOBCONTROL, "foo && bar" }, + { 0, "foo \\&\\& bar" }, + { RUNCMD_HAS_JOBCONTROL, "foo & bar" }, + { 0, "foo \\& bar" }, + { RUNCMD_HAS_JOBCONTROL, "lala foo ; bar" }, + { 0, "lala 'foo; bar'" }, + { RUNCMD_HAS_SUBCOMMAND, "foo \"`extcmd1`\"" }, + { 0, "foo \"\\`extcmd1\\`\"" }, + { RUNCMD_HAS_SUBCOMMAND, "foo `extcmd2`" }, + { 0, "foo \\`extcmd2\\`" }, + { RUNCMD_HAS_SUBCOMMAND, "foo \"$(extcmd3)\"" }, + { 0, "foo \\$\\(extcmd3\\)" }, + { RUNCMD_HAS_SUBCOMMAND | RUNCMD_HAS_PAREN, "foo $(extcmd4" }, + { 0, "foo \\$\\(extcmd4\\)" }, + { RUNCMD_HAS_UBDQ, "foo\" bar" }, + { 0, "foo\\\" bar" }, + { RUNCMD_HAS_UBSQ, "foo' bar" }, + { 0, "foo\\' bar" }, + { RUNCMD_HAS_WILDCARD, "ls -l /tmp/*" }, + { 0, "ls -l /tmp/\\*" }, + { RUNCMD_HAS_WILDCARD, "ls -l /dev/tty?" }, + { 0, "ls -l /dev/tty\\?" }, + { RUNCMD_HAS_SHVAR, "echo $foo" }, + { 0, "echo \\$foo" }, + { RUNCMD_HAS_PAREN, "\\$(hoopla booyaka" }, + { 0, "\\$\\(hoopla booyaka" }, + { RUNCMD_HAS_JOBCONTROL, "a&a&a&a&a&a&a&a&a&a&a&a&a&a&a&a&a&a&a&a&a&a&a"}, + { 0, "a\\&a\\&a\\&a\\&a\\&a\\&a\\&a\\&a\\&a\\&a\\&a\\&a\\&a\\&a\\&a\\&a\\&a\\&a\\&a\\&a\\&a\\&a"}, + { 0, NULL}, +}; + +struct { + int ret; + char *cmd; + int argc_exp; + char *argv_exp[10]; +} parse_case[] = { + { 0, "foo bar nisse", 3, { "foo", "bar", "nisse", NULL }}, + { 0, "foo\\ bar nisse", 2, { "foo bar", "nisse", NULL }}, + { 0, "\"\\\\foo\"", 1, { "\\foo", NULL }}, + { 0, "\"\\1bs in dq\"", 1, { "\\1bs in dq", NULL }}, + { 0, "\"\\\\2bs in dq\"", 1, { "\\2bs in dq", NULL }}, + { 0, "\"\\\\\\3bs in dq\"", 1, { "\\\\3bs in dq", NULL }}, + { 0, "\"\\\\\\\\4bs in dq\"", 1, { "\\\\4bs in dq", NULL }}, + { 0, "\\ \t \\\t \\ ", 3, { " ", "\t", " ", NULL }}, + { 0, "\\$foo walla wonga", 3, { "$foo", "walla", "wonga", NULL }}, + { 0, "\"\\$bar is\" very wide open", 4, { "$bar is", "very", "wide", "open", NULL }}, + { 0, "VAR=VAL some command", 3, { "VAR=VAL", "some", "command", NULL}}, + { RUNCMD_HAS_SHVAR, "VAR=VAL some use of $VAR", 5, { "VAR=VAL", "some", "use", "of", "$VAR", NULL}}, + { RUNCMD_HAS_SHVAR, "VAR=$VAL some use of $VAR", 5, { "VAR=$VAL", "some", "use", "of", "$VAR", NULL}}, + { RUNCMD_HAS_SHVAR | RUNCMD_HAS_WILDCARD, "VAR=\"$VAL\" a wilder\\ command*", 3, { "VAR=$VAL", "a", "wilder command*", NULL}}, + { 0, NULL, 0, { NULL, NULL, NULL }}, +}; + +/* We need an iobreg callback to pass to runcmd_open(). */ +static void stub_iobreg(int fdout, int fderr, void *arg) { } + +int main(int argc, char **argv) +{ + int ret, r2; + + runcmd_init(); + t_set_colors(0); + t_start("exec output comparison"); + { + int i; + char *out = calloc(1, BUF_SIZE); + for (i = 0; cases[i].input != NULL; i++) { + memset(out, 0, BUF_SIZE); + int pfd[2] = {-1, -1}, pfderr[2] = {-1, -1}; + /* We need a stub iobregarg since runcmd_open()'s prototype + * declares it attribute non-null. */ + int stub_iobregarg = 0; + int fd; + char *cmd; + asprintf(&cmd, ECHO_COMMAND " -n %s", cases[i].input); + fd = runcmd_open(cmd, pfd, pfderr, NULL, stub_iobreg, &stub_iobregarg); + free(cmd); + read(pfd[0], out, BUF_SIZE); + ok_str(cases[i].output, out, "Echoing a command should give expected output"); + close(pfd[0]); + close(pfderr[0]); + close(fd); + } + free(out); + } + ret = t_end(); + t_reset(); + t_start("anomaly detection"); + { + int i; + for (i = 0; anomaly[i].cmd; i++) { + int out_argc; + char *out_argv[256]; + int result = runcmd_cmd2strv(anomaly[i].cmd, &out_argc, out_argv); + ok_int(result, anomaly[i].ret, anomaly[i].cmd); + if (out_argv[0]) free(out_argv[0]); + } + } + r2 = t_end(); + ret = r2 ? r2 : ret; + t_reset(); + t_start("argument splitting"); + { + int i; + for (i = 0; parse_case[i].cmd; i++) { + int x, out_argc; + char *out_argv[256]; + int result = runcmd_cmd2strv(parse_case[i].cmd, &out_argc, out_argv); + /*out_argv[out_argc] = NULL;*//* This must be NULL terminated already. */ + ok_int(result, parse_case[i].ret, parse_case[i].cmd); + ok_int(out_argc, parse_case[i].argc_exp, parse_case[i].cmd); + for (x = 0; x < parse_case[x].argc_exp && out_argv[x]; x++) { + ok_str(parse_case[i].argv_exp[x], out_argv[x], "argv comparison test"); + } + if (out_argv[0]) free(out_argv[0]); + } + } + + r2 = t_end(); + return r2 ? r2 : ret; +} diff --git a/lib/test-squeue.c b/lib/test-squeue.c new file mode 100644 index 0000000..dd6c409 --- /dev/null +++ b/lib/test-squeue.c @@ -0,0 +1,179 @@ +/* + * we include the c source file to get at the opaque types and + * api functions + */ +#include +#include +#include +#include +#include +#include +#include +#include "squeue.c" +#include "t-utils.h" + +static void squeue_foreach(squeue_t *q, int (*walker)(squeue_event *, void *), void *arg) +{ + squeue_t *dup; + void *e, *dup_d; + + dup = squeue_create(q->size); + dup_d = dup->d; + memcpy(dup, q, sizeof(*q)); + dup->d = dup_d; + memcpy(dup->d, q->d, (q->size * sizeof(void *))); + + while ((e = pqueue_pop(dup))) { + walker(e, arg); + } + squeue_destroy(dup, 0); +} + +#define t(expr, args...) \ + do { \ + if ((expr)) { \ + t_pass(#expr); \ + } else { \ + t_fail(#expr " @%s:%d", __FILE__, __LINE__); \ + } \ + } while(0) + +typedef struct sq_test_event { + unsigned long id; + squeue_event *evt; +} sq_test_event; + +static time_t sq_high = 0; +static int sq_walker(squeue_event *evt, void *arg) +{ + static int walks = 0; + + walks++; + t(sq_high <= evt->when.tv_sec, "sq_high: %lu; evt->when: %lu\n", + sq_high, evt->when.tv_sec); + sq_high = (unsigned long)evt->when.tv_sec; + + return 0; +} + +#define EVT_ARY 65101 +static int sq_test_random(squeue_t *sq) +{ + unsigned long size, i; + unsigned long long numbers[EVT_ARY], *d, max = 0; + struct timeval now; + + size = squeue_size(sq); + now.tv_sec = time(NULL); + srand((int)now.tv_sec); + for (i = 0; i < EVT_ARY; i++) { + now.tv_usec = (time_t)rand(); + squeue_add_tv(sq, &now, &numbers[i]); + numbers[i] = evt_compute_pri(&now); + t(squeue_size(sq) == i + 1 + size); + } + + t(pqueue_is_valid(sq)); + + /* + * make sure we pop events in increasing "priority", + * since we calculate priority based on time and later + * is lower prio + */ + for (i = 0; i < EVT_ARY; i++) { + d = (unsigned long long *)squeue_pop(sq); + t(max <= *d, "popping randoms. i: %lu; delta: %lld; max: %llu; *d: %llu\n", + i, max - *d, max, *d); + max = *d; + t(squeue_size(sq) == size + (EVT_ARY - i - 1)); + } + t(pqueue_is_valid(sq)); + + return 0; +} + +int main(int argc, char **argv) +{ + squeue_t *sq; + struct timeval tv; + sq_test_event a, b, c, d, *x; + + t_set_colors(0); + t_start("squeue tests"); + + a.id = 1; + b.id = 2; + c.id = 3; + d.id = 4; + + gettimeofday(&tv, NULL); + /* Order in is a, b, c, d, but we should get b, c, d, a out. */ + srand(tv.tv_usec ^ tv.tv_sec); + t((sq = squeue_create(1024)) != NULL); + t(squeue_size(sq) == 0); + + /* we fill and empty the squeue completely once before testing */ + sq_test_random(sq); + t(squeue_size(sq) == 0, "Size should be 0 after first sq_test_random"); + + t((a.evt = squeue_add(sq, time(NULL) + 9, &a)) != NULL); + t(squeue_size(sq) == 1); + t((b.evt = squeue_add(sq, time(NULL) + 3, &b)) != NULL); + t(squeue_size(sq) == 2); + t((c.evt = squeue_add_msec(sq, time(NULL) + 5, 0, &c)) != NULL); + t(squeue_size(sq) == 3); + t((d.evt = squeue_add_usec(sq, time(NULL) + 5, 1, &d)) != NULL); + t(squeue_size(sq) == 4); + + /* add and remove lots. remainder should be what we have above */ + sq_test_random(sq); + + /* testing squeue_peek() */ + t((x = (sq_test_event *)squeue_peek(sq)) != NULL); + t(x == &b, "x: %p; a: %p; b: %p; c: %p; d: %p\n", x, &a, &b, &c, &d); + t(x->id == b.id); + t(squeue_size(sq) == 4); + + /* testing squeue_remove() and re-add */ + t(squeue_remove(sq, b.evt) == 0); + t(squeue_size(sq) == 3); + t((x = squeue_peek(sq)) != NULL); + t(x == &c); + t((b.evt = squeue_add(sq, time(NULL) + 3, &b)) != NULL); + t(squeue_size(sq) == 4); + + /* peek should now give us the &b event (again) */ + t((x = squeue_peek(sq)) != NULL); + if (x != &b) { + printf("about to fail pretty fucking hard...\n"); + printf("ea: %p; &b: %p; &c: %p; ed: %p; x: %p\n", + &a, &b, &c, &d, x); + } + t(x == &b); + t(x->id == b.id); + t(squeue_size(sq) == 4); + + /* testing squeue_pop(), lifo manner */ + t((x = squeue_pop(sq)) != NULL); + t(squeue_size(sq) == 3, + "squeue_size(sq) = %d\n", squeue_size(sq)); + t(x == &b, "x: %p; &b: %p\n", x, &b); + t(x->id == b.id, "x->id: %lu; d.id: %lu\n", x->id, d.id); + + /* Test squeue_pop() */ + t((x = squeue_pop(sq)) != NULL); + t(squeue_size(sq) == 2); + t(x == &c, "x->id: %lu; c.id: %lu\n", x->id, c.id); + t(x->id == c.id, "x->id: %lu; c.id: %lu\n", x->id, c.id); + + /* this should fail gracefully (-1 return from squeue_remove()) */ + t(squeue_remove(NULL, NULL) == -1); + t(squeue_remove(NULL, a.evt) == -1); + + squeue_foreach(sq, sq_walker, NULL); + + /* clean up to prevent false valgrind positives */ + squeue_destroy(sq, 0); + + return t_end(); +} diff --git a/lib/worker.c b/lib/worker.c new file mode 100644 index 0000000..6afc20c --- /dev/null +++ b/lib/worker.c @@ -0,0 +1,873 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "libnagios.h" + +#define MSG_DELIM "\1\0\0" /**< message limiter - note this ends up being + \1\0\0\0 on the wire as "" strings null-terminate */ +#define MSG_DELIM_LEN (sizeof(MSG_DELIM)) /**< message delimiter length - 4, not 3 */ +#define PAIR_SEP 0 /**< pair separator for buf2kvvec() and kvvec2buf() */ +#define KV_SEP '=' /**< key/value separator for buf2kvvec() and kvvec2buf() */ + +struct execution_information { + squeue_event *sq_event; + pid_t pid; + int state; + struct timeval start; + struct timeval stop; + float runtime; + struct rusage rusage; +}; + +static iobroker_set *iobs; +static squeue_t *sq; +static unsigned int started, running_jobs, timeouts, reapable; +static int master_sd; +static int parent_pid; +static fanout_table *ptab; + +static void exit_worker(int code, const char *msg) +{ + child_process *cp; + int discard; +#ifdef HAVE_SIGACTION + struct sigaction sig_action; +#endif + + if (msg) { + perror(msg); + } + + /* + * We must kill our children, so let's embark on that + * large scale filicide. Each process should be in a + * process group of its own, so we can signal not only + * the plugin but also all of its children. + */ +#ifdef HAVE_SIGACTION + sig_action.sa_sigaction = NULL; + sig_action.sa_handler = SIG_IGN; + sigemptyset(&sig_action.sa_mask); + sig_action.sa_flags = 0; + sigaction(SIGTERM, &sig_action, NULL); + sigaction(SIGSEGV, &sig_action, NULL); +#else + signal(SIGTERM, SIG_IGN); + signal(SIGSEGV, SIG_IGN); +#endif + kill(0, SIGTERM); + while (waitpid(-1, &discard, WNOHANG) > 0) + ; /* do nothing */ + sleep(1); + while ((cp = (child_process *)squeue_pop(sq))) { + /* kill all processes in the child's process group */ + (void)kill(-cp->ei->pid, SIGKILL); + } + sleep(1); + while (waitpid(-1, &discard, WNOHANG) > 0) + ; /* do nothing */ + + exit(code); +} + +/* + * write a log message to master. + * Note that this will break if we change delimiters someday, + * but avoids doing several extra malloc()+free() for this + * pretty simple case. + */ +__attribute__((__format__(__printf__, 1, 2))) +static void wlog(const char *fmt, ...) +{ +#define LOG_KEY_LEN 4 + static char lmsg[8192] = "log="; + int len; + va_list ap; + + va_start(ap, fmt); + len = vsnprintf(lmsg + LOG_KEY_LEN, sizeof(lmsg) - LOG_KEY_LEN - MSG_DELIM_LEN, fmt, ap); + va_end(ap); + if (len < 0) { + /* We can't send what we can't print. */ + return; + } + + len += LOG_KEY_LEN; /* log= */ + if (len > sizeof(lmsg) - MSG_DELIM_LEN - 1) { + /* A truncated log is better than no log or buffer overflows. */ + len = sizeof(lmsg) - MSG_DELIM_LEN - 1; + } + + /* Add the kv pair separator and the message delimiter. */ + lmsg[len] = 0; + len++; + memcpy(lmsg + len, MSG_DELIM, MSG_DELIM_LEN); + len += MSG_DELIM_LEN; + + if (write(master_sd, lmsg, len) < 0 && errno == EPIPE) { + /* Master has died or abandoned us, so exit. */ + exit_worker(1, "Failed to write() to master"); + } +} + +__attribute__((__format__(__printf__, 3, 4))) +static void job_error(child_process *cp, struct kvvec *kvv, const char *fmt, ...) +{ + char msg[4096]; + int len; + va_list ap; + + va_start(ap, fmt); + len = vsnprintf(msg, sizeof(msg), fmt, ap); + va_end(ap); + if (len < 0) { + /* We can't send what we can't print. */ + kvvec_destroy(kvv, 0); + return; + } + + if (len > sizeof(msg) - 1) { + /* A truncated log is better than no log or buffer overflows. */ + len = sizeof(msg) - 1; + } + msg[len] = 0; + + if (cp) { + kvvec_addkv(kvv, "job_id", mkstr("%d", cp->id)); + } + kvvec_addkv_wlen(kvv, "error_msg", 9, msg, len); + + if (worker_send_kvvec(master_sd, kvv) < 0 && errno == EPIPE) { + /* Master has died or abandoned us, so exit. */ + exit_worker(1, "Failed to send job error key/value vector to master"); + } + + kvvec_destroy(kvv, 0); +} + +struct kvvec_buf *build_kvvec_buf(struct kvvec *kvv) +{ + struct kvvec_buf *kvvb; + + /* + * key=value, separated by PAIR_SEP and messages + * delimited by MSG_DELIM + */ + kvvb = kvvec2buf(kvv, KV_SEP, PAIR_SEP, MSG_DELIM_LEN); + if (!kvvb) { + return NULL; + } + memcpy(kvvb->buf + (kvvb->bufsize - MSG_DELIM_LEN), MSG_DELIM, MSG_DELIM_LEN); + + return kvvb; +} + +int worker_send_kvvec(int sd, struct kvvec *kvv) +{ + int ret; + struct kvvec_buf *kvvb; + + kvvb = build_kvvec_buf(kvv); + if (!kvvb) + return -1; + + /* bufsize, not buflen, as it gets us the delimiter */ + /* ret = write(sd, kvvb->buf, kvvb->bufsize); */ + ret = nwrite(sd, kvvb->buf, kvvb->bufsize,NULL); + free(kvvb->buf); + free(kvvb); + + return ret; +} + +int send_kvvec(int sd, struct kvvec *kvv) +{ + return worker_send_kvvec(sd, kvv); +} + +char *worker_ioc2msg(iocache *ioc, unsigned long *size, int flags) +{ + return iocache_use_delim(ioc, MSG_DELIM, MSG_DELIM_LEN, size); +} + +int worker_buf2kvvec_prealloc(struct kvvec *kvv, char *buf, unsigned long len, int kvv_flags) +{ + return buf2kvvec_prealloc(kvv, buf, len, KV_SEP, PAIR_SEP, kvv_flags); +} + +#define kvvec_add_long(kvv, key, value) \ + do { \ + const char *buf = mkstr("%ld", value); \ + kvvec_addkv_wlen(kvv, key, sizeof(key) - 1, buf, strlen(buf)); \ + } while (0) + +#define kvvec_add_tv(kvv, key, value) \ + do { \ + const char *buf = mkstr("%ld.%06ld", value.tv_sec, value.tv_usec); \ + kvvec_addkv_wlen(kvv, key, sizeof(key) - 1, buf, strlen(buf)); \ + } while (0) + +/* forward declaration */ +static void gather_output(child_process *cp, iobuf *io, int final); + +static void destroy_job(child_process *cp) +{ + /* + * we must remove the job's timeout ticker, + * or we'll end up accessing an already free()'d + * pointer, or the pointer to a different child. + */ + squeue_remove(sq, cp->ei->sq_event); + running_jobs--; + fanout_remove(ptab, cp->ei->pid); + + if (cp->outstd.buf) { + free(cp->outstd.buf); + cp->outstd.buf = NULL; + } + if (cp->outerr.buf) { + free(cp->outerr.buf); + cp->outerr.buf = NULL; + } + + if(NULL != cp->env) kvvec_destroy(cp->env, KVVEC_FREE_ALL); + kvvec_destroy(cp->request, KVVEC_FREE_ALL); + free(cp->cmd); + + free(cp->ei); + free(cp); +} + +#define strip_nul_bytes(io) \ + do { \ + char *nul; \ + if (!io.buf || !*io.buf) \ + io.len = 0; \ + else if ((nul = memchr(io.buf, 0, io.len))) { \ + io.len = (unsigned long)nul - (unsigned long)io.buf; \ + } \ + } while (0) + +int finish_job(child_process *cp, int reason) +{ + static struct kvvec resp = KVVEC_INITIALIZER; + struct rusage *ru = &cp->ei->rusage; + int i, ret; + + /* get rid of still open filedescriptors */ + if (cp->outstd.fd != -1) { + gather_output(cp, &cp->outstd, 1); + iobroker_close(iobs, cp->outstd.fd); + } + if (cp->outerr.fd != -1) { + gather_output(cp, &cp->outerr, 1); + iobroker_close(iobs, cp->outerr.fd); + } + + /* Make sure network-supplied data doesn't contain nul bytes */ + strip_nul_bytes(cp->outstd); + strip_nul_bytes(cp->outerr); + + /* how many key/value pairs do we need? */ + if (kvvec_init(&resp, 12 + cp->request->kv_pairs) == NULL) { + /* what the hell do we do now? */ + exit_worker(1, "Failed to init response key/value vector"); + } + + gettimeofday(&cp->ei->stop, NULL); + + if (running_jobs != squeue_size(sq)) { + wlog("running_jobs(%d) != squeue_size(sq) (%d)\n", + running_jobs, squeue_size(sq)); + wlog("started: %d; running: %d; finished: %d\n", + started, running_jobs, started - running_jobs); + } + + cp->ei->runtime = tv_delta_f(&cp->ei->start, &cp->ei->stop); + + /* + * Now build the return message. + * First comes the request, minus environment variables + */ + for (i = 0; i < cp->request->kv_pairs; i++) { + struct key_value *kv = &cp->request->kv[i]; + /* skip environment macros */ + if (kv->key_len == 3 && !strcmp(kv->key, "env")) { + continue; + } + kvvec_addkv_wlen(&resp, kv->key, kv->key_len, kv->value, kv->value_len); + } + kvvec_addkv(&resp, "wait_status", mkstr("%d", cp->ret)); + kvvec_add_tv(&resp, "start", cp->ei->start); + kvvec_add_tv(&resp, "stop", cp->ei->stop); + kvvec_addkv(&resp, "runtime", mkstr("%f", cp->ei->runtime)); + if (!reason) { + /* child exited nicely (or with a signal, so check wait_status) */ + kvvec_addkv(&resp, "exited_ok", "1"); + kvvec_add_tv(&resp, "ru_utime", ru->ru_utime); + kvvec_add_tv(&resp, "ru_stime", ru->ru_stime); + kvvec_add_long(&resp, "ru_minflt", ru->ru_minflt); + kvvec_add_long(&resp, "ru_majflt", ru->ru_majflt); + kvvec_add_long(&resp, "ru_inblock", ru->ru_inblock); + kvvec_add_long(&resp, "ru_oublock", ru->ru_oublock); + } else { + /* some error happened */ + kvvec_addkv(&resp, "exited_ok", "0"); + kvvec_addkv(&resp, "error_code", mkstr("%d", reason)); + } + kvvec_addkv_wlen(&resp, "outerr", 6, cp->outerr.buf, cp->outerr.len); + kvvec_addkv_wlen(&resp, "outstd", 6, cp->outstd.buf, cp->outstd.len); + ret = worker_send_kvvec(master_sd, &resp); + if (ret < 0 && errno == EPIPE) + exit_worker(1, "Failed to send kvvec struct to master"); + + return 0; +} + +static int check_completion(child_process *cp, int flags) +{ + int result, status; + + if (!cp || !cp->ei->pid) { + return 0; + } + + /* + * we mustn't let EINTR interrupt us, since it could well + * be a SIGCHLD from the properly exiting process doing it + */ + do { + errno = 0; + result = wait4(cp->ei->pid, &status, flags, &cp->ei->rusage); + } while (result < 0 && errno == EINTR); + + if (result == cp->ei->pid || (result < 0 && errno == ECHILD)) { + cp->ret = status; + finish_job(cp, 0); + destroy_job(cp); + return 0; + } + + if (!result) + return -1; + + return -errno; +} + +/* + * "What can the harvest hope for, if not for the care + * of the Reaper Man?" + * -- Terry Pratchett, Reaper Man + * + * We end up here no matter if the job is stale (ie, the child is + * stuck in uninterruptable sleep) or if it's the first time we try + * to kill it. + * A job is considered reaped once we reap our direct child, in + * which case init will become parent of our grandchildren. + * It's also considered fully reaped if kill() results in ESRCH or + * EPERM, or if wait()ing for the process group results in ECHILD. + */ +static void kill_job(child_process *cp, int reason) +{ + int ret, status, reaped = 0; + int pid = cp ? cp->ei->pid : 0; + + /* + * first attempt at reaping, so see if we just failed to + * notice that things were going wrong her + */ + if (reason == ETIME && !check_completion(cp, WNOHANG)) { + timeouts++; + wlog("job %d with pid %d reaped at timeout. timeouts=%u; started=%u", cp->id, pid, timeouts, started); + return; + } + + /* brutal but efficient */ + if (kill(-cp->ei->pid, SIGKILL) < 0) { + if (errno == ESRCH) { + reaped = 1; + } else { + wlog("kill(-%ld, SIGKILL) failed: %s\n", (long)cp->ei->pid, strerror(errno)); + } + } + + /* + * we must iterate at least once, in case kill() returns + * ESRCH when there's zombies + */ + do { + ret = waitpid(cp->ei->pid, &status, WNOHANG); + if (ret < 0 && errno == EINTR) + continue; + + if (ret == cp->ei->pid || (ret < 0 && errno == ECHILD)) { + reaped = 1; + break; + } + if (!ret) { + struct timeval tv; + + gettimeofday(&tv, NULL); + /* + * stale process (signal may not have been delivered, or + * the child can be stuck in uninterruptible sleep). We + * can't hang around forever, so just reschedule a new + * reap attempt later. + */ + if (reason == ESTALE) { + wlog("tv.tv_sec is currently %llu", (unsigned long long)tv.tv_sec); + tv.tv_sec += 5; + wlog("Failed to reap child with pid %ld. Next attempt @ %llu.%lu", (long)cp->ei->pid, (unsigned long long)tv.tv_sec, (unsigned long)tv.tv_usec); + } else { + tv.tv_usec = 250000; + if (tv.tv_usec > 1000000) { + tv.tv_usec -= 1000000; + tv.tv_sec += 1; + } + cp->ei->state = ESTALE; + finish_job(cp, reason); + } + squeue_remove(sq, cp->ei->sq_event); + cp->ei->sq_event = squeue_add_tv(sq, &tv, cp); + return; + } + } while (!reaped); + + if (cp->ei->state != ESTALE) + finish_job(cp, reason); + else + wlog("job %d (pid=%ld): Dormant child reaped", cp->id, (long)cp->ei->pid); + destroy_job(cp); +} + +static void gather_output(child_process *cp, iobuf *io, int final) +{ + int retry = 5; + + for (;;) { + char buf[4096]; + int rd; + + rd = read(io->fd, buf, sizeof(buf)); + if (rd < 0) { + if (errno == EAGAIN && !final) + break; + if (errno == EINTR || errno == EAGAIN) { + char buf[1024]; + if (--retry == 0) { + sprintf(buf, "job %d (pid=%ld): Failed to read(): %s", cp->id, (long)cp->ei->pid, strerror(errno)); + break; + } + sprintf(buf, "job %d (pid=%ld): read() returned error %d", cp->id, (long)cp->ei->pid, errno); + syslog(LOG_NOTICE, "%s", buf); + sleep(1); + continue; + } + if (!final && errno != EAGAIN) + wlog("job %d (pid=%ld): Failed to read(): %s", cp->id, (long)cp->ei->pid, strerror(errno)); + } + + if (rd > 0) { + /* we read some data */ + io->buf = realloc(io->buf, rd + io->len + 1); + memcpy(&io->buf[io->len], buf, rd); + io->len += rd; + io->buf[io->len] = '\0'; + } + + /* + * Close down on bad, zero and final reads (we don't get + * EAGAIN, so all errors are really unfixable) + */ + if (rd <= 0 || final) { + iobroker_close(iobs, io->fd); + io->fd = -1; + if (!final) + check_completion(cp, WNOHANG); + break; + } + + break; + } +} + + +static int stderr_handler(int fd, int events, void *cp_) +{ + child_process *cp = (child_process *)cp_; + gather_output(cp, &cp->outerr, 0); + return 0; +} + +static int stdout_handler(int fd, int events, void *cp_) +{ + child_process *cp = (child_process *)cp_; + gather_output(cp, &cp->outstd, 0); + return 0; +} + +static void sigchld_handler(int sig) +{ + reapable++; +} + +static void reap_jobs(void) +{ + int reaped = 0; + do { + int pid, status; + struct rusage ru; + pid = wait3(&status, WNOHANG, &ru); + if (pid > 0) { + struct child_process *cp; + + reapable--; + if (!(cp = fanout_get(ptab, pid))) { + /* we reaped a lost child. Odd that */ + continue; + } + cp->ret = status; + memcpy(&cp->ei->rusage, &ru, sizeof(ru)); + reaped++; + if (cp->ei->state != ESTALE) + finish_job(cp, cp->ei->state); + destroy_job(cp); + } + else if (!pid || (pid < 0 && errno == ECHILD)) { + reapable = 0; + } + } while (reapable); +} + +void cmd_iobroker_register(int fdout, int fderr, void *arg) { + /* We must never block, even if plugins issue '_exit()' */ + fcntl(fdout, F_SETFL, O_NONBLOCK); + fcntl(fderr, F_SETFL, O_NONBLOCK); + if( iobroker_register(iobs, fdout, arg, stdout_handler) < 0) { + wlog("Failed to register iobroker for stdout"); + } + if( iobroker_register(iobs, fderr, arg, stderr_handler) < 0) { + wlog("Failed to register iobroker for stderr"); + } +} + +char **env_from_kvvec(struct kvvec *kvv_env) { + + int i; + char **env; + + if(NULL == kvv_env) return NULL; + + env = calloc(kvv_env->kv_pairs*2+1, sizeof(char *)); + for (i = 0; i < kvv_env->kv_pairs; i++) { + struct key_value *kv = &kvv_env->kv[i]; + env[i*2] = kv->key; + env[i*2+1] = kv->value; + } + env[i*2] = NULL; + + return env; +} + +int start_cmd(child_process *cp) +{ + int pfd[2] = {-1, -1}, pfderr[2] = {-1, -1}; + + char **env = env_from_kvvec(cp->env); + + cp->outstd.fd = runcmd_open(cp->cmd, pfd, pfderr, env, + cmd_iobroker_register, cp); + my_free(env); + if (cp->outstd.fd < 0) { + return -1; + } + + cp->outerr.fd = pfderr[0]; + cp->ei->pid = runcmd_pid(cp->outstd.fd); + /* no pid means we somehow failed */ + if (!cp->ei->pid) { + return -1; + } + + fanout_add(ptab, cp->ei->pid, cp); + + return 0; +} + +static iocache *ioc; + +static child_process *parse_command_kvvec(struct kvvec *kvv) +{ + int i; + child_process *cp; + + /* get this command's struct and insert it at the top of the list */ + cp = calloc(1, sizeof(*cp)); + if (!cp) { + wlog("Failed to calloc() a child_process struct"); + return NULL; + } + cp->ei = calloc(1, sizeof(*cp->ei)); + if (!cp->ei) { + wlog("Failed to calloc() a execution_information struct"); + return NULL; + } + + /* + * we must copy from the vector, since it points to data + * found in the iocache where we read the command, which will + * be overwritten when we receive one next + */ + for (i = 0; i < kvv->kv_pairs; i++) { + struct key_value *kv = &kvv->kv[i]; + char *key = kv->key; + char *value = kv->value; + char *endptr; + + if (!strcmp(key, "command")) { + cp->cmd = strdup(value); + continue; + } + if (!strcmp(key, "job_id")) { + cp->id = (unsigned int)strtoul(value, &endptr, 0); + continue; + } + if (!strcmp(key, "timeout")) { + cp->timeout = (unsigned int)strtoul(value, &endptr, 0); + continue; + } + if (!strcmp(key, "env")) { + cp->env = buf2kvvec(value, strlen(value), '=', '\n', KVVEC_COPY); + continue; + } + } + + /* jobs without a timeout get a default of 60 seconds. */ + if (!cp->timeout) { + cp->timeout = 60; + } + + return cp; +} + +static void spawn_job(struct kvvec *kvv, int(*cb)(child_process *)) +{ + int result; + child_process *cp; + + if (!kvv) { + wlog("Received NULL command key/value vector. Bug in iocache.c or kvvec.c?"); + return; + } + + cp = parse_command_kvvec(kvv); + if (!cp) { + job_error(NULL, kvv, "Failed to parse worker-command"); + return; + } + if (!cp->cmd) { + job_error(cp, kvv, "Failed to parse commandline. Ignoring job %u", cp->id); + return; + } + + gettimeofday(&cp->ei->start, NULL); + cp->request = kvv; + cp->ei->sq_event = squeue_add(sq, cp->timeout + time(NULL), cp); + started++; + running_jobs++; + result = cb(cp); + if (result < 0) { + job_error(cp, kvv, "Failed to start child: %s: %s", runcmd_strerror(result), strerror(errno)); + squeue_remove(sq, cp->ei->sq_event); + running_jobs--; + return; + } +} + +static int receive_command(int sd, int events, void *arg) +{ + int ioc_ret; + char *buf; + unsigned long size; + + if (!ioc) { + ioc = iocache_create(512 * 1024); + } + ioc_ret = iocache_read(ioc, sd); + + /* master closed the connection, so we exit */ + if (ioc_ret == 0) { + iobroker_close(iobs, sd); + exit_worker(0, NULL); + } + if (ioc_ret < 0) { + /* XXX: handle this somehow */ + } + +#if 0 + /* debug-volley */ + buf = iocache_use_size(ioc, ioc_ret); + write(master_sd, buf, ioc_ret); + return 0; +#endif + /* + * now loop over all inbound messages in the iocache. + * Since KV_TERMINATOR is a nul-byte, they're separated by 3 nuls + */ + while ((buf = iocache_use_delim(ioc, MSG_DELIM, MSG_DELIM_LEN, &size))) { + struct kvvec *kvv; + /* we must copy vars here, as we preserve them for the response */ + kvv = buf2kvvec(buf, (unsigned int)size, KV_SEP, PAIR_SEP, KVVEC_COPY); + if (kvv) + spawn_job(kvv, arg); + } + + return 0; +} + +int worker_set_sockopts(int sd, int bufsize) +{ + int ret; + + ret = fcntl(sd, F_SETFD, FD_CLOEXEC); + ret |= fcntl(sd, F_SETFL, O_NONBLOCK); + + if (!bufsize) + return ret; + ret |= setsockopt(sd, SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(int)); + ret |= setsockopt(sd, SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof(int)); + + return ret; +} + +/* XXX: deprecated */ +int set_socket_options(int sd, int bufsize) +{ + return worker_set_sockopts(sd, bufsize); +} + +void enter_worker(int sd, int (*cb)(child_process*)) +{ +#ifdef HAVE_SIGACTION + struct sigaction sig_action; +#endif + + /* created with socketpair(), usually */ + master_sd = sd; + parent_pid = getppid(); + (void)chdir("/tmp"); + (void)chdir("nagios-workers"); + + ptab = fanout_create(4096); + + if (setpgid(0, 0)) { + /* XXX: handle error somehow, or maybe just ignore it */ + } + + /* we need to catch child signals to mark jobs as reapable */ +#ifdef HAVE_SIGACTION + sig_action.sa_sigaction = NULL; + sig_action.sa_handler = sigchld_handler; + sigfillset(&sig_action.sa_mask); + sig_action.sa_flags=SA_NOCLDSTOP; + sigaction(SIGCHLD, &sig_action, NULL); +#else + signal(SIGCHLD, sigchld_handler); +#endif + + fcntl(fileno(stdout), F_SETFD, FD_CLOEXEC); + fcntl(fileno(stderr), F_SETFD, FD_CLOEXEC); + fcntl(master_sd, F_SETFD, FD_CLOEXEC); + iobs = iobroker_create(); + if (!iobs) { + /* XXX: handle this a bit better */ + exit_worker(EXIT_FAILURE, "Worker failed to create io broker socket set"); + } + + /* + * Create a modest scheduling queue that will be + * more than enough for our needs + */ + sq = squeue_create(1024); + worker_set_sockopts(master_sd, 256 * 1024); + + iobroker_register(iobs, master_sd, cb, receive_command); + while (iobroker_get_num_fds(iobs) > 0) { + int poll_time = -1; + + /* check for timed out jobs */ + while (running_jobs) { + child_process *cp; + struct timeval now, tmo; + + /* stop when scheduling queue is empty */ + cp = (child_process *)squeue_peek(sq); + if (!cp) + break; + + tmo.tv_usec = cp->ei->start.tv_usec; + tmo.tv_sec = cp->ei->start.tv_sec + cp->timeout; + gettimeofday(&now, NULL); + poll_time = tv_delta_msec(&now, &tmo); + /* + * A little extra takes care of rounding errors and + * ensures we never kill a job before it times out. + * 5 milliseconds is enough to take care of that. + */ + poll_time += 5; + if (poll_time > 0) + break; + + if (cp->ei->state == ESTALE) { + if(cp->ei->sq_event && + squeue_evt_when_is_after(cp->ei->sq_event, &now)) { + /* If the state is already stale, there is a already + a job to kill the child on the queue so don't + add another one here. */ + kill_job(cp, ESTALE); + } + } else { + /* this job timed out, so kill it */ + wlog("job %d (pid=%ld) timed out. Killing it", cp->id, (long)cp->ei->pid); + kill_job(cp, ETIME); + } + } + + iobroker_poll(iobs, poll_time); + + if (reapable) + reap_jobs(); + } + + /* we exit when the master shuts us down */ + exit(EXIT_SUCCESS); +} + +int spawn_named_helper(char *path, char **argv) +{ + int ret, pid; + + pid = fork(); + if (pid < 0) { + return -1; + } + + /* parent leaves early */ + if (pid) + return pid; + + ret = execvp(path, argv); + /* if execvp() fails, there's really nothing we can do */ + exit(ret); +} + +int spawn_helper(char **argv) +{ + return spawn_named_helper(argv[0], argv); +} diff --git a/lib/worker.h b/lib/worker.h new file mode 100644 index 0000000..6a2ffbc --- /dev/null +++ b/lib/worker.h @@ -0,0 +1,133 @@ +#ifndef LIBNAGIOS_WORKER_H_INCLUDED +#define LIBNAGIOS_WORKER_H_INCLUDED +#include +#include +#include +#include +#include +#include +#include +#include "libnagios.h" + +/** + * @file worker.h + * @brief Worker implementation along with various helpers + * + * This code isn't really in the "library" category, but it's tucked + * in here to provide a good resource for writing remote workers and + * as an example on how to use the API's found here. + */ + +#ifndef ETIME +#define ETIME ETIMEDOUT +#endif + +typedef struct iobuf { + int fd; + unsigned int len; + char *buf; +} iobuf; + +typedef struct execution_information execution_information; + +typedef struct child_process { + unsigned int id, timeout; + char *cmd; + struct kvvec *env; + int ret; + struct kvvec *request; + iobuf outstd; + iobuf outerr; + execution_information *ei; +} child_process; + +/** + * Callback for enter_worker that simply runs a command + */ +extern int start_cmd(child_process *cp); + +/** + * Spawn a helper with a specific process name + * The first entry in the argv parameter will be the name of the + * new process, unless the process changes the name itself. + * @param path The path to the executable (can be $PATH relative) + * @param argv Argument vector for the helper to spawn + */ +extern int spawn_named_helper(char *path, char **argv); + +/** + * Spawn any random helper process. Uses spawn_named_helper() + * @param argv The (NULL-sentinel-terminated) argument vector + * @return 0 on success, < 0 on errors + */ +extern int spawn_helper(char **argv); + +/** + * To be called when a child_process has completed to ship the result to nagios + * @param cp The child_process that describes the job + * @param reason 0 if everything was OK, 1 if the job was unable to run + * @return 0 on success, non-zero otherwise + */ +extern int finish_job(child_process *cp, int reason); + +/** + * Start to poll the socket and call the callback when there are new tasks + * @param sd A socket descriptor to poll + * @param cb The callback to call upon completion + */ +extern void enter_worker(int sd, int (*cb)(child_process*)); + +/** + * Build a buffer from a key/value vector buffer. + * The resulting kvvec-buffer is suitable for sending between + * worker and master in either direction, as it has all the + * right delimiters in all the right places. + * @param kvv The key/value vector to build the buffer from + * @return NULL on errors, a newly allocated kvvec buffer on success + */ +extern struct kvvec_buf *build_kvvec_buf(struct kvvec *kvv); + +/** + * Send a key/value vector as a bytestream through a socket + * @param[in] sd The socket descriptor to send to + * @param kvv The key/value vector to send + * @return The number of bytes sent, or -1 on errors + */ +extern int worker_send_kvvec(int sd, struct kvvec *kvv); + +/** @deprecated Use worker_send_kvvec() instead */ +extern int send_kvvec(int sd, struct kvvec *kvv) + NAGIOS_DEPRECATED(4.1.0, "worker_send_kvvec()"); + +/** + * Grab a worker message from an iocache buffer + * @param[in] ioc The io cache + * @param[out] size Out buffer for buffer length + * @param[in] flags Currently unused + * @return A buffer from the iocache on succes; NULL on errors + */ +extern char *worker_ioc2msg(iocache *ioc, unsigned long *size, int flags); + +/** + * Parse a worker message to a preallocated key/value vector + * + * @param[in] kvv Key/value vector to fill + * @param[in] buf The buffer to parse + * @param[in] len Length of 'buf' + * @param[in] kvv_flags Flags for buf2kvvec() + * @return 0 on success, < 0 on errors + */ +extern int worker_buf2kvvec_prealloc(struct kvvec *kvv, char *buf, unsigned long len, int kvv_flags); + +/** + * Set some common socket options + * @param[in] sd The socket to set options for + * @param[in] bufsize Size to set send and receive buffers to + * @return 0 on success. < 0 on errors + */ +extern int worker_set_sockopts(int sd, int bufsize); + +/** @deprecated Use worker_set_sockopts() instead */ +extern int set_socket_options(int sd, int bufsize) + NAGIOS_DEPRECATED(4.1.0, "worker_set_sockopts()"); +#endif /* INCLUDE_worker_h__ */ diff --git a/lib/wproc.c b/lib/wproc.c new file mode 100644 index 0000000..86c984d --- /dev/null +++ b/lib/wproc.c @@ -0,0 +1,256 @@ +/* + * Simple test-program to try multiplexing running other programs + * through the worker process layer. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "worker.h" + + +typedef struct simple_worker { + int pid, sd; + unsigned int job_index; + iocache *ioc; +} simple_worker; + +/* we can't handle packets larger than 64MiB */ +#define MAX_IOCACHE_SIZE (64 * 1024 * 1024) +static int sigreceived; +static iobroker_set *iobs; + +static simple_worker *spawn_worker(void (*init_func)(void *), void *init_arg) +{ + int sv[2]; + int pid; + + if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) < 0) + return NULL; + + pid = fork(); + if (pid < 0) { + close(sv[0]); + close(sv[1]); + return NULL; + } + + /* parent leaves the child */ + if (pid) { + simple_worker *worker = calloc(1, sizeof(simple_worker)); + close(sv[1]); + if (!worker) { + kill(SIGKILL, pid); + close(sv[0]); + return NULL; + } + worker->sd = sv[0]; + worker->pid = pid; + worker->ioc = iocache_create(1 * 1024 * 1024); + return worker; + } + + /* child closes parent's end of socket and gets busy */ + close(sv[0]); + + if (init_func) { + init_func(init_arg); + } + enter_worker(sv[1], start_cmd); + + /* not reached, ever */ + exit(EXIT_FAILURE); +} + +static void die(const char *msg) +{ + perror(msg); + exit(EXIT_FAILURE); +} + +static void sighandler(int sig) +{ + sigreceived = sig; + printf("%d: caught sig %d\n", getpid(), sig); +} + +static void child_exited(int sig) +{ + struct rusage ru; + int status, result; + + result = wait3(&status, 0, &ru); + printf("wait3() status: %d; return %d: %s\n", + status, result, strerror(errno)); + if (WIFEXITED(status)) { + printf("Child with pid %d exited normally\n", result); + } + if (WIFSIGNALED(status)) { + printf("Child caught signal %d\n", WTERMSIG(status)); + printf("Child did%s produce a core dump\n", WCOREDUMP(status) ? "" : " not"); + } + exit(1); +} + +static int print_input(int sd, int events, void *wp_) +{ + int ret, pkt = 0; + simple_worker *wp = (simple_worker *)wp_; + struct kvvec kvv = KVVEC_INITIALIZER; + char *buf; + unsigned long tot_bytes = 0, size; + + /* + * if some command filled the buffer, we grow it and read some + * more until we hit the limit + * @todo Define a limit :p + */ + size = iocache_size(wp->ioc); + if (!iocache_capacity(wp->ioc)) { + if (iocache_size(wp->ioc) < MAX_IOCACHE_SIZE) { + /* double the size */ + iocache_grow(wp->ioc, iocache_size(wp->ioc)); + printf("Growing iocache for worker %d. sizes old/new %lu/%lu\n", + wp->pid, size, iocache_size(wp->ioc)); + } else { + printf("iocache_size() for worker %d is already at max\n", wp->pid); + } + } + + ret = iocache_read(wp->ioc, sd); + if (!ret) { + printf("Worker with pid %d seems to have crashed. Exiting\n", wp->pid); + exit(1); + } + if (ret < 0) { + printf("iocache_read() from worker %d returned %d: %m\n", wp->pid, ret); + return 0; + } + printf("read %d bytes from worker with pid %d::\n", ret, wp->pid); + while ((buf = worker_ioc2msg(wp->ioc, &size, 0))) { + int i, ret; + tot_bytes += size; + ret = worker_buf2kvvec_prealloc(&kvv, buf, (unsigned int)size, KVVEC_ASSIGN); + if (!ret < 0) { + printf("main: Failed to parse buffer of size %lu to key/value vector\n", size); + continue; + } + for (i = 0; i < kvv.kv_pairs; i++) { + struct key_value *kv = &kvv.kv[i]; + if (!i && memcmp(kv->key, buf, kv->key_len)) { + printf("### kv[0]->key doesn't match buf. error in kvvec?\n"); + } + printf("main: %2d.%02d: %s=%s\n", pkt, i, kv->key, kv->value); + } + pkt++; + } + + printf("iocache: available: %lu; size: %lu; capacity: %lu\n", + iocache_available(wp->ioc), iocache_size(wp->ioc), iocache_capacity(wp->ioc)); + printf("Got %d packets in %ld bytes (ret: %d)\n", pkt, tot_bytes, ret); + + return 0; +} + +#define NWPS 3 +static simple_worker *wps[NWPS]; +static int wp_index; + +static int send_command(int sd, int events, void *discard) +{ + char buf[8192]; + int ret; + simple_worker *wp; + struct kvvec *kvv; + + ret = read(sd, buf, sizeof(buf)); + if (ret == 0) { + iobroker_close(iobs, sd); + return 0; + } + if (ret < 0) { + printf("main: Failed to read() from fd %d: %s", + sd, strerror(errno)); + } + + /* this happens when we're reading from stdin */ + buf[--ret] = 0; + + kvv = kvvec_create(5); + wp = wps[wp_index++ % NWPS]; + kvvec_addkv(kvv, "job_id", (char *)mkstr("%d", wp->job_index++)); + kvvec_addkv_wlen(kvv, "command", sizeof("command") - 1, buf, ret); + kvvec_addkv(kvv, "timeout", (char *)mkstr("%d", 10)); + printf("Sending kvvec with %d pairs to worker %d\n", kvv->kv_pairs, wp->pid); + worker_send_kvvec(wp->sd, kvv); + kvvec_destroy(kvv, 0); + return 0; +} + +void print_some_crap(void *arg) +{ + char *str = (char *)arg; + + printf("%d: Argument passed: %s\n", getpid(), str); +} + +int main(int argc, char **argv) +{ + simple_worker *wp; + int i; +#ifdef HAVE_SIGACTION + struct sigaction sig_action; + + sig_action.sa_sigaction = NULL; + sigfillset(&sig_action.sa_mask); + sig_action.sa_flags=SA_NOCLDSTOP; + sig_action.sa_handler = child_exited; + sigaction(SIGCHLD, &sig_action, NULL); + + sig_action.sa_flags = SA_NODEFER|SA_RESTART; + sig_action.sa_handler = sighandler; + sigfillset(&sig_action.sa_mask); + sigaction(SIGINT, &sig_action, NULL); + sigaction(SIGPIPE, &sig_action, NULL); +#else /* HAVE_SIGACTION */ + + signal(SIGINT, sighandler); + signal(SIGPIPE, sighandler); + signal(SIGCHLD, child_exited); +#endif /* HAVE_SIGACTION */ + + iobs = iobroker_create(); + if (!iobs) + die("Failed to create io broker set"); + + for (i = 0; i < NWPS; i++) { + wp = spawn_worker(print_some_crap, "lalala"); + if (!wp) { + die("Failed to spawn worker(s)\n"); + } + wps[i] = wp; + printf("Registering worker sd %d with io broker\n", wp->sd); + iobroker_register(iobs, wp->sd, wp, print_input); + } + + iobroker_register(iobs, fileno(stdin), NULL, send_command); + + /* get to work */ + while (!sigreceived && iobroker_get_num_fds(iobs)) { + iobroker_poll(iobs, -1); + } + + for (i = 0; i < NWPS; i++) { + kill(wps[i]->pid, SIGKILL); + } + + return 0; +} diff --git a/module/Makefile.in b/module/Makefile.in index a0eb7c5..3e52f5c 100644 --- a/module/Makefile.in +++ b/module/Makefile.in @@ -1,7 +1,6 @@ ################################### # Makefile for NEB examples # -# Last Modified: 12-14-2007 ################################### @@ -28,7 +27,7 @@ CP=@CP@ all: helloworld.o helloworld.o: helloworld.c - $(CC) $(MOD_CFLAGS) $(CFLAGS) -o helloworld.o helloworld.c $(MOD_LDFLAGS) $(LDFLAGS) $(LIBS) + $(CC) -I.. $(MOD_CFLAGS) $(CFLAGS) -o helloworld.o helloworld.c $(MOD_LDFLAGS) $(LDFLAGS) $(LIBS) clean: rm -f helloworld.o diff --git a/module/helloworld.c b/module/helloworld.c index 4748d9a..8e66554 100644 --- a/module/helloworld.c +++ b/module/helloworld.c @@ -2,9 +2,7 @@ * * HELLOWORLD.C - Example of a simple NEB module * - * Copyright (c) 2003-2007 Ethan Galstad (http://www.nagios.org) - * - * Last Modified: 12-26-2007 + * Copyright (c) 2003-2007 Ethan Galstad (https://www.nagios.org) * * Description: * @@ -22,8 +20,6 @@ * *****************************************************************************/ -#include "../include/config.h" - /* include (minimum required) event broker header files */ #include "../include/nebmodules.h" #include "../include/nebcallbacks.h" diff --git a/nagios.spec b/nagios.spec index 4f599c6..0ed76dd 100644 --- a/nagios.spec +++ b/nagios.spec @@ -1,435 +1,249 @@ -%define name nagios -%define version 3.5.1 -%define release 1 -%define nsusr nagios -%define nsgrp nagios -%define cmdgrp nagiocmd -%define wwwusr apache -%define wwwgrp apache +# Upstream: Ethan Galstad +# Modified version from original dag spec -# Performance data handling method to use. By default we will use -# the file-based one (as existed in NetSaint). -# You can select the external command based method (the defaut for -# Nagios) by specifying -# --define 'PERF_EXTERNAL 1' -# in the rpm command-line -%{!?PERF_EXTERNAL: %define PERF_EXTERNAL 0} +### FIXME: TODO: Add sysv script based on template. (remove cmd-file on start-up) +%define logmsg logger -t %{name}/rpm +%define logdir %{_localstatedir}/log/nagios -# Embedded Perl stuff, specify -# --define 'EMBPERL 1' -# in the rpm command-line to enable it -%{!?EMBPERL: %define EMBPERL 0} +# Setup some debugging options in case we build with --with debug +%if %{defined _with_debug} + %define mycflags -O0 -pg -ggdb3 +%else + %define mycflags %{nil} +%endif -# Macro that print mesages to syslog at package (un)install time -%define nnmmsg logger -t %{name}/rpm +# Allow newer compiler to suppress warnings +%if 0%{?el6} + %define myXcflags -Wno-unused-result +%else + %define myXcflags %{nil} +%endif -Summary: Host/service/network monitoring program -Name: %{name} -Version: %{version} -Release: %{release} +Summary: Open Source host, service and network monitoring program +Name: nagios +Version: 4.3.2 +Release: 2%{?dist} License: GPL -Group: Application/System -Source0: %{name}-%{version}.tar.gz -BuildRoot: %{_tmppath}/%{name}-buildroot -Prefix: %{_prefix} -Prefix: /etc/init.d -Prefix: /etc/nagios -Prefix: /var/log/nagios -Prefix: /var/spool/nagios -Requires: gd > 1.8, zlib, libpng, libjpeg, bash, grep -PreReq: /usr/bin/logger, chkconfig, sh-utils, shadow-utils, sed, initscripts, fileutils, mktemp -BuildRequires: gd-devel > 1.8, zlib-devel, libpng-devel, libjpeg-devel +Group: Applications/System +URL: https://www.nagios.org/ +Packager: Daniel Wittenberg +Vendor: Nagios Enterprises (https://www.nagios.org) +Source0: http://dl.sf.net/nagios/nagios-%{version}.tar.gz +BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root +BuildRequires: gd-devel > 1.8 +BuildRequires: zlib-devel +BuildRequires: libpng-devel +BuildRequires: libjpeg-devel +BuildRequires: doxygen +BuildRequires: gperf + +Obsoletes: nagios-www <= %{version} +Requires: httpd,php %description -Nagios is a program that will monitor hosts and services on your -network. It has the ability to email or page you when a problem arises -and when a problem is resolved. Nagios is written in C and is -designed to run under Linux (and some other *NIX variants) as a -background process, intermittently running checks on various services -that you specify. +Nagios is an application, system and network monitoring application. +It can escalate problems by email, pager or any other medium. It is +also useful for incident or SLA reporting. + +Nagios is written in C and is designed as a background process, +intermittently running checks on various services that you specify. The actual service checks are performed by separate "plugin" programs which return the status of the checks to Nagios. The plugins are -available at http://sourceforge.net/projects/nagiosplug - -This package provide core programs for nagios. The web interface, -documentation, and development files are built as separate packages - - -%package www -Group: Application/System -Summary: Provides the HTML and CGI files for the Nagios web interface. -Requires: %{name} = %{version} -Requires: webserver - - -%description www -Nagios is a program that will monitor hosts and services on your -network. It has the ability to email or page you when a problem arises -and when a problem is resolved. Nagios is written in C and is -designed to run under Linux (and some other *NIX variants) as a -background process, intermittently running checks on various services -that you specify. - -Several CGI programs are included with Nagios in order to allow you -to view the current service status, problem history, notification -history, and log file via the web. This package provides the HTML and -CGI files for the Nagios web interface. In addition, HTML -documentation is included in this package - +located in the nagios-plugins package. %package devel -Group: Application/System -Summary: Provides include files that Nagios-related applications may compile against. -Requires: %{name} = %{version} +Summary: Header files, libraries and development documentation for %{name} +Group: Development/Libraries +Requires: %{name} = %{version}-%{release} %description devel -Nagios is a program that will monitor hosts and services on your -network. It has the ability to email or page you when a problem arises -and when a problem is resolved. Nagios is written in C and is -designed to run under Linux (and some other *NIX variants) as a -background process, intermittently running checks on various services -that you specify. +This package contains the header files, static libraries and development +documentation for %{name}. If you are a NEB-module author or wish to +write addons for Nagios using Nagios' own API's, you should install +this package. -This package provides include files that Nagios-related applications -may compile against. +%package contrib +Summary: Files from the contrib directory +Group: Development/Utils +Requires: %{name} = %{version}-%{release} +%description contrib +This package contains all the files from the contrib directory %prep -%setup -q +%setup + +# /usr/local/nagios is hardcoded in many places +%{__perl} -pi.orig -e 's|/usr/local/nagios/var/rw|%{_localstatedir}/nagios/rw|g;' contrib/eventhandlers/submit_check_result + +%build + +CFLAGS="%{mycflags} %{myXcflags}" LDFLAGS="$CFLAGS" %configure \ + --datadir="%{_datadir}/nagios" \ + --libexecdir="%{_libdir}/nagios/plugins" \ + --localstatedir="%{_localstatedir}/nagios" \ + --with-checkresult-dir="%{_localstatedir}/nagios/spool/checkresults" \ + --sbindir="%{_libdir}/nagios/cgi" \ + --sysconfdir="%{_sysconfdir}/nagios" \ + --with-cgiurl="/nagios/cgi-bin" \ + --with-command-user="apache" \ + --with-command-group="apache" \ + --with-gd-lib="%{_libdir}" \ + --with-gd-inc="%{_includedir}" \ + --with-htmurl="/nagios" \ + --with-init-dir="%{_initrddir}" \ + --with-lockfile="%{_localstatedir}/nagios/nagios.pid" \ + --with-mail="/bin/mail" \ + --with-nagios-user="nagios" \ + --with-nagios-group="nagios" \ + --with-perlcache \ + --with-template-objects \ + --with-template-extinfo \ + --enable-event-broker +find . -type f -name Makefile -exec /usr/bin/perl -p -i -e "s/-mtune=generic/-march=nocona/g" Makefile {} \; -print +%{__make} %{?_smp_mflags} all + +### Build our documentation +%{__make} dox + +### Apparently contrib does not obey configure ! +%{__make} %{?_smp_mflags} -C contrib + +%install +export PATH=%{_bindir}:/bin:\$PATH +%{__rm} -rf %{buildroot} +%{__make} install-unstripped install-init install-commandmode install-config \ + DESTDIR="%{buildroot}" \ + INSTALL_OPTS="" \ + COMMAND_OPTS="" \ + INIT_OPTS="" + +%{__install} -d -m 0755 %{buildroot}%{_includedir}/nagios/ +%{__install} -p -m 0644 include/*.h %{buildroot}%{_includedir}/nagios/ +%{__mkdir} -p -m 0755 %{buildroot}/%{_includedir}/nagios/lib +%{__install} -m 0644 lib/*.h %{buildroot}/%{_includedir}/nagios/lib + +%{__install} -Dp -m 0644 sample-config/httpd.conf %{buildroot}%{_sysconfdir}/httpd/conf.d/nagios.conf + +### FIX log-paths +%{__perl} -pi -e ' + s|log_file.*|log_file=%{logdir}/nagios.log|; + s|log_archive_path=.*|log_archive_path=%{logdir}/archives|; + s|debug_file=.*|debug_file=%{logdir}/nagios.debug|; + ' %{buildroot}%{_sysconfdir}/nagios/nagios.cfg + +### make logdirs +%{__mkdir_p} %{buildroot}%{logdir}/ +%{__mkdir_p} %{buildroot}%{logdir}/archives/ + +### Install logos +%{__mkdir_p} %{buildroot}%{_datadir}/nagios/images/logos + +### Install documentation +%{__mkdir_p} %{buildroot}%{_datadir}/nagios/documentation +%{__cp} -a Documentation/html/* %{buildroot}%{_datadir}/nagios/documentation + +# Put the new RC script in place +%{__install} -m 0755 daemon-init %{buildroot}/%{_initrddir}/nagios +%{__install} -d -m 0755 %{buildroot}/%{_sysconfdir}/sysconfig/ +%{__install} -m 0644 nagios.sysconfig %{buildroot}/%{_sysconfdir}/sysconfig/nagios + +### Apparently contrib wants to do embedded-perl stuff as well and does not obey configure ! +%{__make} install -C contrib \ + DESTDIR="%{buildroot}" \ + INSTALL_OPTS="" + +### Install libnagios +%{__install} -m 0644 lib/libnagios.a %{buildroot}%{_libdir}/libnagios.a + +%{__install} -d -m 0755 %{buildroot}%{_libdir}/nagios/plugins/eventhandlers/ +%{__cp} -afpv contrib/eventhandlers/* %{buildroot}%{_libdir}/nagios/plugins/eventhandlers/ +%{__mv} contrib/README contrib/README.contrib + +CGI=`find contrib/ -name '*.cgi' -type f |sed s/'contrib\/'//g` +CGI=`for i in $CGI; do echo -n "$i|"; done |sed s/\|$//` +find %{buildroot}/%{_libdir}/nagios/cgi -type f -print | sed s!'%{buildroot}'!!g | egrep -ve "($CGI)" > cgi.files +find %{buildroot}/%{_libdir}/nagios/cgi -type f -print | sed s!'%{buildroot}'!!g | egrep "($CGI)" > contrib.files + %pre -# Create `nagios' user on the system if necessary -if /usr/bin/id %{nsusr} > /dev/null 2>&1 ; then - : # user already exists +if ! /usr/bin/id nagios &>/dev/null; then + /usr/sbin/useradd -r -d %{logdir} -s /bin/sh -c "nagios" nagios || \ + %logmsg "Unexpected error adding user \"nagios\". Aborting installation." +fi +if ! /usr/bin/getent group nagiocmd &>/dev/null; then + /usr/sbin/groupadd nagiocmd &>/dev/null || \ + %logmsg "Unexpected error adding group \"nagiocmd\". Aborting installation." +fi + +%post +/sbin/chkconfig --add nagios + +if /usr/bin/id apache &>/dev/null; then + if ! /usr/bin/id -Gn apache 2>/dev/null | grep -q nagios ; then + /usr/sbin/usermod -a -G nagios,nagiocmd apache &>/dev/null + fi else - /usr/sbin/useradd -r -d /var/log/nagios -s /bin/sh -c "%{nsusr}" %{nsusr} || \ - %nnmmsg Unexpected error adding user "%{nsusr}". Aborting install process. + %logmsg "User \"apache\" does not exist and is not added to group \"nagios\". Sending commands to Nagios from the command CGI is not possible." fi -# id cannot tell us if the group already exists -# so just try to create it and assume it works -/usr/sbin/groupadd %{cmdgrp} > /dev/null 2>&1 - -# if LSB standard /etc/init.d does not exist, -# create it as a symlink to the first match we find -if [ -d /etc/init.d -o -L /etc/init.d ]; then - : # we're done -elif [ -d /etc/rc.d/init.d ]; then - ln -s /etc/rc.d/init.d /etc/init.d -elif [ -d /usr/local/etc/rc.d ]; then - ln -s /usr/local/etc/rc.d /etc/init.d -elif [ -d /sbin/init.d ]; then - ln -s /sbin/init.d /etc/init.d -fi - - %preun -if [ "$1" = 0 ]; then - /sbin/service nagios stop > /dev/null 2>&1 - /sbin/chkconfig --del nagios +if [ $1 -eq 0 ]; then + /sbin/service nagios stop &>/dev/null || : + /sbin/chkconfig --del nagios fi %postun -if [ "$1" -ge "1" ]; then - /sbin/service nagios condrestart >/dev/null 2>&1 || : -fi -# Delete nagios user and group -# (if grep doesn't find a match, then it is NIS or LDAP served and cannot be deleted) -if [ $1 = 0 ]; then - /bin/grep '^%{nsusr}:' /etc/passwd > /dev/null 2>&1 && /usr/sbin/userdel %{nsusr} || %nnmmsg "User %{nsusr} could not be deleted." - /bin/grep '^%{nsgrp}:' /etc/group > /dev/null 2>&1 && /usr/sbin/groupdel %{nsgrp} || %nnmmsg "Group %{nsgrp} could not be deleted." - /bin/grep '^%{cmdgrp}:' /etc/group > /dev/null 2>&1 && /usr/sbin/groupdel %{cmdgrp} || %nnmmsg "Group %{cmdgrp} could not be deleted." -fi - - -%post www -# If apache is installed, and we can find the apache user, set a shell var -wwwusr=`awk '/^[ \t]*User[ \t]+[a-zA-Z0-9]+/ {print $2}' /etc/httpd/conf/*.conf` -if [ "z" == "z$wwwusr" ]; then # otherwise, use the default - wwwusr=%{wwwusr} -fi -# if apache user is not in cmdgrp, add it -if /usr/bin/id -Gn $wwwusr 2>/dev/null | /bin/grep -q %{cmdgrp} > /dev/null 2>&1 ; then - : # $wwwusr (default: apache) is already in nagiocmd group -else - # first find apache primary group - pgrp=`/usr/bin/id -gn $wwwusr 2>/dev/null` - # filter apache primary group from secondary groups - sgrps=`/usr/bin/id -Gn $wwwusr 2>/dev/null | /bin/sed "s/^$pgrp //;s/ $pgrp //;s/^$pgrp$//;s/ /,/g;"` - if [ "z" == "z$sgrps" ] ; then - sgrps=%{cmdgrp} - else - sgrps=$sgrps,%{cmdgrp} - fi - # modify apache user, adding it to cmdgrp - /usr/sbin/usermod -G $sgrps $wwwusr >/dev/null 2>&1 - %nnmmsg "User $wwwusr added to group %{cmdgrp} so sending commands to Nagios from the command CGI is possible." -fi - - -%preun www -if [ $1 = 0 ]; then -if test -f /etc/httpd/conf/httpd.conf; then - TEMPFILE=`mktemp /etc/httpd/conf/httpd.conf.tmp.XXXXXX` - if grep "^ *Include /etc/httpd/conf.d/nagios.conf" /etc/httpd/conf/httpd.conf > /dev/null; then - grep -v "^ *Include /etc/httpd/conf.d/nagios.conf" /etc/httpd/conf/httpd.conf > $TEMPFILE - mv $TEMPFILE /etc/httpd/conf/httpd.conf - chmod 664 /etc/httpd/conf/httpd.conf - /etc/rc.d/init.d/httpd restart - fi -fi -fi - - -%build -export PATH=$PATH:/usr/sbin -CFLAGS="$RPM_OPT_FLAGS" CXXFLAGS="$RPM_OPT_FLAGS" \ -./configure \ - --with-init-dir=/etc/init.d \ - --with-cgiurl=/nagios/cgi-bin \ - --with-htmurl=/nagios \ - --with-lockfile=/var/run/nagios.pid \ - --with-nagios-user=%{nsusr} \ - --with-nagios-group=%{nsgrp} \ - --prefix=%{_prefix} \ - --exec-prefix=%{_prefix}/sbin \ - --bindir=%{_prefix}/sbin \ - --sbindir=%{_prefix}/lib/nagios/cgi \ - --libexecdir=%{_prefix}/lib/nagios/plugins \ - --datarootdir=%{_prefix}/share/nagios \ - --sysconfdir=/etc/nagios \ - --localstatedir=/var/log/nagios \ -%if ! %{PERF_EXTERNAL} - --with-file-perfdata \ -%endif -%if %{EMBPERL} - --enable-embedded-perl \ -%endif - --with-gd-lib=/usr/lib \ - --with-gd-inc=/usr/include \ - --with-template-objects \ - --with-template-extinfo - -make all - -# make sample configs -###cd sample-config -###F=`mktemp temp.XXXXXX` -###sed -e 's=/var/log/nagios/rw/=/var/spool/nagios/=;s=@sysconfdir@/resource.cfg=@sysconfdir@/private/resource.cfg=' nagios.cfg > ${F} -###mv ${F} nagios.cfg -###cd .. - -# make daemonchk.cgi and event handlers -cd contrib -make -cd eventhandlers -for f in `find . -type f` ; do - F=`mktemp temp.XXXXXX` - sed "s=/usr/local/nagios/var/rw/=/var/spool/nagios/=; \ - s=/usr/local/nagios/libexec/eventhandlers/=%{_prefix}/lib/nagios/plugins/eventhandlers=; \ - s=/usr/local/nagios/test/var=/var/log/nagios=" ${f} > ${F} - mv ${F} ${f} -done -cd ../.. - - -%install -[ "$RPM_BUILD_ROOT" != "/" ] && rm -rf $RPM_BUILD_ROOT -install -d -m 0775 ${RPM_BUILD_ROOT}/var/spool/nagios -install -d -m 0755 ${RPM_BUILD_ROOT}%{_prefix}/include/nagios -install -d -m 0755 ${RPM_BUILD_ROOT}/etc/init.d -install -d -m 0755 ${RPM_BUILD_ROOT}/etc/logrotate.d -install -d -m 0755 ${RPM_BUILD_ROOT}/etc/httpd/conf.d -install -d -m 0755 ${RPM_BUILD_ROOT}/etc/nagios -install -d -m 0755 ${RPM_BUILD_ROOT}/etc/nagios/objects -### install -d -m 0755 ${RPM_BUILD_ROOT}/etc/nagios/private -make DESTDIR=${RPM_BUILD_ROOT} INSTALL_OPTS="" COMMAND_OPTS="" install -make DESTDIR=${RPM_BUILD_ROOT} INSTALL_OPTS="" COMMAND_OPTS="" INIT_OPTS="" install-daemoninit - -# install templated configuration files -cd sample-config -for f in {nagios,cgi}.cfg ; do - [ -f $f ] && install -c -m 664 $f ${RPM_BUILD_ROOT}/etc/nagios/${f} -done -###mkdir -p ${RPM_BUILD_ROOT}/etc/nagios/private -for f in resource.cfg ; do - [ -f $f ] && install -c -m 664 $f ${RPM_BUILD_ROOT}/etc/nagios/${f} -done -cd template-object -for f in {commands,contacts,localhost,switch,templates,timeperiods}.cfg -do - [ -f $f ] && install -c -m 664 $f ${RPM_BUILD_ROOT}/etc/nagios/objects/${f} -done -cd .. -cd .. - -# install headers for development package -install -m 0644 include/locations.h ${RPM_BUILD_ROOT}%{_prefix}/include/nagios - -# install httpd configuration in RH80-style httpd config subdir -cp sample-config/httpd.conf ${RPM_BUILD_ROOT}/etc/httpd/conf.d/nagios.conf - -# install CGIs -cd contrib -make INSTALL=install DESTDIR=${RPM_BUILD_ROOT} INSTALL_OPTS="" COMMAND_OPTS="" CGIDIR=%{_prefix}/lib/nagios/cgi install -#mv ${RPM_BUILD_ROOT}%{_prefix}/lib/nagios/cgi/convertcfg ${RPM_BUILD_ROOT}%{_prefix}/lib/nagios/ -#mv ${RPM_BUILD_ROOT}%{_prefix}/lib/nagios/cgi/mini_epn ${RPM_BUILD_ROOT}%{_prefix}/sbin/ -cd .. - -# install event handlers -cd contrib/eventhandlers -install -d -m 0755 ${RPM_BUILD_ROOT}%{_prefix}/lib/nagios/eventhandlers -for file in * ; do - test -f $file && install -m 0755 $file ${RPM_BUILD_ROOT}%{_prefix}/lib/nagios/eventhandlers && rm -f $file -done -cd ../.. - +# This could be bad if files are left with this uid/gid and then get owned by a new user +#if [ $1 -eq 0 ]; then +# /usr/sbin/userdel nagios || %logmsg "User \"nagios\" could not be deleted." +# /usr/sbin/groupdel nagios || %logmsg "Group \"nagios\" could not be deleted." +#fi +/sbin/service nagios condrestart &>/dev/null || : %clean -rm -rf $RPM_BUILD_ROOT - - -%files -%defattr(755,root,root) -/etc/init.d/nagios -%{_prefix}/sbin/nagios -%{_prefix}/sbin/nagiostats -%if %{EMBPERL} -%{_prefix}/sbin/p1.pl -%endif -%{_prefix}/sbin/mini_epn -%{_prefix}/sbin/new_mini_epn -%dir %{_prefix}/lib/nagios/eventhandlers -%{_prefix}/lib/nagios/eventhandlers/* -%{_sbindir}/convertcfg -%dir /etc/nagios -%dir /etc/nagios/objects -%defattr(644,root,root) -%config(noreplace) /etc/nagios/*.cfg -%config(noreplace) /etc/nagios/objects/*.cfg -%defattr(750,root,%{nsgrp}) -###%dir /etc/nagios/private -%defattr(640,root,%{nsgrp}) -### %config(noreplace) /etc/nagios/private/resource.cfg -%defattr(755,%{nsusr},%{nsgrp}) -%dir /var/log/nagios -%dir /var/log/nagios/archives -%defattr(2775,%{nsusr},%{nsgrp}) -%dir /var/spool/nagios -%doc Changelog INSTALLING LICENSE README UPGRADING - - -%files www -%defattr(755,root,root) -%dir %{_prefix}/lib/nagios/cgi -%{_prefix}/lib/nagios/cgi/* -%dir %{_prefix}/share/nagios -%defattr(-,root,root) -%{_prefix}/share/nagios/* -%config(noreplace) /etc/httpd/conf.d/nagios.conf +%{__rm} -rf %{buildroot} +%files -f cgi.files +%defattr(-, root, root, 0755) +%doc Changelog INSTALLING LEGAL LICENSE README THANKS UPGRADING +%attr(0644,root,root) %config(noreplace) %{_sysconfdir}/httpd/conf.d/nagios.conf +%attr(0644,root,root) %config(noreplace) %{_sysconfdir}/sysconfig/nagios +%attr(0755,root,root) %config %{_initrddir}/nagios +%attr(0755,root,root) %{_bindir}/nagios +%attr(0755,root,root) %{_bindir}/nagiostats +%attr(0755,root,root) %{_libdir}/nagios/plugins/ +%attr(0755,root,root) %{_datadir}/nagios/ +%attr(0755,nagios,nagios) %dir %{_sysconfdir}/nagios/ +%attr(0644,nagios,nagios) %config(noreplace) %{_sysconfdir}/nagios/*.cfg +%attr(0755,nagios,nagios) %{_sysconfdir}/nagios/objects/ +%attr(0644,nagios,nagios) %config(noreplace) %{_sysconfdir}/nagios/objects/*.cfg +%attr(0755,nagios,nagios) %dir %{_localstatedir}/nagios/ +%attr(0755,nagios,nagios) %{_localstatedir}/nagios/ +%attr(0755,nagios,nagios) %{logdir}/ +%attr(0755,nagios,apache) %{_localstatedir}/nagios/rw/ +%attr(0644,root,root) %{_libdir}/libnagios.a %files devel -%defattr(-,root,root) -%dir %{_prefix}/include/nagios -%{_prefix}/include/nagios/locations.h +%attr(0755,root,root) %{_includedir}/nagios/ +%files contrib -f contrib.files +%doc contrib/README.contrib +%attr(0755,root,root) %{_bindir}/convertcfg +%attr(0755,root,root) %{_libdir}/nagios/plugins/eventhandlers/ %changelog -* Tue Nov 22 2005 Andreas Kasenides -- packaged %{_prefix}/sbin/new_mini_epn -- moved resource.cfg in /etc/nagios +* Fri Nov 15 2013 Eric Stanley 4.0.1-1 +- Corrected permissions on plugins directory (bug #494 - patch by Karsten Weiss) +- Corrected doc directive (bug #494 - patch by Karsten Weiss) +- Added configuration directive for *.cfg files (bug #494 - patch by Karsten Weiss) -* Thu Dec 30 2004 Rui Miguel Silva Seabra -- FIX spec (wrong tag for License, and update to current state of compile) +* Wed Sep 18 2013 Daniel Wittenberg 4.0.0rc2-1 +- Fix find command - Florin Andrei, bug #489 +- Remove compiler warning option that breaks older builds, bug #488 -* Sat May 31 2003 Karl DeBisschop (1.1-1) -- Merge with CVS for 1.1 release - -* Fri May 30 2003 Karl DeBisschop (1.0-4) -- cmdgrp was not always getting created -- patches for cmd.cgi and history.cgi - -* Sat May 24 2003 Karl DeBisschop (1.0-3) -- patches for doco and PostgreSQL timestamp -- make sure all files are packaged (otherwise, will not build on RH9) - -* Sat May 17 2003 Karl DeBisschop (1.0-2) -- patch for file descriptor leak - -* Fri Oct 04 2002 Karl DeBisschop -- merge many improvements from Ramiro Morales - (macros for PERF_EXTERNAL and EMBPERL, cleanup pre/post scripts, - nnmmsg logger macro, include eventhandlers, convertcfg, mini_epn) -- use LSB-standard /etc/init.d/nagios startup location - -* Tue Aug 13 2002 Karl DeBisschop -- INSTALL was renamed INSTALLING -- p1.pl script included in package -- web server restarted because Red Hat 7.3 init does not do 'reload' - -* Fri Jun 14 2002 Ethan Galstad (1.0a4) -- Fixed spec file to work with Nagios - -* Wed Jan 17 2001 Karl DeBisschop (0.0.7a5-1) -- switch from /usr/libexec to /usr/lib because linux FHS has no libexec -- use global macro to set location of init script -- fold htaccess.sample into contrib directory of tarball - -* Fri Nov 03 2000 Karl DeBisschop (0.0.6-1) -- Rebuild with final sources - -* Wed Sep 06 2000 Karl DeBisschop (0.0.6b5-1) -- Create separate cgi, html, and devel packages -- Include commands.cfg - -* Sun Aug 27 2000 Karl DeBisschop (0.0.6b5-1) -- beta 5 - -* Sun Jul 23 2000 Karl DeBisschop (0.0.6b3-2) -- fixes for daemon-init, multi-OS RPM building - -* Wed Jul 12 2000 Karl DeBisschop (0.0.6b3-1) -- beta 3 - -* Sun Jun 25 2000 Karl DeBisschop (0.0.6b2-3) -- true beta2 sources - -* Sat Jun 24 2000 Karl DeBisschop (0.0.6b2-2) -- cleanup spec, still using pre-beta2 sources - -* Sat Jun 24 2000 Karl DeBisschop (0.0.6b2-1) -- mandrake merge using pre-beta2 sources (many thanks to Stefan van der Eijk ) - -* Wed Jun 14 2000 Karl DeBisschop (0.0.6b1-1) -- add stylesheet diffs - -* Mon Jun 12 2000 Karl DeBisschop (0.0.6b1-1) -- adapt for 0.0.6b1 - -* Mon Jun 05 2000 Karl DeBisschop (0.0.5-4) -- add traceroute.cgi and htaccess.sample -- move placement of docs (in files) to avoid group warnings -- change www user and group to nobody and add warning - -* Mon Jun 05 2000 Karsten Weiss (0.0.5-3) -- official group name -- improved user detection - -* Tue Oct 19 1999 Mike McHenry (0.0.4-1) -- Upgraded package from 0.0.4b4 to 0.0.4 - -* Mon Aug 16 1999 Mike McHenry -- First RPM build (0.0.4b4) +* Fri Mar 15 2013 Daniel Wittenberg 3.99.96-1 +- Major updates for version 4.0 +- New spec file, new RC script, new sysconfig diff --git a/nagios.sysconfig b/nagios.sysconfig new file mode 100644 index 0000000..c6abd79 --- /dev/null +++ b/nagios.sysconfig @@ -0,0 +1,13 @@ +# Setup some basic values for startup + +# Do you want to use the ramdisk +USE_RAMDISK=0 + +# How big (in MB) should the ramdisk be +RAMDISK_SIZE=256 + +# Ramdisk Location +RAMDISK_DIR="/var/nagios/ramcache" + +# Should the process be niced +NICELEVEL=-15 diff --git a/p1.pl b/p1.pl deleted file mode 100644 index 0e95291..0000000 --- a/p1.pl +++ /dev/null @@ -1,775 +0,0 @@ - package Embed::Persistent; - -# p1.pl for Nagios - -use strict ; - -use Text::ParseWords qw(parse_line) ; - -use constant LEAVE_MSG => 1 ; -use constant CACHE_DUMP => 2 ; -use constant PLUGIN_DUMP => 4 ; - -use constant DEBUG_LEVEL => 0 ; -# use constant DEBUG_LEVEL => CACHE_DUMP ; -# use constant DEBUG_LEVEL => LEAVE_MSG ; -# use constant DEBUG_LEVEL => LEAVE_MSG | CACHE_DUMP ; -# use constant DEBUG_LEVEL => LEAVE_MSG | CACHE_DUMP | PLUGIN_DUMP ; - -use constant DEBUG_LOG_PATH => '/usr/local/nagios/var/' ; -# use constant DEBUG_LOG_PATH => './' ; -use constant LEAVE_MSG_STREAM => DEBUG_LOG_PATH . 'epn_leave-msgs.log' ; -use constant CACHE_DUMP_STREAM => DEBUG_LOG_PATH . 'epn_cache-dump.log' ; -use constant PLUGIN_DUMP_STREAM => DEBUG_LOG_PATH . 'epn_plugin-dump.log' ; - -use constant NUMBER_OF_PERL_PLUGINS => 60 ; - -use constant Cache_Dump_Interval => 20 ; - # Cache will be dumped every Cache_Dump_Interval plugin compilations - -(DEBUG_LEVEL & LEAVE_MSG) && do { - open LH, '>> ' . LEAVE_MSG_STREAM - or die "Can't open " . LEAVE_MSG_STREAM . ": $!" ; - - # Unbuffer LH since this will be written by child processes. - - select( (select(LH), $| = 1)[0] ) ; - } ; -(DEBUG_LEVEL & CACHE_DUMP) && do { - (open CH, '>> ' . CACHE_DUMP_STREAM - or die "Can't open " . CACHE_DUMP_STREAM . ": $!") ; - select( (select(CH), $| = 1)[0] ) ; - } ; -(DEBUG_LEVEL & PLUGIN_DUMP) && (open PH, '>> ' . PLUGIN_DUMP_STREAM - or die "Can't open " . PLUGIN_DUMP_STREAM . ": $!") ; - -require Data::Dumper - if DEBUG_LEVEL & CACHE_DUMP ; - -my (%Cache, $Current_Run) ; -keys %Cache = NUMBER_OF_PERL_PLUGINS ; - # Offsets in %Cache{$filename} -use constant MTIME => 0 ; -use constant PLUGIN_ARGS => 1 ; -use constant PLUGIN_ERROR => 2 ; -use constant PLUGIN_HNDLR => 3 ; - -package main; - -use subs 'CORE::GLOBAL::exit'; - -sub CORE::GLOBAL::exit { die "ExitTrap: $_[0] (Redefine exit to trap plugin exit with eval BLOCK)" } - - -package OutputTrap; - - # Methods for use by tied STDOUT in embedded PERL module. - # Simply ties STDOUT to a scalar and caches values written to it. - # NB No more than 4KB characters per line are kept. - -sub TIEHANDLE { - my ($class) = @_; - my $me = ''; - bless \$me, $class; -} - -sub PRINT { - my $self = shift; - # $$self = substr(join('',@_), 0, 256) ; - $$self .= substr(join('',@_), 0, 4096) ; -} - -sub PRINTF { - my $self = shift; - my $fmt = shift; - # $$self = substr(sprintf($fmt,@_), 0, 256) ; - $$self .= substr(sprintf($fmt,@_), 0, 4096) ; -} - -sub READLINE { - my $self = shift; - -# CHANGED 12/26/07 EG Following two statements didn't allow for multi-line output or output > 256 chars - # Omit all lines after the first, per the nagios plugin guidelines -# $$self = (split /\n/, $$self)[0]; - # Perl code other than plugins may print nothing; in this case return "(No output!)\n". -# return $$self ? substr($$self, 0, 256) : "(No output!)\n" ; - - return $$self; -} - -sub CLOSE { - my $self = shift; - undef $self ; -} - -sub DESTROY { - my $self = shift; - undef $self; -} - -package Embed::Persistent; - -sub valid_package_name { - local $_ = shift ; - s|([^A-Za-z0-9\/])|sprintf("_%2x",unpack("C",$1))|eg; - # second pass only for words starting with a digit - s|/(\d)|sprintf("/_%2x",unpack("C",$1))|eg; - - # Dress it up as a real package name - s|/|::|g; - return /^::/ ? "Embed$_" : "Embed::$_" ; - } - -# Perl 5.005_03 only traps warnings for errors classed by perldiag -# as Fatal (eg 'Global symbol """"%s"""" requires explicit package name'). -# Therefore treat all warnings as fatal. - -sub throw_exception { - die shift ; -} - -sub eval_file { - my ($filename, $delete, undef, $plugin_args) = @_ ; - - my $mtime = -M $filename ; - my $ts = localtime(time()) - if DEBUG_LEVEL ; - - - if ( - exists($Cache{$filename}) && - $Cache{$filename}[MTIME] && - $Cache{$filename}[MTIME] <= $mtime - ) { - # We have compiled this plugin before and - # it has not changed on disk; nothing to do except - # 1 parse the plugin arguments and cache them (to save - # repeated parsing of the same args) - the same - # plugin could be called with different args. - # 2 return the error from a former compilation - # if there was one. - - $Cache{$filename}[PLUGIN_ARGS]{$plugin_args} ||= [ parse_line('\s+', 0, $plugin_args) ] - if $plugin_args ; - - if ( $Cache{$filename}[PLUGIN_ERROR] ) { - print LH qq($ts eval_file: $filename failed compilation formerly and file has not changed; skipping compilation.\n) - if DEBUG_LEVEL & LEAVE_MSG ; - die qq(**ePN failed to compile $filename: "$Cache{$filename}[PLUGIN_ERROR]") ; - } else { - print LH qq($ts eval_file: $filename already successfully compiled and file has not changed; skipping compilation.\n) - if DEBUG_LEVEL & LEAVE_MSG ; - return $Cache{$filename}[PLUGIN_HNDLR] ; - } - } - - my $package = valid_package_name($filename) ; - - $Cache{$filename}[PLUGIN_ARGS]{$plugin_args} ||= [ parse_line('\s+', 0, $plugin_args) ] - if $plugin_args ; - - local *FH; - # die will be trapped by caller (checking ERRSV) - open FH, $filename - or die qq(**ePN failed to open "$filename": "$!") ; - - my $sub ; - sysread FH, $sub, -s FH ; - close FH; - # Cater for scripts that have embedded EOF symbols (__END__) - # XXXX - # Doesn't make sense to me. - - # $sub =~ s/__END__/\;}\n__END__/; - # Wrap the code into a subroutine inside our unique package - # (using $_ here [to save a lexical] is not a good idea since - # the definition of the package is visible to any other Perl - # code that uses [non localised] $_). - my $hndlr = <>> -$sub - # <<< END of PLUGIN >>> -} -EOSUB - - $Cache{$filename}[MTIME] = $mtime - unless $delete ; - # Suppress warning display. - local $SIG{__WARN__} = \&throw_exception ; - - - # Following 3 lines added 10/18/07 by Larry Low to fix problem where - # modified Perl plugins didn't get recached by the epn - no strict 'refs'; - undef %{$package.'::'}; - use strict 'refs'; - - # Compile &$package::hndlr. Since non executable code is being eval'd - # there is no need to protect lexicals in this scope. - eval $hndlr; - - # $@ is set for any warning and error. - # This guarantees that the plugin will not be run. - if ($@) { - # Report error line number wrt to original plugin text (7 lines added by eval_file). - # Error text looks like - # 'Use of uninitialized ..' at (eval 23) line 186, line 218 - # The error line number is 'line 186' - chomp($@) ; - $@ =~ s/line (\d+)[\.,]/'line ' . ($1 - 7) . ','/e ; - - print LH qq($ts eval_file: syntax error in $filename: "$@".\n) - if DEBUG_LEVEL & LEAVE_MSG ; - - if ( DEBUG_LEVEL & PLUGIN_DUMP ) { - my $i = 1 ; - $_ = $hndlr ; - s/^/sprintf('%10d ', $i++)/meg ; - # Will only get here once (when a faulty plugin is compiled). - # Therefore only _faulty_ plugins are dumped once each time the text changes. - - print PH qq($ts eval_file: transformed plugin "$filename" to ==>\n$_\n) ; - } - - $@ = substr($@, 0, 4096) - if length($@) > 4096 ; - - $Cache{$filename}[PLUGIN_ERROR] = $@ ; - # If the compilation fails, leave nothing behind that may affect subsequent - # compilations. This will be trapped by caller (checking ERRSV). - die qq(**ePN failed to compile $filename: "$@") ; - - } else { - $Cache{$filename}[PLUGIN_ERROR] = '' ; - } - - print LH qq($ts eval_file: successfully compiled "$filename $plugin_args".\n) - if DEBUG_LEVEL & LEAVE_MSG ; - - print CH qq($ts eval_file: after $Current_Run compilations \%Cache =>\n), Data::Dumper->Dump([\%Cache], [qw(*Cache)]), "\n" - if ( (DEBUG_LEVEL & CACHE_DUMP) && (++$Current_Run % Cache_Dump_Interval == 0) ) ; - - no strict 'refs' ; - return $Cache{$filename}[PLUGIN_HNDLR] = *{ $package . '::hndlr' }{CODE} ; - -} - -sub run_package { - my ($filename, undef, $plugin_hndlr_cr, $plugin_args) = @_; - # Second parm (after $filename) _may_ be used to wallop stashes. - - my $res = 3 ; - my $ts = localtime(time()) - if DEBUG_LEVEL ; - - local $SIG{__WARN__} = \&throw_exception ; - my $stdout = tie (*STDOUT, 'OutputTrap'); - my @plugin_args = $plugin_args ? @{ $Cache{$filename}[PLUGIN_ARGS]{$plugin_args} } : () ; - - # If the plugin has args, they have been cached by eval_file. - # ( cannot cache @plugin_args here because run_package() is - # called by child processes so cannot update %Cache.) - - eval { $plugin_hndlr_cr->(@plugin_args) } ; - - if ($@) { - # Error => normal plugin termination (exit) || run time error. - $_ = $@ ; - /^ExitTrap: (-?\d+)/ ? $res = $1 : - # For normal plugin exit, $@ will always match /^ExitTrap: (-?\d+)/ - /^ExitTrap: / ? $res = 0 : do { - # Run time error/abnormal plugin termination. - - chomp ; - # Report error line number wrt to original plugin text (7 lines added by eval_file). - s/line (\d+)[\.,]/'line ' . ($1 - 7) . ','/e ; - print STDOUT qq(**ePN $filename: "$_".\n) ; - } ; - - ($@, $_) = ('', '') ; - } - # ! Error => Perl code is not a plugin (fell off the end; no exit) - - # !! (read any output from the tied file handle.) - my $plugin_output = ; - - undef $stdout ; - untie *STDOUT; - - print LH qq($ts run_package: "$filename $plugin_args" returning ($res, "$plugin_output").\n) - if DEBUG_LEVEL & LEAVE_MSG ; - - return ($res, $plugin_output) ; -} - -1; - -=head1 NAME - -p1.pl - Perl program to provide Perl code persistence for the Nagios project (http://www.Nagios.Org). - -This program provides an API for calling Nagios Perl plugins from Nagios when it is built with embedded Perl support. The -intent is to tradeoff memory usage (see BUGS) against repeated context switches to recompile Perl plugins. - -=head1 SYNOPSIS - - -B - - /* 1 Initialise Perl - see perlembed - maintaining a persistent interpreter> */ - /* 2 Push the arguments (char *args[]) of call_pv() onto the Perl stack */ - /* 3 Compile the plugin - char *args[] is an array of pointers to strings required by p1.pl */ - - call_pv("Embed::Persistent::eval_file", G_SCALAR | G_EVAL) - - /* 4 if (SvTrue(ERRSV)) */ - goto outahere ; - - /* 5 Pop the code reference to the Perl sub (corresp to the plugin) returned by Perl */ - /* 6 Push the arguments (char *args[]) of call_pv() onto the Perl stack */ - /* 7 Run the plugin */ - - call_pv("Embed::Persistent::run_package", G_ARRAY) - - /* 8 example arguments for call_ functions */ - - args = { "check_rcp", /* pointer to plugin file name */ - "1", /* 1 to recompile plugins each time */ - "", /* temporary file name - no longer used */ - "-H sundev -C nfs" /* pointer to plugin argument string */ - } - -B - - my ($plugin_file, $plugin_args) = split(/\s+/, $_, 2) ; - my $plugin_hndlr_cr ; - eval { - - # 'eval {}' simulates the G_EVAL flag to perl_call_argv('code', 'flags') - # Otherwise, die in 'eval_file' will end the caller also. - - $plugin_hndlr_cr = Embed::Persistent::eval_file($plugin_file, 0, '', $plugin_args) ; - - } ; - - if ( $@) { - print "plugin compilation failed.\n" ; - } else { - my ($rc, $output) = Embed::Persistent::run_package($plugin_file, 0, $plugin_hndlr_cr, $plugin_args) ; - printf "embedded perl plugin return code and output was: %d & %s\n", $rc, $output) ; - -In the p1.pl text, 'use constant' statements set the log path and the log level. - -The log level flags determine the amount and type of messages logged in the log path. - -The default log level results in similar behaviour to former versions of p1.pl - -log files will B be opened. - -If you want to enable logging - -=over 4 - -=item 1 Choose log options (see below) - -=item 2 Choose a log path - -=item 3 Edit p1.pl - -=back - -Set the values of (the 'use constant' statements) the log path, B, and set the B constant to -one or more of the log options (B and friends ) or'ed together. -The default is to log nothing and to use S</var/epn_stderr.log> as the log path. - -=head1 DESCRIPTION - -Nagios is a program to monitor service availability by scheduling 'plugins' - discrete programs -that check a service (by for example simulating a users interaction with a web server using WWW::Mechanize) and output a line of -text (the summary of the service state) for those responsible for the service, and exit with a coded value to relay the same information to Nagios. - -Each plugin is run in a new child process forked by Nagios. - -Plugins, like CGIs, can be coded in Perl. The persistence framework embeds a Perl interpreter in Nagios to - -=over 4 - -=item * reduce the time taken for the Perl compile and execute cycle. - -=item * eliminate the need for Nagios to fork a process (with popen) to run the Perl code. - -=item * eliminate reloading of frequently used modules. - -=back - -and all the good things mentioned in the B man page under 'Maintaining a persistent interpreter'. - -Plugin run-time and syntax errors, are returned to Nagios as the 'plugin output'. These messages -appear in the Nagios log like S<**ePN 'check_test' Global symbol "$status" requires explicit package name at (eval 54) line 15.> - -Extra logging is given by setting DEBUG_LEVEL to include - - -B - -B<1> opens an extra output stream in the path given by the value of DEBUG_LOG_PATH - -B<2> logs messages describing the success or otherwise of the plugin compilation and the result of the plugin run. - -An example of such messages are - - Fri Apr 22 11:54:21 2005 eval_file: successfully compiled "/usr/local/nagios/libexec/check_bass ". - Fri Apr 22 11:54:21 2005 run_package: "/usr/local/nagios/libexec/check_bass " returning ("0", "BASS Transaction completed Ok. - "). - Fri Apr 22 11:55:02 2005 eval_file: successfully compiled "/usr/local/nagios/libexec/check_ad -D production.prod -S". - Fri Apr 22 11:55:02 2005 run_package: "/usr/local/nagios/libexec/check_ad -D foo.dom -S" returning ("0", "Ok. Expected 2 domain controllers [foo1 foo2] for "foo.dom.prod" domain from "1.1.2.3" DNS, found 8 [foo1 foo2 ..] - "). - Fri Apr 22 11:55:19 2005 eval_file: successfully compiled "/usr/local/nagios/libexec/check_ldap adonis". - Fri Apr 22 11:55:19 2005 run_package: "/usr/local/nagios/libexec/check_ldap adonis" returning ("0", "Ok. Schema query response DN: dc=ipaustralia,dc=gov,dc=au aci: (target="ldap:///dc=ipaustralia,dc=gov,dc=au")(targetattr!="userPassword")(targetfi - "). - Fri Apr 22 11:55:29 2005 eval_file: successfully compiled "/usr/local/nagios/libexec/check_scheduler -H aphrodite -p 7003". - Fri Apr 22 11:55:30 2005 eval_file: successfully compiled "/usr/local/nagios/libexec/check_pams -H aphrodite -p 7003 -R". - Fri Apr 22 11:55:29 2005 run_package: "/usr/local/nagios/libexec/check_scheduler -H aphrodite -p 7003" returning ("0", "Ok. COMSQ last ran 31 seconds ago. System: 0.02s Number of jobs waiting 0 "Detail" system sch_V2_6 14/01/2005 12:22:53 aimali Jobs: COMSQ/PollerManager Fri Apr 22 11:55:00, adhoc pause Fri Apr 22 09:00:00, PAMS/SchedExamDocCheck Thu Apr 21 23:00:00, CFX Cl" - ). - Fri Apr 22 11:55:30 2005 run_package: "/usr/local/nagios/libexec/check_pams -H aphrodite -p 7003 -R" returning ("0", "OK PAMS Worst: Test Time 2.61 Failure Ratio 0 [0:5] Statii: BASE OK Oracle (direct) OK COMS Processor OK CCS Name Search (direct) OK Correspondence Manager OK PAMS Tier OK CASEWORK OK Objective (direct) OK Customer Manager OK - "). - Fri Apr 22 11:55:45 2005 eval_file: successfully compiled "/usr/local/nagios/libexec/check_coms ". - Fri Apr 22 11:55:45 2005 run_package: "/usr/local/nagios/libexec/check_coms " returning ("0", "COMS Ok. 11 successes 20 minutes ago. 55 minute deltas: (0 0 0 11 0 1 3 4 0 6) or graph - ) - - .. after all the plugins are compiled, the 'successfully compiled mesages' are replaced by 'skipping compilation' - - Fri Apr 22 12:05:10 2005 eval_file: /usr/local/nagios/libexec/check_adds already successfully compiled and file has not changed; skipping compilation. - Fri Apr 22 12:05:11 2005 eval_file: /usr/local/nagios/libexec/check_aub already successfully compiled and file has not changed; skipping compilation - . - Fri Apr 22 12:05:10 2005 run_package: "/usr/local/nagios/libexec/check_adds " returning ("0", "ADDS Transaction completed Ok. - "). - Fri Apr 22 12:05:13 2005 eval_file: /usr/local/nagios/libexec/check_eForm already successfully compiled and file has not changed; skipping compilation. - Fri Apr 22 12:05:13 2005 run_package: "/usr/local/nagios/libexec/check_eForm " returning ("0", "eForm Transaction completed Ok. - "). - Fri Apr 22 12:05:15 2005 eval_file: /usr/local/nagios/libexec/check_cfx_log already successfully compiled and file has not changed; skipping compilation. - Fri Apr 22 12:05:15 2005 run_package: "/usr/local/nagios/libexec/check_cfx_log -H faxgw1" returning ("0", "Ok. Last write of "//faxgw1/Faxloader$/cfxFaxLoaderClient.log" 0.0 minutes ago. File info (create, access, modify, write times): "Wed Mar 26 17:19:42 2003 Fri Apr 22 12:05:13 2005 Fri Apr 22 12:05:13 2005 Fri Apr 22 12:05:13 2005". - "). - Fri Apr 22 12:05:16 2005 eval_file: /usr/local/nagios/libexec/check_cfx_log already successfully compiled and file has not changed; skipping compilation. - Fri Apr 22 12:05:16 2005 run_package: "/usr/local/nagios/libexec/check_cfx_log -H faxgw2" returning ("0", "Ok. Last write of "//faxgw2/Faxloader$/cfxFaxLoaderClient.log" 0.3 minutes ago. File info (create, access, modify, write times): "Wed Mar 26 17:27:24 2003 Fri Apr 22 12:04:55 2005 Fri Apr 22 12:04:55 2005 Fri Apr 22 12:04:55 2005". - "). - Fri Apr 22 12:05:17 2005 eval_file: /usr/local/nagios/libexec/check_apps_asearch already successfully compiled and file has not changed; skipping compilation. - Fri Apr 22 12:05:18 2005 eval_file: /usr/local/nagios/libexec/check_aurioness already successfully compiled and file has not changed; skipping compi lation. - Fri Apr 22 12:05:11 2005 run_package: "/usr/local/nagios/libexec/check_aub " returning ("0", "AU-B Transaction completed Ok. - "). - -If you are lucky enough to have plugins with errors in them, - - Fri Apr 22 12:16:01 2005 run_package: "//usr/local/nagios/libexec/eventhandlers/restart_coldfusion OK SOFT" returning ("3", "**ePN "//usr/local/nagios/libexec/eventhandlers/restart_coldfusion": "Can't use string ("") as a subroutine ref while "strict refs" in use at /usr/local/nagios/bin/p1.pl line 291, line 218". - - -B - -B<1> opens an extra output stream in the path given by the value of DEBUG_LOG_PATH. - -B<2> logs a listing of the text of any B plugin - as transformed by the persistence framework. Note that plugins that compile -are B dumped. This option is only useful for investigating WTF a plugin that runs from the CLI does not run under Nagios with embedded Perl. - - Sat Apr 23 19:25:32 2005 eval_file: transformed plugin "check_dummy_plugin" to ==> - 1 package Embed::check_5fdummy_5fplugin; - 2 - 3 sub hndlr { - 4 @ARGV = @_ ; - 5 local $^W = 1 ; - 6 - 7 # <<< START of PLUGIN (first line of plugin is line 8 in the text) >>> - 8 #!/usr/bin/perl -w - 9 - 10 use strict - 11 # use strict ; - 12 - 13 my @texts = split(/\n/, < 0 ? 2 : 0 ; - 24 exit $rc ; - 25 - 26 - 27 # <<< END of PLUGIN >>> - 28 } - - -This listing is logged each time the plugin source file modification time stamp is changed (when the file is -compiled for the first time and then either by correcting a syntax error or touching the file). - -Note that the plugin text (lines 8 to 27 inclusive) has been transformed by the persistence framework as described below. - -B - -B<1> opens an extra output stream in the path given by the value of DEBUG_LOG_PATH. - -B<2> A dump of the %Cache data structure (showing the plugin file modification time, a hash keyed by the plugin argument string of arrays of parsed -arguments (if non null), the last compilation error, and a code ref to the Perl subroutine corresponding the plugin (this is undef if the plugin failed to compile). - - Sat Apr 23 19:24:59 2005 eval_file: after 5 compilations %Cache => - %Cache = ( - '/usr/local/nagios/libexec/check_adds' => [ - '100.230810185185', - undef, - '', - sub { "DUMMY" } - ], - 'check_adds' => [ - '3.96288194444444', - undef, - '', - sub { "DUMMY" } - ], - 'check_atmoss' => [ - '3.96288194444444', - undef, - '', - sub { "DUMMY" } - ], - '/usr/local/nagios/libexec/check_pams' => [ - '1.90859953703704', - { - '-R -I -H asterix -p 7003' => [ - '-R', - '-I', - '-H', - 'asterix', - '-p', - '7003' - ] - }, - sub { "DUMMY" } - ], - 'check_dummy_plugin' => [ - '3.96288194444444', - undef, - '', - sub { "DUMMY" } - ] - ); - .. - - - - -This dump is produced periodically: each B<$Cache_Dump_Interval> plugin compilations the %Cache data structure is dumped. - -=head1 SUBROUTINES - -Unless otherwise stated, all subroutines take two (4) arguments :- - -=over 4 - -=item 1 plugin_filename - char * (called from C) or scalar (called from Perl): the path to the plugin. - -=item 2 DO_CLEAN - boolean: set if plugin is not to be cached. Defaults to 0. - -Setting this flag means that the plugin is compiled each time it is executed. Nagios B sets this flag when the -Nagios is compiled with the configure setting --with-perlcache. - -=item 3 (SV *) code ref to the Perl subroutine corresponding to the plugin - -This argument is only used by run_package(); it is returned by eval_file(). - -=item 4 plugin arguments - char ** (called from C) or scalar (called from Perl); the plugin options and arguments - - -=back - -=over 4 - -=item Embed::Persistent::eval_file( plugin_filename, DO_CLEAN, "", plugin_arguments ) - -E<10> -Returns B a Perl code reference (an SV containing a hard reference to a subroutine) to the subroutine that -has been produced and compiled by eval_file, B raises an exception (by calling die) and setting the value of B or -B<$@> (if called from Perl). - - -eval_file() transforms the plugin to a subroutine in a package, by compiling the string containing the -transformed plugin, and caches the plugin file modification time (to avoid recompiling it), -the parsed plugin arguments. and either the error trapped when the plugin is compiled or a code reference to the -compiled subroutine representing the plugin. - -eval_file() caches these values in the cache named B<%Cache>. The plugin file name is the key to an array containing -the values illustrated above. - -If the plugin file has not been modified, eval_file returns the cached plugin error B the code ref to the plugin subroutine. - -Otherwise, the plugin is compiled into a subroutine in a new package by - -=over 4 - -=item 1 creating a package name from the plugin file name (C) - -=item 2 turning off subroutine redefinition warnings (C) - -=item 3 overriding CORE::GLOBAL::exit from within package main (C) - -This allows the plugin to both call exit without taking down the persistence framework, and to return the exit code to the -Nagios. - -=item 4 prepending the plugin text with code to let the plugin function as a subroutine. - -The plugin command line arguments are expected to be in @ARGV, so @ARGV is set to the subroutine arguments (@_). - -The new subroutine also sets the warning level to trap all warnings that may have been caused by -by the transformation (the -w option to Perl in the text is no longer significant (because the shebang line is not fed to exec()). - -=item 5 writing the plugin as the subroutine named B in the new package. - -=item 6 returning either a code reference to the subroutine named hndlr in the package named in item 1, OR the -compilation error trapped by eval 'string'. It is the callers responsibility to check either ERRSV (from C) or $@ (from Perl) -and skip run_package() if these values are true. - -=back - -=item Embed::Persistent::run_package( plugin_filename, DO_CLEAN, (SV *) plugin_hndlr_cr, plugin_argument_string ) - -E<10> -Returns (plugin_return_code, plugin_output) - -run_plugin() actually runs the plugins with the arguments contained in the (space separated string) 4th argument. - -=back - -=head1 DIFFERENCES FROM PERSISTENT.PL - -The example B takes no account of - -=over 4 - -=item * Capturing output from the Perl program being run - -This framework ties STDOUT to a scalar that stores the result of PRINT or PRINTF. - -=item * Running Perl programs in child processes - -This is the largest single difference between this framework and the example program persistent.pl. The example uses one -subroutine (eval_file()) to compile and run the program. This is unsuitable for a process like Nagios that -fork a new process to run a plugin. (It is unsuitable because were the child process -to call eval_file() and then the update its copy of %Cache, other child processes would not get the updated %Cache, -and would therefore recompile the plugin). - -Instead, eval_file() is split into two: eval_file() and run_package(). - -Eval_file is called by the Nagios parent process to compile the plugin -and update %Cache. Child processes forked in base/checks.c have the same copy of %Cache and call run_plugin() to check the -last compilation error (from %Cache) and run the plugin if the plugin was error free. - -=item * Dealing with Perl programs that call exit - -This framework redefines exit() to die emitting a string containing the plugin return code (the first argument of exit). -Since the plugin is run by eval(), B<$@> contains this string from which the return code is extracted. - -=item * Providing command line arguments to the Perl program - -This framework sets @ARGV in the B subroutine to the remaining subroutine arguments. - -All of these clever ideas came from, AFAIK, Stephen Davies. - -=back - -=head1 BUGS - -=item * MEMORY LEAK - - - -This framework does nothing to prevent the memory leaks mentioned in B, relying on operator intervention. - -Probably the best way of doing so is by periodically scheduling - -=over 4 - -=item 1 A check of the memory used by the Nagios process (by running for example the standard Nagios plugin check_procs) - -=item 2 Restarting Nagios with the (supplied with Nagios) startup script (restart command). - - -=back - -If you do periodically restart Nagios, make sure that - -=over 4 - -=item 1 plugins all set the PATH environment variable if they need other system binaries (otherwise, if the -init script is excec'd by cron, the PATH will be reset and the plugins will fail - but only when reatsrted by cron). - -=item 2 that the group owning the Nagios command pipe is the same as the Nagios group (otherwise, the restarted -Nagios will not be able to read from the command pipe). - -=back - -Nagios installations using the persistence framework B monitor the memory use of the Nagios process and stop/start it when -the usage is exorbidant (eg, for a site with 400 services on 200 hosts and custom Perl plugins used for about 10% of the -service checks, the Nagios process uses ~80 MB after 20-30 days runningi with Perl 5.005 [Memory usage is -B greater with recent Perls]. It is usually stopped and started at this point). - -Note that a HUP signal is B sufficient to deallocate the Perl memory; the Nagios process must be stopped and started. In fact, since HUP -causes Nagios to re-run the Perl interpreter initialisation code, memory use increases significantly. B; use the 'restart' argument -of the Nagios supplied startup script. - -There are all sorts of suprising gotchas about the debug logging including - -=over 4 - -=item * No dump of good plugins. - -Only plugins that fail to compile (after transformation) are dumped. - -=item * Cache dump is periodic - -The Cache is only dumped after the user specified number of plugin B. If plugins are not compiled, you get -no dump of the cache. - -=item * Debug level set at compile time - -Nagios must be restarted to change the debug level (use the examples if you have a troublesome plugin;l you may need a debug copy -of Nagios) - -=item * Not all Cached fields visible - -Always compile one more plugin to ensure that all the fields in the cache are set. - - -=back - -=head1 SEE ALSO - -=over 4 - -=item * perlembed (section on maintaining a persistent interpreter) - -=item * examples in the examples/ directory including both C and Perl drivers that run Nagios plugins using p1.pl. - -=back - - -=head1 AUTHOR - -Originally by Stephen Davies. - -Now maintained by Stanley Hopcroft who retains responsibility for the 'bad bits'. - -=head1 COPYRIGHT - -Copyright (c) 2004 Stanley Hopcroft. All rights reserved. -This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. - -=cut - diff --git a/sample-config/README b/sample-config/README index be16b80..eacaa41 100644 --- a/sample-config/README +++ b/sample-config/README @@ -18,7 +18,7 @@ cgi.cfg - This is a sample CGI config file nagios.cfg - This is a sample main config file -resource.cfg - This is a sample resource config file, used for definining +resource.cfg - This is a sample resource config file, used for defining custom macros, storing sensitive data, etc. httpd.conf - This file contains sample snippets that you'll need to diff --git a/sample-config/cgi.cfg.in b/sample-config/cgi.cfg.in index c36fb28..c93e6ee 100644 --- a/sample-config/cgi.cfg.in +++ b/sample-config/cgi.cfg.in @@ -2,7 +2,6 @@ # # CGI.CFG - Sample CGI Configuration File for Nagios @VERSION@ # -# Last Modified: 06-17-2009 # ################################################################# @@ -57,7 +56,6 @@ use_pending_states=1 - # AUTHENTICATION USAGE # This option controls whether or not the CGIs will use any # authentication when displaying host and service information, as @@ -79,7 +77,6 @@ use_authentication=1 - # x509 CERT AUTHENTICATION # When enabled, this option allows you to use x509 cert (SSL) # authentication in the CGIs. This is an advanced option and should @@ -89,7 +86,6 @@ use_ssl_authentication=0 - # DEFAULT USER # Setting this variable will define a default user name that can # access pages without authentication. This allows people within a @@ -153,7 +149,6 @@ authorized_for_system_commands=nagiosadmin # you choose to not use authorization). You may use an asterisk (*) # to authorize any user who has authenticated to the web server. - authorized_for_all_services=nagiosadmin authorized_for_all_hosts=nagiosadmin @@ -183,7 +178,6 @@ authorized_for_all_host_commands=nagiosadmin - # STATUSMAP BACKGROUND IMAGE # This option allows you to specify an image to be used as a # background in the statusmap CGI. It is assumed that the image @@ -192,14 +186,13 @@ authorized_for_all_host_commands=nagiosadmin # to the path specified by the 'physical_html_path' directive. # Note: The image file may be in GIF, PNG, JPEG, or GD2 format. # However, I recommend that you convert your image to GD2 format -# (uncompressed), as this will cause less CPU load when the CGI -# generates the image. +# (uncompressed) but ONLY IF YOU WILL USE THE LEGACY MAP EXCLUSIVELY, +# as this will cause less CPU load when the CGI generates the image. #statusmap_background_image=smbackground.gd2 - # STATUSMAP TRANSPARENCY INDEX COLOR # These options set the r,g,b values of the background color used the statusmap CGI, # so normal browsers that can't show real png transparency set the desired color as @@ -212,20 +205,33 @@ authorized_for_all_host_commands=nagiosadmin - # DEFAULT STATUSMAP LAYOUT METHOD # This option allows you to specify the default layout method # the statusmap CGI should use for drawing hosts. If you do -# not use this option, the default is to use user-defined -# coordinates. Valid options are as follows: +# not use this option, the default for the legacy map is to use +# user-defined coordinates and the default for the new map is "6" +# (Circular Balloon). +# Valid options for the legacy map are as follows: # 0 = User-defined coordinates # 1 = Depth layers -# 2 = Collapsed tree -# 3 = Balanced tree -# 4 = Circular -# 5 = Circular (Marked Up) +# 2 = Collapsed tree +# 3 = Balanced tree +# 4 = Circular +# 5 = Circular (Marked Up) +# Valid options for the new map are as follows: +# 0 = User-defined coordinates +# 1 = Depth Layers (Horizontal) +# 2 = Collapsed tree (Horizontal) +# 3 = Balanced tree (Horizontal) +# 4 = DON'T USE +# 5 = Circular Markup +# 6 = Circular Balloon +# 7 = Balanced tree (Vertical) +# 8 = Collapsed tree (Vertical) +# 9 = Depth Layers (Vertical) +# 10 = Force Map -default_statusmap_layout=5 +#default_statusmap_layout=6 @@ -274,6 +280,8 @@ ping_syntax=/bin/ping -n -U -c 5 $HOSTADDRESS$ refresh_rate=90 + + # DEFAULT PAGE LIMIT # This option allows you to specify the default number of results # displayed on the status.cgi. This number can be adjusted from @@ -283,6 +291,7 @@ refresh_rate=90 result_limit=100 + # ESCAPE HTML TAGS # This option determines whether HTML tags in host and service # status output is escaped in the web interface. If enabled, @@ -292,7 +301,6 @@ escape_html_tags=1 - # SOUND OPTIONS # These options allow you to specify an optional audio file # that should be played in your browser window when there are @@ -328,7 +336,6 @@ notes_url_target=_blank - # LOCK AUTHOR NAMES OPTION # This option determines whether users can change the author name # when submitting comments, scheduling downtime. If disabled, the @@ -340,7 +347,6 @@ lock_author_names=1 - # SPLUNK INTEGRATION OPTIONS # These options allow you to enable integration with Splunk # in the web interface. If enabled, you'll be presented with @@ -355,10 +361,36 @@ lock_author_names=1 #enable_splunk_integration=1 - # This option should be the URL used to access your instance of Splunk - #splunk_url=http://127.0.0.1:8000/ +# NAVIGATION BAR SEARCH OPTIONS +# The following options allow to configure the navbar search. Default +# is to search for hostnames. With enabled navbar_search_for_addresses, +# the navbar search queries IP addresses as well. It's also possible +# to enable search for aliases by setting navbar_search_for_aliases=1. + +navbar_search_for_addresses=1 +navbar_search_for_aliases=1 + + + +# DEFAULTS FOR CHECKBOXES FOR ACKNOWLEDGEMENTS +# Enabling ack_no_sticky will default the "Sticky Acknowledgement" to +# be unchecked. +# Enabling ack_no_send will default the "Send Notification" to +# be unchecked. + +#ack_no_sticky=0 +#ack_no_send=0 + + + +# SHOW ONLY HARD STATES IS TACTICAL OVERVIEW +# This option controls whether only HARD states are counted on the +# Tactical Overview, or if both HARD and SOFT states are counted. +# Set to 1 to show only HARD states. Defaults to 0 (HARD+SOFT). + +#tac_cgi_hard_only=0 diff --git a/sample-config/httpd.conf.in b/sample-config/httpd.conf.in index 71d4fbb..a98e998 100644 --- a/sample-config/httpd.conf.in +++ b/sample-config/httpd.conf.in @@ -1,5 +1,4 @@ # SAMPLE CONFIG SNIPPETS FOR APACHE WEB SERVER -# Last Modified: 11-26-2005 # # This file contains examples of entries that need # to be incorporated into your Apache web server @@ -12,15 +11,29 @@ ScriptAlias @cgiurl@ "@sbindir@" # SSLRequireSSL Options ExecCGI AllowOverride None - Order allow,deny - Allow from all -# Order deny,allow -# Deny from all -# Allow from 127.0.0.1 - AuthName "Nagios Access" - AuthType Basic - AuthUserFile @sysconfdir@/htpasswd.users - Require valid-user + = 2.3> + + Require all granted +# Require host 127.0.0.1 + + AuthName "Nagios Access" + AuthType Basic + AuthUserFile @sysconfdir@/htpasswd.users + Require valid-user + + + + Order allow,deny + Allow from all +# Order deny,allow +# Deny from all +# Allow from 127.0.0.1 + + AuthName "Nagios Access" + AuthType Basic + AuthUserFile @sysconfdir@/htpasswd.users + Require valid-user + Alias @htmurl@ "@datadir@" @@ -29,14 +42,27 @@ Alias @htmurl@ "@datadir@" # SSLRequireSSL Options None AllowOverride None - Order allow,deny - Allow from all -# Order deny,allow -# Deny from all -# Allow from 127.0.0.1 - AuthName "Nagios Access" - AuthType Basic - AuthUserFile @sysconfdir@/htpasswd.users - Require valid-user - + = 2.3> + + Require all granted +# Require host 127.0.0.1 + AuthName "Nagios Access" + AuthType Basic + AuthUserFile @sysconfdir@/htpasswd.users + Require valid-user + + + + Order allow,deny + Allow from all +# Order deny,allow +# Deny from all +# Allow from 127.0.0.1 + + AuthName "Nagios Access" + AuthType Basic + AuthUserFile @sysconfdir@/htpasswd.users + Require valid-user + + diff --git a/sample-config/nagios.cfg.in b/sample-config/nagios.cfg.in index 1c2718e..d394c4a 100644 --- a/sample-config/nagios.cfg.in +++ b/sample-config/nagios.cfg.in @@ -6,7 +6,6 @@ # file. I've provided some comments here, but things may not be so # clear without further explanation. # -# Last Modified: 12-14-2008 # ############################################################################## @@ -144,24 +143,6 @@ check_external_commands=1 -# EXTERNAL COMMAND CHECK INTERVAL -# This is the interval at which Nagios should check for external commands. -# This value works of the interval_length you specify later. If you leave -# that at its default value of 60 (seconds), a value of 1 here will cause -# Nagios to check for external commands every minute. If you specify a -# number followed by an "s" (i.e. 15s), this will be interpreted to mean -# actual seconds rather than a multiple of the interval_length variable. -# Note: In addition to reading the external command file at regularly -# scheduled intervals, Nagios will also check for external commands after -# event handlers are executed. -# NOTE: Setting this value to -1 causes Nagios to check the external -# command file as often as possible. - -#command_check_interval=15s -command_check_interval=-1 - - - # EXTERNAL COMMAND FILE # This is the file that Nagios checks for external command requests. # It is also where the command CGI will write commands that are submitted @@ -174,13 +155,10 @@ command_file=@localstatedir@/rw/nagios.cmd -# EXTERNAL COMMAND BUFFER SLOTS -# This settings is used to tweak the number of items or "slots" that -# the Nagios daemon should allocate to the buffer that holds incoming -# external commands before they are processed. As external commands -# are processed by the daemon, they are removed from the buffer. +# QUERY HANDLER INTERFACE +# This is the socket that is created for the Query Handler interface -external_command_buffer_slots=4096 +#query_socket=@localstatedir@/rw/nagios.qh @@ -224,7 +202,7 @@ event_broker_options=-1 # This directive is used to specify an event broker module that should # by loaded by Nagios at startup. Use multiple directives if you want # to load more than one module. Arguments that should be passed to -# the module at startup are seperated from the module path by a space. +# the module at startup are separated from the module path by a space. # #!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! # WARNING !!! WARNING !!! WARNING !!! WARNING !!! WARNING !!! WARNING @@ -321,6 +299,15 @@ log_initial_states=0 +# CURRENT STATES LOGGING OPTION +# If you don't want Nagios to log all current host and service states +# after log has been rotated to the main log file, you can disable this +# option by setting this value to 0. Default value is 1. + +log_current_states=1 + + + # EXTERNAL COMMANDS LOGGING OPTION # If you don't want Nagios to log external commands, set this value # to 0. If external commands should be logged, set this value to 1. @@ -590,14 +577,6 @@ auto_rescheduling_window=180 -# SLEEP TIME -# This is the number of seconds to sleep between checking for system -# events and service checks that need to be run. - -sleep_time=0.25 - - - # TIMEOUT VALUES # These options control how much time Nagios will allow various # types of commands to execute before killing them off. Options @@ -726,14 +705,14 @@ interval_length=60 # patches to Nagios. Nagios is critical to you - make sure you keep it in # good shape. Nagios will check once a day for new updates. Data collected # by Nagios Enterprises from the update check is processed in accordance -# with our privacy policy - see http://api.nagios.org for details. +# with our privacy policy - see https://api.nagios.org for details. check_for_updates=1 # BARE UPDATE CHECK -# This option deterines what data Nagios will send to api.nagios.org when +# This option determines what data Nagios will send to api.nagios.org when # it checks for updates. By default, Nagios will send information on the # current version of Nagios you have installed, as well as an indicator as # to whether this was a new installation or not. Nagios Enterprises uses @@ -850,8 +829,8 @@ process_performance_data=0 # Performance data is only written to these files if the # enable_performance_data option (above) is set to 1. -#host_perfdata_file=/tmp/host-perfdata -#service_perfdata_file=/tmp/service-perfdata +#host_perfdata_file=@localstatedir@/host-perfdata +#service_perfdata_file=@localstatedir@/service-perfdata @@ -873,7 +852,7 @@ process_performance_data=0 # performance data files are opened in write ("w") or append ("a") # mode. If you want to use named pipes, you should use the special # pipe ("p") mode which avoid blocking at startup, otherwise you will -# likely want the defult append ("a") mode. +# likely want the default append ("a") mode. #host_perfdata_file_mode=a #service_perfdata_file_mode=a @@ -902,7 +881,7 @@ process_performance_data=0 # HOST AND SERVICE PERFORMANCE DATA PROCESS EMPTY RESULTS -# THese options determine wether the core will process empty perfdata +# These options determine wether the core will process empty perfdata # results or not. This is needed for distributed monitoring, and intentionally # turned on by default. # If you don't require empty perfdata - saving some cpu cycles @@ -1136,37 +1115,6 @@ date_format=us - -# P1.PL FILE LOCATION -# This value determines where the p1.pl perl script (used by the -# embedded Perl interpreter) is located. If you didn't compile -# Nagios with embedded Perl support, this option has no effect. - -p1_file=@bindir@/p1.pl - - - -# EMBEDDED PERL INTERPRETER OPTION -# This option determines whether or not the embedded Perl interpreter -# will be enabled during runtime. This option has no effect if Nagios -# has not been compiled with support for embedded Perl. -# Values: 0 = disable interpreter, 1 = enable interpreter - -enable_embedded_perl=1 - - - -# EMBEDDED PERL USAGE OPTION -# This option determines whether or not Nagios will process Perl plugins -# and scripts with the embedded Perl interpreter if the plugins/scripts -# do not explicitly indicate whether or not it is okay to do so. Read -# the HTML documentation on the embedded Perl interpreter for more -# information on how this option works. - -use_embedded_perl_implicitly=1 - - - # ILLEGAL OBJECT NAME CHARACTERS # This option allows you to specify illegal characters that cannot # be used in host names, service descriptions, or names of other @@ -1183,10 +1131,12 @@ illegal_object_name_chars=`~!$%^&*|'"<>?,()= # host check commands. # The following macros are stripped of the characters you specify: # $HOSTOUTPUT$ +# $LONGHOSTOUTPUT$ # $HOSTPERFDATA$ # $HOSTACKAUTHOR$ # $HOSTACKCOMMENT$ # $SERVICEOUTPUT$ +# $LONGSERVICEOUTPUT$ # $SERVICEPERFDATA$ # $SERVICEACKAUTHOR$ # $SERVICEACKCOMMENT$ @@ -1260,13 +1210,16 @@ use_large_installation_tweaks=0 # This option determines whether or not Nagios will make all standard # macros available as environment variables when host/service checks # and system commands (event handlers, notifications, etc.) are -# executed. Enabling this option can cause performance issues in -# large installations, as it will consume a bit more memory and (more -# importantly) consume more CPU. -# Values: 1 - Enable environment variable macros (default) -# 0 - Disable environment variable macros +# executed. +# Enabling this is a very bad idea for anything but very small setups, +# as it means plugins, notification scripts and eventhandlers may run +# out of environment space. It will also cause a significant increase +# in CPU- and memory usage and drastically reduce the number of checks +# you can run. +# Values: 1 - Enable environment variable macros +# 0 - Disable environment variable macros (default) -enable_environment_macros=1 +enable_environment_macros=0 @@ -1348,3 +1301,48 @@ debug_file=@localstatedir@/nagios.debug max_debug_file_size=1000000 + +# Should we allow hostgroups to have no hosts, we default this to off since +# that was the old behavior + +allow_empty_hostgroup_assignment=0 + + + +# Normally worker count is dynamically allocated based on 1.5 * number of cpu's +# with a minimum of 4 workers. This value will override the defaults + +#check_workers=3 + + + +# DISABLE SERVICE CHECKS WHEN HOST DOWN +# This option will disable all service checks if the host is not in an UP state +# +# While desirable in some environments, enabling this value can distort report +# values as the expected quantity of checks will not have been performed + +#host_down_disable_service_checks=0 + + + +# EXPERIMENTAL load controlling options +# To get current defaults based on your system issue a command to +# the query handler. Please note that this is an experimental feature +# and not meant for production use. Used incorrectly it can induce +# enormous latency. +# #core loadctl +# jobs_max - The maximum amount of jobs to run at one time +# jobs_min - The minimum amount of jobs to run at one time +# jobs_limit - The maximum amount of jobs the current load lets us run +# backoff_limit - The minimum backoff_change +# backoff_change - # of jobs to remove from jobs_limit when backing off +# rampup_limit - Minimum rampup_change +# rampup_change - # of jobs to add to jobs_limit when ramping up +# NOTE: The backoff_limit and rampup_limit are NOT used by anything currently, +# so if your system is under load nothing will actively modify the jobs +# even if you have these options enabled, they are for external +# connector information only. However, if you change the jobs_max or +# jobs_min manually here or through the query handler interface that +# WILL affect your system +#loadctl_options=jobs_max=100;backoff_limit=10;rampup_change=5 diff --git a/sample-config/resource.cfg.in b/sample-config/resource.cfg.in index 5227bc2..1994a1d 100644 --- a/sample-config/resource.cfg.in +++ b/sample-config/resource.cfg.in @@ -2,7 +2,6 @@ # # RESOURCE.CFG - Sample Resource File for Nagios @VERSION@ # -# Last Modified: 09-10-2003 # # You can define $USERx$ macros in this file, which can in turn be used # in command definitions in your host config file(s). $USERx$ macros are diff --git a/sample-config/template-object/commands.cfg.in b/sample-config/template-object/commands.cfg.in index acb3a4b..cc460bb 100644 --- a/sample-config/template-object/commands.cfg.in +++ b/sample-config/template-object/commands.cfg.in @@ -1,7 +1,6 @@ ############################################################################### # COMMANDS.CFG - SAMPLE COMMAND DEFINITIONS FOR NAGIOS @VERSION@ # -# Last Modified: 05-31-2007 # # NOTES: This config file provides you with some example command definitions # that you can reference in host, service, and contact definitions. diff --git a/sample-config/template-object/contacts.cfg.in b/sample-config/template-object/contacts.cfg.in index bb6b7bf..4c090ec 100644 --- a/sample-config/template-object/contacts.cfg.in +++ b/sample-config/template-object/contacts.cfg.in @@ -1,7 +1,6 @@ ############################################################################### # CONTACTS.CFG - SAMPLE CONTACT/CONTACTGROUP DEFINITIONS # -# Last Modified: 05-31-2007 # # NOTES: This config file provides you with some example contact and contact # group definitions that you can reference in host and service diff --git a/sample-config/template-object/localhost.cfg.in b/sample-config/template-object/localhost.cfg.in index 6882ced..f8bb741 100644 --- a/sample-config/template-object/localhost.cfg.in +++ b/sample-config/template-object/localhost.cfg.in @@ -1,7 +1,6 @@ ############################################################################### # LOCALHOST.CFG - SAMPLE OBJECT CONFIG FILE FOR MONITORING THIS MACHINE # -# Last Modified: 05-31-2007 # # NOTE: This config file is intended to serve as an *extremely* simple # example of how you can create configuration entries to monitor @@ -97,7 +96,7 @@ define service{ # Define a service to check the number of currently running procs # on the local machine. Warning if > 250 processes, critical if -# > 400 users. +# > 400 processes. define service{ use local-service ; Name of service template to use diff --git a/sample-config/template-object/printer.cfg.in b/sample-config/template-object/printer.cfg.in index 1de8855..125d1d6 100644 --- a/sample-config/template-object/printer.cfg.in +++ b/sample-config/template-object/printer.cfg.in @@ -1,7 +1,6 @@ ############################################################################### # PRINTER.CFG - SAMPLE CONFIG FILE FOR MONITORING A NETWORK PRINTER # -# Last Modified: 10-03-2007 # # NOTES: This config file assumes that you are using the sample configuration # files that get installed with the Nagios quickstart guide. @@ -68,18 +67,18 @@ define service{ host_name hplj2605dn ; The name of the host the service is associated with service_description Printer Status ; The service description check_command check_hpjd!-C public ; The command used to monitor the service - normal_check_interval 10 ; Check the service every 10 minutes under normal conditions - retry_check_interval 1 ; Re-check the service every minute until its final/hard state is determined + check_interval 10 ; Check the service every 10 minutes under normal conditions + retry_interval 1 ; Re-check the service every minute until its final/hard state is determined } -# Create a service for "pinging" the printer occassionally. Useful for monitoring RTA, packet loss, etc. +# Create a service for "pinging" the printer occasionally. Useful for monitoring RTA, packet loss, etc. define service{ use generic-service host_name hplj2605dn service_description PING check_command check_ping!3000.0,80%!5000.0,100% - normal_check_interval 10 - retry_check_interval 1 + check_interval 10 + retry_interval 1 } diff --git a/sample-config/template-object/switch.cfg.in b/sample-config/template-object/switch.cfg.in index 60c4db6..62d25e3 100644 --- a/sample-config/template-object/switch.cfg.in +++ b/sample-config/template-object/switch.cfg.in @@ -1,7 +1,6 @@ ############################################################################### # SWITCH.CFG - SAMPLE CONFIG FILE FOR MONITORING A SWITCH # -# Last Modified: 10-03-2007 # # NOTES: This config file assumes that you are using the sample configuration # files that get installed with the Nagios quickstart guide. @@ -65,8 +64,8 @@ define service{ host_name linksys-srw224p ; The name of the host the service is associated with service_description PING ; The service description check_command check_ping!200.0,20%!600.0,60% ; The command used to monitor the service - normal_check_interval 5 ; Check the service every 5 minutes under normal conditions - retry_check_interval 1 ; Re-check the service every minute until its final/hard state is determined + check_interval 5 ; Check the service every 5 minutes under normal conditions + retry_interval 1 ; Re-check the service every minute until its final/hard state is determined } diff --git a/sample-config/template-object/templates.cfg.in b/sample-config/template-object/templates.cfg.in index 16a980d..6647482 100644 --- a/sample-config/template-object/templates.cfg.in +++ b/sample-config/template-object/templates.cfg.in @@ -1,7 +1,6 @@ ############################################################################### # TEMPLATES.CFG - SAMPLE OBJECT TEMPLATES # -# Last Modified: 10-03-2007 # # NOTES: This config file provides you with some example object definition # templates that are refered by other host, service, contact, etc. @@ -54,7 +53,6 @@ define host{ notifications_enabled 1 ; Host notifications are enabled event_handler_enabled 1 ; Host event handler is enabled flap_detection_enabled 1 ; Flap detection is enabled - failure_prediction_enabled 1 ; Failure prediction is enabled process_perf_data 1 ; Process performance data retain_status_information 1 ; Retain status information across program restarts retain_nonstatus_information 1 ; Retain non-status information across program restarts @@ -160,15 +158,14 @@ define service{ notifications_enabled 1 ; Service notifications are enabled event_handler_enabled 1 ; Service event handler is enabled flap_detection_enabled 1 ; Flap detection is enabled - failure_prediction_enabled 1 ; Failure prediction is enabled process_perf_data 1 ; Process performance data retain_status_information 1 ; Retain status information across program restarts retain_nonstatus_information 1 ; Retain non-status information across program restarts is_volatile 0 ; The service is not volatile check_period 24x7 ; The service can be checked at any time of the day max_check_attempts 3 ; Re-check the service up to 3 times in order to determine its final (hard) state - normal_check_interval 10 ; Check the service every 10 minutes under normal conditions - retry_check_interval 2 ; Re-check the service every two minutes until a hard state can be determined + check_interval 10 ; Check the service every 10 minutes under normal conditions + retry_interval 2 ; Re-check the service every two minutes until a hard state can be determined contact_groups admins ; Notifications get sent out to everyone in the 'admins' group notification_options w,u,c,r ; Send notifications about warning, unknown, critical, and recovery events notification_interval 60 ; Re-notify about service problems every hour @@ -183,8 +180,8 @@ define service{ name local-service ; The name of this service template use generic-service ; Inherit default values from the generic-service definition max_check_attempts 4 ; Re-check the service up to 4 times in order to determine its final (hard) state - normal_check_interval 5 ; Check the service every 5 minutes under normal conditions - retry_check_interval 1 ; Re-check the service every minute until a hard state can be determined + check_interval 5 ; Check the service every 5 minutes under normal conditions + retry_interval 1 ; Re-check the service every minute until a hard state can be determined register 0 ; DONT REGISTER THIS DEFINITION - ITS NOT A REAL SERVICE, JUST A TEMPLATE! } diff --git a/sample-config/template-object/timeperiods.cfg.in b/sample-config/template-object/timeperiods.cfg.in index 7f1802e..8b6eddd 100644 --- a/sample-config/template-object/timeperiods.cfg.in +++ b/sample-config/template-object/timeperiods.cfg.in @@ -1,7 +1,6 @@ ############################################################################### # TIMEPERIODS.CFG - SAMPLE TIMEPERIOD DEFINITIONS # -# Last Modified: 05-31-2007 # # NOTES: This config file provides you with some example timeperiod definitions # that you can reference in host, service, contact, and dependency @@ -60,7 +59,7 @@ define timeperiod{ # Some U.S. holidays # Note: The timeranges for each holiday are meant to *exclude* the holidays from being # treated as a valid time for notifications, etc. You probably don't want your pager -# going off on New Year's. Although you're employer might... :-) +# going off on New Year's. Although your employer might... :-) define timeperiod{ name us-holidays timeperiod_name us-holidays diff --git a/sample-config/template-object/windows.cfg.in b/sample-config/template-object/windows.cfg.in index 264a63a..0ddcdc1 100644 --- a/sample-config/template-object/windows.cfg.in +++ b/sample-config/template-object/windows.cfg.in @@ -1,7 +1,6 @@ ############################################################################### # WINDOWS.CFG - SAMPLE CONFIG FILE FOR MONITORING A WINDOWS MACHINE # -# Last Modified: 06-13-2007 # # NOTES: This config file assumes that you are using the sample configuration # files that get installed with the Nagios quickstart guide. diff --git a/subst.in b/subst.in index a8e2c06..dc7f0aa 100755 --- a/subst.in +++ b/subst.in @@ -2,9 +2,12 @@ my ${exec_prefix}; my ${prefix}; +my ${datarootdir}; ${prefix}="@prefix@"; ${exec_prefix}="@exec_prefix@"; +${datarootdir}="@datarootdir@"; + while ($f = shift @ARGV) { if (-x "/bin/mktemp") { @@ -29,6 +32,7 @@ while ($f = shift @ARGV) { s|\@TMPDIR\@|@TMPDIR@|g; s|\@CHECKRESULTDIR\@|@CHECKRESULTDIR@|g; s|\@datadir\@|@datadir@|g; + s|\@datarootdir\@|@datarootdir@|g; s|\@sbindir\@|@sbindir@|g; s|\@bindir\@|@bindir@|g; s|\@htmurl\@|@htmurl@|g; diff --git a/t-tap/.gitignore b/t-tap/.gitignore index 3c8db7f..5e2d4ab 100644 --- a/t-tap/.gitignore +++ b/t-tap/.gitignore @@ -1,6 +1,7 @@ test_events test_logging test_checks +test_macros test_nagios_config test_timeperiods test_xsddefault diff --git a/t-tap/Makefile.in b/t-tap/Makefile.in index 2be4ae9..d347357 100644 --- a/t-tap/Makefile.in +++ b/t-tap/Makefile.in @@ -8,25 +8,28 @@ SRC_XDATA=../xdata SRC_BASE=../base SRC_CGI=../cgi SRC_COMMON=../common +SRC_LIB=../lib CC=@CC@ -CFLAGS=@CFLAGS@ @DEFS@ -DNSCORE -I../include -I../tap/src +CFLAGS=@CFLAGS@ @DEFS@ -DNSCORE -I../include -I../tap/src -I.. -TESTS = test_logging test_events test_timeperiods test_nagios_config -TESTS += test_xsddefault +TESTS = test_logging +TESTS += test_events TESTS += test_checks -TESTS += test_strtoul TESTS += test_commands TESTS += test_downtime +TESTS += test_nagios_config +TESTS += test_timeperiods +TESTS += test_macros XSD_OBJS = $(SRC_CGI)/statusdata-cgi.o $(SRC_CGI)/xstatusdata-cgi.o XSD_OBJS += $(SRC_CGI)/objects-cgi.o $(SRC_CGI)/xobjects-cgi.o XSD_OBJS += $(SRC_CGI)/comments-cgi.o $(SRC_CGI)/downtime-cgi.o -XSD_OBJS += $(SRC_CGI)/cgiutils.o $(SRC_CGI)/skiplist.o ../common/shared.o +XSD_OBJS += $(SRC_CGI)/cgiutils.o ../common/shared.o TP_OBJS = $(SRC_BASE)/utils.o $(SRC_BASE)/config.o $(SRC_BASE)/macros-base.o TP_OBJS += $(SRC_BASE)/objects-base.o $(SRC_BASE)/xobjects-base.o -TP_OBJS += $(SRC_BASE)/skiplist.o ../common/shared.o +TP_OBJS += ../common/shared.o CFG_OBJS = $(TP_OBJS) CFG_OBJS += $(SRC_BASE)/comments-base.o $(SRC_BASE)/xcomments-base.o @@ -35,7 +38,7 @@ CFG_OBJS += $(SRC_BASE)/retention-base.o $(SRC_BASE)/xretention-base.o LDFLAGS=@LDFLAGS@ -LIBS=@LIBS@ +LIBS=@LIBS@ ../lib/libnagios.a prefix=@prefix@ exec_prefix=@exec_prefix@ @@ -56,76 +59,56 @@ MATHLIBS=-lm PERLLIBS=@PERLLIBS@ PERLXSI_O=@PERLXSI_O@ SOCKETLIBS=@SOCKETLIBS@ -THREADLIBS=@THREADLIBS@ BROKERLIBS=@BROKERLIBS@ BROKER_LDFLAGS=@BROKER_LDFLAGS@ CP=@CP@ -# External data I/O code and headers -XSDC=@XSDC@ -XSDH=@XSDH@ -XCDC=@XCDC@ -XCDH=@XCDH@ -XRDC=@XRDC@ -XRDH=@XRDH@ -XODC=@XODC@ -XODH=@XODH@ -XPDC=@XPDC@ -XPDH=@XPDH@ -XDDC=@XDDC@ -XDDH=@XDDH@ - # Extra base code BASEEXTRALIBS=@BASEEXTRALIBS@ -# Generated automatically from configure script -SNPRINTF_O=@SNPRINTF_O@ -BROKER_O=@BROKER_O@ -BROKER_H=@BROKER_H@ - TAPOBJ=../tap/src/tap.o $(SNPRINTF_O) all: $(TESTS) ########## TESTS ########## -test_logging: test_logging.o $(SRC_BASE)/logging.o $(TAPOBJ) - $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) +test_logging: test_logging.o $(SRC_BASE)/logging.o $(TAPOBJ) $(SRC_COMMON)/shared.o $(SRC_BASE)/objects-base.o + $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) $(LIBS) -test_events: test_events.o $(SRC_BASE)/events.o $(TAPOBJ) - $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) $(MATHLIBS) $(LIBS) +test_events: test_events.o $(SRC_BASE)/events.o $(TAPOBJ) $(SRC_BASE)/utils.o $(SRC_COMMON)/shared.o $(SRC_BASE)/objects-base.o $(SRC_BASE)/checks.o $(SRC_LIB)/squeue.o $(SRC_LIB)/nsutils.o $(SRC_LIB)/kvvec.o $(SRC_LIB)/dkhash.o $(SRC_LIB)/pqueue.o $(SRC_BASE)/config.o $(SRC_LIB)/nspath.o $(SRC_BASE)/macros-base.o $(SRC_XDATA)/xodtemplate.o $(SRC_LIB)/bitmap.o $(SRC_LIB)/skiplist.o + $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) $(MATHLIBS) -test_checks: test_checks.o $(SRC_BASE)/checks.o $(TAPOBJ) +test_checks: test_checks.o $(SRC_BASE)/checks.o $(TAPOBJ) $(SRC_BASE)/utils.o $(SRC_COMMON)/shared.o $(SRC_BASE)/objects-base.o $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) $(MATHLIBS) $(LIBS) test_commands: test_commands.o $(SRC_COMMON)/shared.o $(TAPOBJ) - $(CC) $(CFLAGS) -o $@ $^ + $(CC) $(CFLAGS) -o $@ $^ $(LIBS) -test_downtime: test_downtime.o $(SRC_BASE)/downtime-base.o $(SRC_BASE)/xdowntime-base.o $(TAPOBJ) - $(CC) $(CFLAGS) -o $@ $^ +test_downtime: test_downtime.o $(SRC_BASE)/downtime-base.o $(SRC_BASE)/utils.o $(SRC_COMMON)/shared.o $(SRC_BASE)/config.o $(SRC_BASE)/objects-base.o $(SRC_BASE)/macros-base.o $(SRC_XDATA)/xodtemplate.o $(TAPOBJ) + $(CC) $(CFLAGS) -o $@ $^ $(LIBS) $(MATHLIBS) test_freshness: test_freshness.o $(SRC_BASE)/freshness.o $(TAPOBJ) $(CC) $(CFLAGS) -o $@ $^ -test_nagios_config: test_nagios_config.o $(CFG_OBJS) $(TAPOBJ) - $(CC) $(CFLAGS) -o $@ $^ $(BROKER_LDFLAGS) $(LDFLAGS) $(MATHLIBS) $(SOCKETLIBS) $(THREADLIBS) $(BROKERLIBS) $(LIBS) +test_nagios_config: test_nagios_config.o $(TAPOBJ) $(SRC_BASE)/utils.o $(SRC_BASE)/config.o $(SRC_XDATA)/xrddefault.o $(SRC_BASE)/comments-base.o $(SRC_BASE)/downtime-base.o $(SRC_COMMON)/shared.o $(SRC_BASE)/objects-base.o $(SRC_XDATA)/xcddefault.o $(SRC_XDATA)/xodtemplate.o $(SRC_BASE)/macros-base.o + $(CC) $(CFLAGS) -o $@ $^ $(BROKER_LDFLAGS) $(LDFLAGS) $(MATHLIBS) $(SOCKETLIBS) $(BROKERLIBS) $(LIBS) test_timeperiods: test_timeperiods.o $(TP_OBJS) $(TAPOBJ) - $(CC) $(CFLAGS) -o $@ $^ $(BROKER_LDFLAGS) $(LDFLAGS) $(MATHLIBS) $(SOCKETLIBS) $(THREADLIBS) $(BROKERLIBS) $(LIBS) + $(CC) $(CFLAGS) -o $@ $^ $(BROKER_LDFLAGS) $(LDFLAGS) $(MATHLIBS) $(SOCKETLIBS) $(BROKERLIBS) $(LIBS) + +test_macros: test_macros.o $(TP_OBJS) $(TAPOBJ) + $(CC) $(CFLAGS) -o $@ $^ $(BROKER_LDFLAGS) $(LDFLAGS) $(MATHLIBS) $(SOCKETLIBS) $(LIBS) test_xsddefault: test_xsddefault.o $(XSD_OBJS) $(TAPOBJ) $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) -test_strtoul: test_strtoul.c - $(CC) $(CFLAGS) -o $@ test_strtoul.c $(TAPOBJ) - test: $(TESTS) HARNESS_PERL=./test_each.t perl -MTest::Harness -e '$$Test::Harness::switches=""; runtests(map { "./$$_" } @ARGV)' $(TESTS) clean: - rm -f nagios nagiostats core *.o gmon.out + rm -f core core.* *.o gmon.out $(TESTS) rm -f *~ *.*~ distclean: clean diff --git a/t-tap/smallconfig/minimal.cfg b/t-tap/smallconfig/minimal.cfg index 0615efa..010e584 100644 --- a/t-tap/smallconfig/minimal.cfg +++ b/t-tap/smallconfig/minimal.cfg @@ -192,6 +192,12 @@ define timeperiod{ } +define timeperiod{ + timeperiod_name exclude_always + alias exclude_always + monday 00:00-24:00 + exclude 24x7 +} define contact { contact_name nagiosadmin diff --git a/t-tap/smallconfig/nagios.cfg b/t-tap/smallconfig/nagios.cfg index e538f9e..f374f1f 100644 --- a/t-tap/smallconfig/nagios.cfg +++ b/t-tap/smallconfig/nagios.cfg @@ -1,1307 +1,101 @@ -############################################################################## -# -# NAGIOS.CFG - Sample Main Config File for Nagios 3.1.0 -# -# Read the documentation for more information on this configuration -# file. I've provided some comments here, but things may not be so -# clear without further explanation. -# -# Last Modified: 12-14-2008 -# -############################################################################## - - -# LOG FILE -# This is the main log file where service and host events are logged -# for historical purposes. This should be the first option specified -# in the config file!!! - log_file=smallconfig/nagios.log - - - -# OBJECT CONFIGURATION FILE(S) -# These are the object configuration files in which you define hosts, -# host groups, contacts, contact groups, services, etc. -# You can split your object definitions across several config files -# if you wish (as shown below), or keep them all in a single config file. - -# Note: A relative path here is relative to the location of the overall nagios.cfg file, -# not relative to the current directory cfg_file=minimal.cfg - -# You can also tell Nagios to process all config files (with a .cfg -# extension) in a particular directory by using the cfg_dir -# directive as shown below: - -#cfg_dir=/usr/local/nagios/etc/servers -#cfg_dir=/usr/local/nagios/etc/printers -#cfg_dir=/usr/local/nagios/etc/switches -#cfg_dir=/usr/local/nagios/etc/routers - - - - -# OBJECT CACHE FILE -# This option determines where object definitions are cached when -# Nagios starts/restarts. The CGIs read object definitions from -# this cache file (rather than looking at the object config files -# directly) in order to prevent inconsistencies that can occur -# when the config files are modified after Nagios starts. - object_cache_file=smallconfig/objects.cache - - - -# PRE-CACHED OBJECT FILE -# This options determines the location of the precached object file. -# If you run Nagios with the -p command line option, it will preprocess -# your object configuration file(s) and write the cached config to this -# file. You can then start Nagios with the -u option to have it read -# object definitions from this precached file, rather than the standard -# object configuration files (see the cfg_file and cfg_dir options above). -# Using a precached object file can speed up the time needed to (re)start -# the Nagios process if you've got a large and/or complex configuration. -# Read the documentation section on optimizing Nagios to find our more -# about how this feature works. - precached_object_file=smallconfig/objects.precache - - - -# RESOURCE FILE -# This is an optional resource file that contains $USERx$ macro -# definitions. Multiple resource files can be specified by using -# multiple resource_file definitions. The CGIs will not attempt to -# read the contents of resource files, so information that is -# considered to be sensitive (usernames, passwords, etc) can be -# defined as macros in this file and restrictive permissions (600) -# can be placed on this file. - resource_file=smallconfig/resource.cfg - - - -# STATUS FILE -# This is where the current status of all monitored services and -# hosts is stored. Its contents are read and processed by the CGIs. -# The contents of the status file are deleted every time Nagios -# restarts. - status_file=smallconfig/status.dat - - - -# STATUS FILE UPDATE INTERVAL -# This option determines the frequency (in seconds) that -# Nagios will periodically dump program, host, and -# service status data. - status_update_interval=10 - - - -# NAGIOS USER -# This determines the effective user that Nagios should run as. -# You can either supply a username or a UID. - nagios_user=nagios - - - -# NAGIOS GROUP -# This determines the effective group that Nagios should run as. -# You can either supply a group name or a GID. - nagios_group=nagios - - - -# EXTERNAL COMMAND OPTION -# This option allows you to specify whether or not Nagios should check -# for external commands (in the command file defined below). By default -# Nagios will *not* check for external commands, just to be on the -# cautious side. If you want to be able to use the CGI command interface -# you will have to enable this. -# Values: 0 = disable commands, 1 = enable commands - check_external_commands=1 - - - -# EXTERNAL COMMAND CHECK INTERVAL -# This is the interval at which Nagios should check for external commands. -# This value works of the interval_length you specify later. If you leave -# that at its default value of 60 (seconds), a value of 1 here will cause -# Nagios to check for external commands every minute. If you specify a -# number followed by an "s" (i.e. 15s), this will be interpreted to mean -# actual seconds rather than a multiple of the interval_length variable. -# Note: In addition to reading the external command file at regularly -# scheduled intervals, Nagios will also check for external commands after -# event handlers are executed. -# NOTE: Setting this value to -1 causes Nagios to check the external -# command file as often as possible. - -#command_check_interval=15s -command_check_interval=-1 - - - -# EXTERNAL COMMAND FILE -# This is the file that Nagios checks for external command requests. -# It is also where the command CGI will write commands that are submitted -# by users, so it must be writeable by the user that the web server -# is running as (usually 'nobody'). Permissions should be set at the -# directory level instead of on the file, as the file is deleted every -# time its contents are processed. - command_file=smallconfig/nagios.cmd - - - -# EXTERNAL COMMAND BUFFER SLOTS -# This settings is used to tweak the number of items or "slots" that -# the Nagios daemon should allocate to the buffer that holds incoming -# external commands before they are processed. As external commands -# are processed by the daemon, they are removed from the buffer. - -external_command_buffer_slots=4096 - - - -# LOCK FILE -# This is the lockfile that Nagios will use to store its PID number -# in when it is running in daemon mode. - lock_file=smallconfig/nagios.lock - - - -# TEMP FILE -# This is a temporary file that is used as scratch space when Nagios -# updates the status log, cleans the comment file, etc. This file -# is created, used, and deleted throughout the time that Nagios is -# running. - temp_file=smallconfig/nagios.tmp - - - -# TEMP PATH -# This is path where Nagios can create temp files for service and -# host check results, etc. - temp_path=smallconfig - - - -# EVENT BROKER OPTIONS -# Controls what (if any) data gets sent to the event broker. -# Values: 0 = Broker nothing -# -1 = Broker everything -# = See documentation - event_broker_options=-1 - - - -# EVENT BROKER MODULE(S) -# This directive is used to specify an event broker module that should -# by loaded by Nagios at startup. Use multiple directives if you want -# to load more than one module. Arguments that should be passed to -# the module at startup are seperated from the module path by a space. -# -#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -# WARNING !!! WARNING !!! WARNING !!! WARNING !!! WARNING !!! WARNING -#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -# -# Do NOT overwrite modules while they are being used by Nagios or Nagios -# will crash in a fiery display of SEGFAULT glory. This is a bug/limitation -# either in dlopen(), the kernel, and/or the filesystem. And maybe Nagios... -# -# The correct/safe way of updating a module is by using one of these methods: -# 1. Shutdown Nagios, replace the module file, restart Nagios -# 2. Delete the original module file, move the new module file into place, restart Nagios -# -# Example: -# -# broker_module= [moduleargs] - -#broker_module=/somewhere/module1.o -#broker_module=/somewhere/module2.o arg1 arg2=3 debug=0 - - - -# LOG ROTATION METHOD -# This is the log rotation method that Nagios should use to rotate -# the main log file. Values are as follows.. -# n = None - don't rotate the log -# h = Hourly rotation (top of the hour) -# d = Daily rotation (midnight every day) -# w = Weekly rotation (midnight on Saturday evening) -# m = Monthly rotation (midnight last day of month) - log_rotation_method=d - - - -# LOG ARCHIVE PATH -# This is the directory where archived (rotated) log files should be -# placed (assuming you've chosen to do log rotation). - log_archive_path=smallconfig - - - -# LOGGING OPTIONS -# If you want messages logged to the syslog facility, as well as the -# Nagios log file set this option to 1. If not, set it to 0. - use_syslog=1 - - - -# NOTIFICATION LOGGING OPTION -# If you don't want notifications to be logged, set this value to 0. -# If notifications should be logged, set the value to 1. - log_notifications=1 - - - -# SERVICE RETRY LOGGING OPTION -# If you don't want service check retries to be logged, set this value -# to 0. If retries should be logged, set the value to 1. - log_service_retries=1 - - - -# HOST RETRY LOGGING OPTION -# If you don't want host check retries to be logged, set this value to -# 0. If retries should be logged, set the value to 1. - log_host_retries=1 - - - -# EVENT HANDLER LOGGING OPTION -# If you don't want host and service event handlers to be logged, set -# this value to 0. If event handlers should be logged, set the value -# to 1. - log_event_handlers=1 - - - -# INITIAL STATES LOGGING OPTION -# If you want Nagios to log all initial host and service states to -# the main log file (the first time the service or host is checked) -# you can enable this option by setting this value to 1. If you -# are not using an external application that does long term state -# statistics reporting, you do not need to enable this option. In -# this case, set the value to 0. - log_initial_states=0 - - - -# EXTERNAL COMMANDS LOGGING OPTION -# If you don't want Nagios to log external commands, set this value -# to 0. If external commands should be logged, set this value to 1. -# Note: This option does not include logging of passive service -# checks - see the option below for controlling whether or not -# passive checks are logged. - log_external_commands=1 - - - -# PASSIVE CHECKS LOGGING OPTION -# If you don't want Nagios to log passive host and service checks, set -# this value to 0. If passive checks should be logged, set -# this value to 1. - log_passive_checks=1 - - - -# GLOBAL HOST AND SERVICE EVENT HANDLERS -# These options allow you to specify a host and service event handler -# command that is to be run for every host or service state change. -# The global event handler is executed immediately prior to the event -# handler that you have optionally specified in each host or -# service definition. The command argument is the short name of a -# command definition that you define in your host configuration file. -# Read the HTML docs for more information. - -#global_host_event_handler=somecommand -#global_service_event_handler=somecommand - - - -# SERVICE INTER-CHECK DELAY METHOD -# This is the method that Nagios should use when initially -# "spreading out" service checks when it starts monitoring. The -# default is to use smart delay calculation, which will try to -# space all service checks out evenly to minimize CPU load. -# Using the dumb setting will cause all checks to be scheduled -# at the same time (with no delay between them)! This is not a -# good thing for production, but is useful when testing the -# parallelization functionality. -# n = None - don't use any delay between checks -# d = Use a "dumb" delay of 1 second between checks -# s = Use "smart" inter-check delay calculation -# x.xx = Use an inter-check delay of x.xx seconds - service_inter_check_delay_method=s - - - -# MAXIMUM SERVICE CHECK SPREAD -# This variable determines the timeframe (in minutes) from the -# program start time that an initial check of all services should -# be completed. Default is 30 minutes. - max_service_check_spread=30 - - - -# SERVICE CHECK INTERLEAVE FACTOR -# This variable determines how service checks are interleaved. -# Interleaving the service checks allows for a more even -# distribution of service checks and reduced load on remote -# hosts. Setting this value to 1 is equivalent to how versions -# of Nagios previous to 0.0.5 did service checks. Set this -# value to s (smart) for automatic calculation of the interleave -# factor unless you have a specific reason to change it. -# s = Use "smart" interleave factor calculation -# x = Use an interleave factor of x, where x is a -# number greater than or equal to 1. - service_interleave_factor=s - - - -# HOST INTER-CHECK DELAY METHOD -# This is the method that Nagios should use when initially -# "spreading out" host checks when it starts monitoring. The -# default is to use smart delay calculation, which will try to -# space all host checks out evenly to minimize CPU load. -# Using the dumb setting will cause all checks to be scheduled -# at the same time (with no delay between them)! -# n = None - don't use any delay between checks -# d = Use a "dumb" delay of 1 second between checks -# s = Use "smart" inter-check delay calculation -# x.xx = Use an inter-check delay of x.xx seconds - host_inter_check_delay_method=s - - - -# MAXIMUM HOST CHECK SPREAD -# This variable determines the timeframe (in minutes) from the -# program start time that an initial check of all hosts should -# be completed. Default is 30 minutes. - max_host_check_spread=30 - - - -# MAXIMUM CONCURRENT SERVICE CHECKS -# This option allows you to specify the maximum number of -# service checks that can be run in parallel at any given time. -# Specifying a value of 1 for this variable essentially prevents -# any service checks from being parallelized. A value of 0 -# will not restrict the number of concurrent checks that are -# being executed. - max_concurrent_checks=0 - - - -# HOST AND SERVICE CHECK REAPER FREQUENCY -# This is the frequency (in seconds!) that Nagios will process -# the results of host and service checks. - check_result_reaper_frequency=10 - - - - -# MAX CHECK RESULT REAPER TIME -# This is the max amount of time (in seconds) that a single -# check result reaper event will be allowed to run before -# returning control back to Nagios so it can perform other -# duties. - max_check_result_reaper_time=30 - - - - -# CHECK RESULT PATH -# This is directory where Nagios stores the results of host and -# service checks that have not yet been processed. -# -# Note: Make sure that only one instance of Nagios has access -# to this directory! - check_result_path=smallconfig - - - - -# MAX CHECK RESULT FILE AGE -# This option determines the maximum age (in seconds) which check -# result files are considered to be valid. Files older than this -# threshold will be mercilessly deleted without further processing. - max_check_result_file_age=3600 - - - - -# CACHED HOST CHECK HORIZON -# This option determines the maximum amount of time (in seconds) -# that the state of a previous host check is considered current. -# Cached host states (from host checks that were performed more -# recently that the timeframe specified by this value) can immensely -# improve performance in regards to the host check logic. -# Too high of a value for this option may result in inaccurate host -# states being used by Nagios, while a lower value may result in a -# performance hit for host checks. Use a value of 0 to disable host -# check caching. - cached_host_check_horizon=15 - - - -# CACHED SERVICE CHECK HORIZON -# This option determines the maximum amount of time (in seconds) -# that the state of a previous service check is considered current. -# Cached service states (from service checks that were performed more -# recently that the timeframe specified by this value) can immensely -# improve performance in regards to predictive dependency checks. -# Use a value of 0 to disable service check caching. - cached_service_check_horizon=15 - - - -# ENABLE PREDICTIVE HOST DEPENDENCY CHECKS -# This option determines whether or not Nagios will attempt to execute -# checks of hosts when it predicts that future dependency logic test -# may be needed. These predictive checks can help ensure that your -# host dependency logic works well. -# Values: -# 0 = Disable predictive checks -# 1 = Enable predictive checks (default) - enable_predictive_host_dependency_checks=1 - - - -# ENABLE PREDICTIVE SERVICE DEPENDENCY CHECKS -# This option determines whether or not Nagios will attempt to execute -# checks of service when it predicts that future dependency logic test -# may be needed. These predictive checks can help ensure that your -# service dependency logic works well. -# Values: -# 0 = Disable predictive checks -# 1 = Enable predictive checks (default) - enable_predictive_service_dependency_checks=1 - - - -# SOFT STATE DEPENDENCIES -# This option determines whether or not Nagios will use soft state -# information when checking host and service dependencies. Normally -# Nagios will only use the latest hard host or service state when -# checking dependencies. If you want it to use the latest state (regardless -# of whether its a soft or hard state type), enable this option. -# Values: -# 0 = Don't use soft state dependencies (default) -# 1 = Use soft state dependencies - soft_state_dependencies=0 - - - -# TIME CHANGE ADJUSTMENT THRESHOLDS -# These options determine when Nagios will react to detected changes -# in system time (either forward or backwards). - -#time_change_threshold=900 - - - -# AUTO-RESCHEDULING OPTION -# This option determines whether or not Nagios will attempt to -# automatically reschedule active host and service checks to -# "smooth" them out over time. This can help balance the load on -# the monitoring server. -# WARNING: THIS IS AN EXPERIMENTAL FEATURE - IT CAN DEGRADE -# PERFORMANCE, RATHER THAN INCREASE IT, IF USED IMPROPERLY - auto_reschedule_checks=0 - - - -# AUTO-RESCHEDULING INTERVAL -# This option determines how often (in seconds) Nagios will -# attempt to automatically reschedule checks. This option only -# has an effect if the auto_reschedule_checks option is enabled. -# Default is 30 seconds. -# WARNING: THIS IS AN EXPERIMENTAL FEATURE - IT CAN DEGRADE -# PERFORMANCE, RATHER THAN INCREASE IT, IF USED IMPROPERLY - auto_rescheduling_interval=30 - - - -# AUTO-RESCHEDULING WINDOW -# This option determines the "window" of time (in seconds) that -# Nagios will look at when automatically rescheduling checks. -# Only host and service checks that occur in the next X seconds -# (determined by this variable) will be rescheduled. This option -# only has an effect if the auto_reschedule_checks option is -# enabled. Default is 180 seconds (3 minutes). -# WARNING: THIS IS AN EXPERIMENTAL FEATURE - IT CAN DEGRADE -# PERFORMANCE, RATHER THAN INCREASE IT, IF USED IMPROPERLY - auto_rescheduling_window=180 - - - -# SLEEP TIME -# This is the number of seconds to sleep between checking for system -# events and service checks that need to be run. - -sleep_time=0.25 - - - -# TIMEOUT VALUES -# These options control how much time Nagios will allow various -# types of commands to execute before killing them off. Options -# are available for controlling maximum time allotted for -# service checks, host checks, event handlers, notifications, the -# ocsp command, and performance data commands. All values are in -# seconds. - service_check_timeout=60 host_check_timeout=30 event_handler_timeout=30 notification_timeout=30 ocsp_timeout=5 perfdata_timeout=5 - - - -# RETAIN STATE INFORMATION -# This setting determines whether or not Nagios will save state -# information for services and hosts before it shuts down. Upon -# startup Nagios will reload all saved service and host state -# information before starting to monitor. This is useful for -# maintaining long-term data on state statistics, etc, but will -# slow Nagios down a bit when it (re)starts. Since its only -# a one-time penalty, I think its well worth the additional -# startup delay. - retain_state_information=1 - - - -# STATE RETENTION FILE -# This is the file that Nagios should use to store host and -# service state information before it shuts down. The state -# information in this file is also read immediately prior to -# starting to monitor the network when Nagios is restarted. -# This file is used only if the preserve_state_information -# variable is set to 1. - state_retention_file=smallconfig/retention.dat - - - -# RETENTION DATA UPDATE INTERVAL -# This setting determines how often (in minutes) that Nagios -# will automatically save retention data during normal operation. -# If you set this value to 0, Nagios will not save retention -# data at regular interval, but it will still save retention -# data before shutting down or restarting. If you have disabled -# state retention, this option has no effect. - retention_update_interval=60 - - - -# USE RETAINED PROGRAM STATE -# This setting determines whether or not Nagios will set -# program status variables based on the values saved in the -# retention file. If you want to use retained program status -# information, set this value to 1. If not, set this value -# to 0. - use_retained_program_state=1 - - - -# USE RETAINED SCHEDULING INFO -# This setting determines whether or not Nagios will retain -# the scheduling info (next check time) for hosts and services -# based on the values saved in the retention file. If you -# If you want to use retained scheduling info, set this -# value to 1. If not, set this value to 0. - use_retained_scheduling_info=1 - - - -# RETAINED ATTRIBUTE MASKS (ADVANCED FEATURE) -# The following variables are used to specify specific host and -# service attributes that should *not* be retained by Nagios during -# program restarts. -# -# The values of the masks are bitwise ANDs of values specified -# by the "MODATTR_" definitions found in include/common.h. -# For example, if you do not want the current enabled/disabled state -# of flap detection and event handlers for hosts to be retained, you -# would use a value of 24 for the host attribute mask... -# MODATTR_EVENT_HANDLER_ENABLED (8) + MODATTR_FLAP_DETECTION_ENABLED (16) = 24 - -# This mask determines what host attributes are not retained retained_host_attribute_mask=0 - -# This mask determines what service attributes are not retained retained_service_attribute_mask=0 - -# These two masks determine what process attributes are not retained. -# There are two masks, because some process attributes have host and service -# options. For example, you can disable active host checks, but leave active -# service checks enabled. retained_process_host_attribute_mask=0 retained_process_service_attribute_mask=0 - -# These two masks determine what contact attributes are not retained. -# There are two masks, because some contact attributes have host and -# service options. For example, you can disable host notifications for -# a contact, but leave service notifications enabled for them. retained_contact_host_attribute_mask=0 retained_contact_service_attribute_mask=0 - - - -# INTERVAL LENGTH -# This is the seconds per unit interval as used in the -# host/contact/service configuration files. Setting this to 60 means -# that each interval is one minute long (60 seconds). Other settings -# have not been tested much, so your mileage is likely to vary... - interval_length=60 - - - -# CHECK FOR UPDATES -# This option determines whether Nagios will automatically check to -# see if new updates (releases) are available. It is recommend that you -# enable this option to ensure that you stay on top of the latest critical -# patches to Nagios. Nagios is critical to you - make sure you keep it in -# good shape. Nagios will check once a day for new updates. Data collected -# by Nagios Enterprises from the update check is processed in accordance -# with our privacy policy - see http://api.nagios.org for details. - check_for_updates=1 - - - -# BARE UPDATE CHECK -# This option deterines what data Nagios will send to api.nagios.org when -# it checks for updates. By default, Nagios will send information on the -# current version of Nagios you have installed, as well as an indicator as -# to whether this was a new installation or not. Nagios Enterprises uses -# this data to determine the number of users running specific version of -# Nagios. Enable this option if you do not want this information to be sent. - bare_update_check=0 - - - -# AGGRESSIVE HOST CHECKING OPTION -# If you don't want to turn on aggressive host checking features, set -# this value to 0 (the default). Otherwise set this value to 1 to -# enable the aggressive check option. Read the docs for more info -# on what aggressive host check is or check out the source code in -# base/checks.c - use_aggressive_host_checking=0 - - - -# SERVICE CHECK EXECUTION OPTION -# This determines whether or not Nagios will actively execute -# service checks when it initially starts. If this option is -# disabled, checks are not actively made, but Nagios can still -# receive and process passive check results that come in. Unless -# you're implementing redundant hosts or have a special need for -# disabling the execution of service checks, leave this enabled! -# Values: 1 = enable checks, 0 = disable checks - execute_service_checks=1 - - - -# PASSIVE SERVICE CHECK ACCEPTANCE OPTION -# This determines whether or not Nagios will accept passive -# service checks results when it initially (re)starts. -# Values: 1 = accept passive checks, 0 = reject passive checks - accept_passive_service_checks=1 - - - -# HOST CHECK EXECUTION OPTION -# This determines whether or not Nagios will actively execute -# host checks when it initially starts. If this option is -# disabled, checks are not actively made, but Nagios can still -# receive and process passive check results that come in. Unless -# you're implementing redundant hosts or have a special need for -# disabling the execution of host checks, leave this enabled! -# Values: 1 = enable checks, 0 = disable checks - execute_host_checks=1 - - - -# PASSIVE HOST CHECK ACCEPTANCE OPTION -# This determines whether or not Nagios will accept passive -# host checks results when it initially (re)starts. -# Values: 1 = accept passive checks, 0 = reject passive checks - accept_passive_host_checks=1 - - - -# NOTIFICATIONS OPTION -# This determines whether or not Nagios will sent out any host or -# service notifications when it is initially (re)started. -# Values: 1 = enable notifications, 0 = disable notifications - enable_notifications=1 - - - -# EVENT HANDLER USE OPTION -# This determines whether or not Nagios will run any host or -# service event handlers when it is initially (re)started. Unless -# you're implementing redundant hosts, leave this option enabled. -# Values: 1 = enable event handlers, 0 = disable event handlers - enable_event_handlers=1 - - - -# PROCESS PERFORMANCE DATA OPTION -# This determines whether or not Nagios will process performance -# data returned from service and host checks. If this option is -# enabled, host performance data will be processed using the -# host_perfdata_command (defined below) and service performance -# data will be processed using the service_perfdata_command (also -# defined below). Read the HTML docs for more information on -# performance data. -# Values: 1 = process performance data, 0 = do not process performance data - process_performance_data=0 - - - -# HOST AND SERVICE PERFORMANCE DATA PROCESSING COMMANDS -# These commands are run after every host and service check is -# performed. These commands are executed only if the -# enable_performance_data option (above) is set to 1. The command -# argument is the short name of a command definition that you -# define in your host configuration file. Read the HTML docs for -# more information on performance data. - -#host_perfdata_command=process-host-perfdata -#service_perfdata_command=process-service-perfdata - - - -# HOST AND SERVICE PERFORMANCE DATA FILES -# These files are used to store host and service performance data. -# Performance data is only written to these files if the -# enable_performance_data option (above) is set to 1. - -#host_perfdata_file=/tmp/host-perfdata -#service_perfdata_file=/tmp/service-perfdata - - - -# HOST AND SERVICE PERFORMANCE DATA FILE TEMPLATES -# These options determine what data is written (and how) to the -# performance data files. The templates may contain macros, special -# characters (\t for tab, \r for carriage return, \n for newline) -# and plain text. A newline is automatically added after each write -# to the performance data file. Some examples of what you can do are -# shown below. - -#host_perfdata_file_template=[HOSTPERFDATA]\t$TIMET$\t$HOSTNAME$\t$HOSTEXECUTIONTIME$\t$HOSTOUTPUT$\t$HOSTPERFDATA$ -#service_perfdata_file_template=[SERVICEPERFDATA]\t$TIMET$\t$HOSTNAME$\t$SERVICEDESC$\t$SERVICEEXECUTIONTIME$\t$SERVICELATENCY$\t$SERVICEOUTPUT$\t$SERVICEPERFDATA$ - - - -# HOST AND SERVICE PERFORMANCE DATA FILE MODES -# This option determines whether or not the host and service -# performance data files are opened in write ("w") or append ("a") -# mode. If you want to use named pipes, you should use the special -# pipe ("p") mode which avoid blocking at startup, otherwise you will -# likely want the defult append ("a") mode. - -#host_perfdata_file_mode=a -#service_perfdata_file_mode=a - - - -# HOST AND SERVICE PERFORMANCE DATA FILE PROCESSING INTERVAL -# These options determine how often (in seconds) the host and service -# performance data files are processed using the commands defined -# below. A value of 0 indicates the files should not be periodically -# processed. - -#host_perfdata_file_processing_interval=0 -#service_perfdata_file_processing_interval=0 - - - -# HOST AND SERVICE PERFORMANCE DATA FILE PROCESSING COMMANDS -# These commands are used to periodically process the host and -# service performance data files. The interval at which the -# processing occurs is determined by the options above. - -#host_perfdata_file_processing_command=process-host-perfdata-file -#service_perfdata_file_processing_command=process-service-perfdata-file - - - -# OBSESS OVER SERVICE CHECKS OPTION -# This determines whether or not Nagios will obsess over service -# checks and run the ocsp_command defined below. Unless you're -# planning on implementing distributed monitoring, do not enable -# this option. Read the HTML docs for more information on -# implementing distributed monitoring. -# Values: 1 = obsess over services, 0 = do not obsess (default) - obsess_over_services=0 - - - -# OBSESSIVE COMPULSIVE SERVICE PROCESSOR COMMAND -# This is the command that is run for every service check that is -# processed by Nagios. This command is executed only if the -# obsess_over_services option (above) is set to 1. The command -# argument is the short name of a command definition that you -# define in your host configuration file. Read the HTML docs for -# more information on implementing distributed monitoring. - -#ocsp_command=somecommand - - - -# OBSESS OVER HOST CHECKS OPTION -# This determines whether or not Nagios will obsess over host -# checks and run the ochp_command defined below. Unless you're -# planning on implementing distributed monitoring, do not enable -# this option. Read the HTML docs for more information on -# implementing distributed monitoring. -# Values: 1 = obsess over hosts, 0 = do not obsess (default) - obsess_over_hosts=0 - - - -# OBSESSIVE COMPULSIVE HOST PROCESSOR COMMAND -# This is the command that is run for every host check that is -# processed by Nagios. This command is executed only if the -# obsess_over_hosts option (above) is set to 1. The command -# argument is the short name of a command definition that you -# define in your host configuration file. Read the HTML docs for -# more information on implementing distributed monitoring. - -#ochp_command=somecommand - - - -# TRANSLATE PASSIVE HOST CHECKS OPTION -# This determines whether or not Nagios will translate -# DOWN/UNREACHABLE passive host check results into their proper -# state for this instance of Nagios. This option is useful -# if you have distributed or failover monitoring setup. In -# these cases your other Nagios servers probably have a different -# "view" of the network, with regards to the parent/child relationship -# of hosts. If a distributed monitoring server thinks a host -# is DOWN, it may actually be UNREACHABLE from the point of -# this Nagios instance. Enabling this option will tell Nagios -# to translate any DOWN or UNREACHABLE host states it receives -# passively into the correct state from the view of this server. -# Values: 1 = perform translation, 0 = do not translate (default) - translate_passive_host_checks=0 - - - -# PASSIVE HOST CHECKS ARE SOFT OPTION -# This determines whether or not Nagios will treat passive host -# checks as being HARD or SOFT. By default, a passive host check -# result will put a host into a HARD state type. This can be changed -# by enabling this option. -# Values: 0 = passive checks are HARD, 1 = passive checks are SOFT - passive_host_checks_are_soft=0 - - - -# ORPHANED HOST/SERVICE CHECK OPTIONS -# These options determine whether or not Nagios will periodically -# check for orphaned host service checks. Since service checks are -# not rescheduled until the results of their previous execution -# instance are processed, there exists a possibility that some -# checks may never get rescheduled. A similar situation exists for -# host checks, although the exact scheduling details differ a bit -# from service checks. Orphaned checks seem to be a rare -# problem and should not happen under normal circumstances. -# If you have problems with service checks never getting -# rescheduled, make sure you have orphaned service checks enabled. -# Values: 1 = enable checks, 0 = disable checks - check_for_orphaned_services=1 check_for_orphaned_hosts=1 - - - -# SERVICE FRESHNESS CHECK OPTION -# This option determines whether or not Nagios will periodically -# check the "freshness" of service results. Enabling this option -# is useful for ensuring passive checks are received in a timely -# manner. -# Values: 1 = enabled freshness checking, 0 = disable freshness checking - check_service_freshness=1 - - - -# SERVICE FRESHNESS CHECK INTERVAL -# This setting determines how often (in seconds) Nagios will -# check the "freshness" of service check results. If you have -# disabled service freshness checking, this option has no effect. - service_freshness_check_interval=60 - - - -# HOST FRESHNESS CHECK OPTION -# This option determines whether or not Nagios will periodically -# check the "freshness" of host results. Enabling this option -# is useful for ensuring passive checks are received in a timely -# manner. -# Values: 1 = enabled freshness checking, 0 = disable freshness checking - check_host_freshness=0 - - - -# HOST FRESHNESS CHECK INTERVAL -# This setting determines how often (in seconds) Nagios will -# check the "freshness" of host check results. If you have -# disabled host freshness checking, this option has no effect. - host_freshness_check_interval=60 - - - - -# ADDITIONAL FRESHNESS THRESHOLD LATENCY -# This setting determines the number of seconds that Nagios -# will add to any host and service freshness thresholds that -# it calculates (those not explicitly specified by the user). - additional_freshness_latency=15 - - - - -# FLAP DETECTION OPTION -# This option determines whether or not Nagios will try -# and detect hosts and services that are "flapping". -# Flapping occurs when a host or service changes between -# states too frequently. When Nagios detects that a -# host or service is flapping, it will temporarily suppress -# notifications for that host/service until it stops -# flapping. Flap detection is very experimental, so read -# the HTML documentation before enabling this feature! -# Values: 1 = enable flap detection -# 0 = disable flap detection (default) - enable_flap_detection=1 - - - -# FLAP DETECTION THRESHOLDS FOR HOSTS AND SERVICES -# Read the HTML documentation on flap detection for -# an explanation of what this option does. This option -# has no effect if flap detection is disabled. - low_service_flap_threshold=5.0 high_service_flap_threshold=20.0 low_host_flap_threshold=5.0 high_host_flap_threshold=20.0 - - - -# DATE FORMAT OPTION -# This option determines how short dates are displayed. Valid options -# include: -# us (MM-DD-YYYY HH:MM:SS) -# euro (DD-MM-YYYY HH:MM:SS) -# iso8601 (YYYY-MM-DD HH:MM:SS) -# strict-iso8601 (YYYY-MM-DDTHH:MM:SS) -# - date_format=us - - - - -# TIMEZONE OFFSET -# This option is used to override the default timezone that this -# instance of Nagios runs in. If not specified, Nagios will use -# the system configured timezone. -# -# NOTE: In order to display the correct timezone in the CGIs, you -# will also need to alter the Apache directives for the CGI path -# to include your timezone. Example: -# -# -# SetEnv TZ "Australia/Brisbane" -# ... -# - -#use_timezone=US/Mountain -#use_timezone=Australia/Brisbane - - - - -# P1.PL FILE LOCATION -# This value determines where the p1.pl perl script (used by the -# embedded Perl interpreter) is located. If you didn't compile -# Nagios with embedded Perl support, this option has no effect. - -p1_file=/usr/local/nagios/bin/p1.pl - - - -# EMBEDDED PERL INTERPRETER OPTION -# This option determines whether or not the embedded Perl interpreter -# will be enabled during runtime. This option has no effect if Nagios -# has not been compiled with support for embedded Perl. -# Values: 0 = disable interpreter, 1 = enable interpreter - -enable_embedded_perl=1 - - - -# EMBEDDED PERL USAGE OPTION -# This option determines whether or not Nagios will process Perl plugins -# and scripts with the embedded Perl interpreter if the plugins/scripts -# do not explicitly indicate whether or not it is okay to do so. Read -# the HTML documentation on the embedded Perl interpreter for more -# information on how this option works. - -use_embedded_perl_implicitly=1 - - - -# ILLEGAL OBJECT NAME CHARACTERS -# This option allows you to specify illegal characters that cannot -# be used in host names, service descriptions, or names of other -# object types. - illegal_object_name_chars=`~!$%^&*|'"<>?,()= - - - -# ILLEGAL MACRO OUTPUT CHARACTERS -# This option allows you to specify illegal characters that are -# stripped from macros before being used in notifications, event -# handlers, etc. This DOES NOT affect macros used in service or -# host check commands. -# The following macros are stripped of the characters you specify: -# $HOSTOUTPUT$ -# $HOSTPERFDATA$ -# $HOSTACKAUTHOR$ -# $HOSTACKCOMMENT$ -# $SERVICEOUTPUT$ -# $SERVICEPERFDATA$ -# $SERVICEACKAUTHOR$ -# $SERVICEACKCOMMENT$ - illegal_macro_output_chars=`~$&|'"<> - - - -# REGULAR EXPRESSION MATCHING -# This option controls whether or not regular expression matching -# takes place in the object config files. Regular expression -# matching is used to match host, hostgroup, service, and service -# group names/descriptions in some fields of various object types. -# Values: 1 = enable regexp matching, 0 = disable regexp matching - use_regexp_matching=0 - - - -# "TRUE" REGULAR EXPRESSION MATCHING -# This option controls whether or not "true" regular expression -# matching takes place in the object config files. This option -# only has an effect if regular expression matching is enabled -# (see above). If this option is DISABLED, regular expression -# matching only occurs if a string contains wildcard characters -# (* and ?). If the option is ENABLED, regexp matching occurs -# all the time (which can be annoying). -# Values: 1 = enable true matching, 0 = disable true matching - use_true_regexp_matching=0 - - - -# ADMINISTRATOR EMAIL/PAGER ADDRESSES -# The email and pager address of a global administrator (likely you). -# Nagios never uses these values itself, but you can access them by -# using the $ADMINEMAIL$ and $ADMINPAGER$ macros in your notification -# commands. - admin_email=nagios@localhost admin_pager=pagenagios@localhost - - - -# DAEMON CORE DUMP OPTION -# This option determines whether or not Nagios is allowed to create -# a core dump when it runs as a daemon. Note that it is generally -# considered bad form to allow this, but it may be useful for -# debugging purposes. Enabling this option doesn't guarantee that -# a core file will be produced, but that's just life... -# Values: 1 - Allow core dumps -# 0 - Do not allow core dumps (default) - daemon_dumps_core=0 - - - -# LARGE INSTALLATION TWEAKS OPTION -# This option determines whether or not Nagios will take some shortcuts -# which can save on memory and CPU usage in large Nagios installations. -# Read the documentation for more information on the benefits/tradeoffs -# of enabling this option. -# Values: 1 - Enabled tweaks -# 0 - Disable tweaks (default) - use_large_installation_tweaks=0 - - - -# ENABLE ENVIRONMENT MACROS -# This option determines whether or not Nagios will make all standard -# macros available as environment variables when host/service checks -# and system commands (event handlers, notifications, etc.) are -# executed. Enabling this option can cause performance issues in -# large installations, as it will consume a bit more memory and (more -# importantly) consume more CPU. -# Values: 1 - Enable environment variable macros (default) -# 0 - Disable environment variable macros - enable_environment_macros=1 - - - -# CHILD PROCESS MEMORY OPTION -# This option determines whether or not Nagios will free memory in -# child processes (processed used to execute system commands and host/ -# service checks). If you specify a value here, it will override -# program defaults. -# Value: 1 - Free memory in child processes -# 0 - Do not free memory in child processes - -#free_child_process_memory=1 - - - -# CHILD PROCESS FORKING BEHAVIOR -# This option determines how Nagios will fork child processes -# (used to execute system commands and host/service checks). Normally -# child processes are fork()ed twice, which provides a very high level -# of isolation from problems. Fork()ing once is probably enough and will -# save a great deal on CPU usage (in large installs), so you might -# want to consider using this. If you specify a value here, it will -# program defaults. -# Value: 1 - Child processes fork() twice -# 0 - Child processes fork() just once - -#child_processes_fork_twice=1 - - - -# DEBUG LEVEL -# This option determines how much (if any) debugging information will -# be written to the debug file. OR values together to log multiple -# types of information. -# Values: -# -1 = Everything -# 0 = Nothing -# 1 = Functions -# 2 = Configuration -# 4 = Process information -# 8 = Scheduled events -# 16 = Host/service checks -# 32 = Notifications -# 64 = Event broker -# 128 = External commands -# 256 = Commands -# 512 = Scheduled downtime -# 1024 = Comments -# 2048 = Macros - debug_level=0 - - - -# DEBUG VERBOSITY -# This option determines how verbose the debug log out will be. -# Values: 0 = Brief output -# 1 = More detailed -# 2 = Very detailed - debug_verbosity=1 - - - -# DEBUG FILE -# This option determines where Nagios should write debugging information. - debug_file=smallconfig/nagios.debug - - - -# MAX DEBUG FILE SIZE -# This option determines the maximum size (in bytes) of the debug file. If -# the file grows larger than this size, it will be renamed with a .old -# extension. If a file already exists with a .old extension it will -# automatically be deleted. This helps ensure your disk space usage doesn't -# get out of control when debugging Nagios. - max_debug_file_size=1000000 - - diff --git a/t-tap/smallconfig/retention.dat b/t-tap/smallconfig/retention.dat index 2d35294..3a1e974 100644 --- a/t-tap/smallconfig/retention.dat +++ b/t-tap/smallconfig/retention.dat @@ -25,7 +25,6 @@ obsess_over_hosts=0 check_service_freshness=1 check_host_freshness=1 enable_flap_detection=1 -enable_failure_prediction=1 process_performance_data=1 global_host_event_handler= global_service_event_handler= @@ -81,7 +80,6 @@ active_checks_enabled=1 passive_checks_enabled=1 event_handler_enabled=0 flap_detection_enabled=1 -failure_prediction_enabled=1 process_performance_data=1 obsess_over_host=0 is_flapping=1 @@ -135,7 +133,6 @@ active_checks_enabled=1 passive_checks_enabled=1 event_handler_enabled=0 flap_detection_enabled=1 -failure_prediction_enabled=1 process_performance_data=1 obsess_over_host=0 is_flapping=1 @@ -186,7 +183,7 @@ host_name=host1 downtime_id=1102 entry_time=1280488503 start_time=1980913033 -end_time=1980913033 +end_time=2980913033 triggered_by=0 fixed=1 duration=7 diff --git a/t-tap/stub_broker.c b/t-tap/stub_broker.c index 15c9824..b9712be 100644 --- a/t-tap/stub_broker.c +++ b/t-tap/stub_broker.c @@ -6,3 +6,10 @@ void broker_adaptive_service_data(int type, int flags, int attr, service *svc, i void broker_adaptive_contact_data(int type, int flags, int attr, contact *cntct, int command_type, unsigned long modattr, unsigned long modattrs, unsigned long modhattr, unsigned long modhattrs, unsigned long modsattr, unsigned long modsattrs, struct timeval *timestamp) {} void broker_external_command(int type, int flags, int attr, int command_type, time_t entry_time, char *command_string, char *command_args, struct timeval *timestamp) {} void broker_acknowledgement_data(int type, int flags, int attr, int acknowledgement_type, void *data, char *ack_author, char *ack_data, int subtype, int notify_contacts, int persistent_comment, struct timeval *timestamp) {} +int broker_host_check(int type, int flags, int attr, host *hst, int check_type, int state, int state_type, struct timeval start_time, struct timeval end_time, char *cmd, double latency, double exectime, int timeout, int early_timeout, int retcode, char *cmdline, char *output, char *long_output, char *perfdata, struct timeval *timestamp, check_result *cr) { return OK; } +int broker_service_check(int type, int flags, int attr, service *svc, int check_type, struct timeval start_time, struct timeval end_time, char *cmd, double latency, double exectime, int timeout, int early_timeout, int retcode, char *cmdline, struct timeval *timestamp, check_result *cr) { return OK; } +void broker_program_state(int type, int flags, int attr, struct timeval *timestamp) {} +void broker_system_command(int type, int flags, int attr, struct timeval start_time, struct timeval end_time, double exectime, int timeout, int early_timeout, int retcode, char *cmd, char *output, struct timeval *timestamp) {} +void broker_log_data(int type, int flags, int attr, char *data, unsigned long data_type, time_t entry_time, struct timeval *timestamp) {} +void broker_comment_data(int type, int flags, int attr, int comment_type, int entry_type, char *host_name, char *svc_description, time_t entry_time, char *author_name, char *comment_data, int persistent, int source, int expires, time_t expire_time, unsigned long comment_id, struct timeval *timestamp) {} +void broker_timed_event(int type, int flags, int attr, timed_event *event, struct timeval *timestamp) {} diff --git a/t-tap/stub_checks.c b/t-tap/stub_checks.c index b7c101b..ca339c6 100644 --- a/t-tap/stub_checks.c +++ b/t-tap/stub_checks.c @@ -1,2 +1,13 @@ void schedule_host_check(host *hst, time_t check_time, int options) {} void schedule_service_check(service *svc, time_t check_time, int options) {} +int handle_async_host_check_result(host *temp_host, check_result *queued_check_result) { return OK; } +int handle_async_service_check_result(service *temp_service, check_result *queued_check_result) { return OK; } +#ifndef TEST_EVENTS_C +int run_scheduled_service_check(service *svc, int check_options, double latency) { return OK; } +#endif +int reap_check_results(void) { return OK; } +void check_for_orphaned_services(void) {} +void check_service_result_freshness(void) {} +int run_scheduled_host_check(host *hst, int check_options, double latency) { return OK; } +void check_host_result_freshness(void) {} +void check_for_orphaned_hosts(void) {} diff --git a/t-tap/stub_commands.c b/t-tap/stub_commands.c new file mode 100644 index 0000000..245e8ac --- /dev/null +++ b/t-tap/stub_commands.c @@ -0,0 +1,3 @@ +/* Stub file for routines from commands.c */ + +int close_command_file(void) { return OK; } diff --git a/t-tap/stub_comments.c b/t-tap/stub_comments.c index 0830343..a3eece3 100644 --- a/t-tap/stub_comments.c +++ b/t-tap/stub_comments.c @@ -7,3 +7,5 @@ int delete_host_acknowledgement_comments(host *hst) {} int add_new_service_comment(int entry_type, char *host_name, char *svc_description, time_t entry_time, char *author_name, char *comment_data, int persistent, int source, int expires, time_t expire_time, unsigned long *comment_id) {} int add_new_host_comment(int entry_type, char *host_name, time_t entry_time, char *author_name, char *comment_data, int persistent, int source, int expires, time_t expire_time, unsigned long *comment_id) {} int delete_all_comments(int type, char *host_name, char *svc_description) {} +void free_comment_data(void) {} +int check_for_expired_comment(unsigned long comment_id) { return OK; } diff --git a/t-tap/stub_downtime.c b/t-tap/stub_downtime.c index 7a6a1d1..d465fc8 100644 --- a/t-tap/stub_downtime.c +++ b/t-tap/stub_downtime.c @@ -1,4 +1,8 @@ /* Stub for common/downtime.c */ +unsigned long next_downtime_id = 0; int schedule_downtime(int type, char *host_name, char *service_description, time_t entry_time, char *author, char *comment_data, time_t start_time, time_t end_time, int fixed, unsigned long triggered_by, unsigned long duration, unsigned long *new_downtime_id) {} int unschedule_downtime(int type, unsigned long downtime_id) {} int check_pending_flex_host_downtime(host *hst) {} +int check_pending_flex_service_downtime(service *svc) { return OK; } +int handle_scheduled_downtime_by_id(unsigned long downtime_id) { return OK; } +int check_for_expired_downtime(void) { return OK; } diff --git a/t-tap/stub_events.c b/t-tap/stub_events.c index ae6e2fd..7081893 100644 --- a/t-tap/stub_events.c +++ b/t-tap/stub_events.c @@ -1,3 +1,4 @@ /* Stub for base/events.c */ -int schedule_new_event(int event_type, int high_priority, time_t run_time, int recurring, unsigned long event_interval, void *timing_func, int compensate_for_time_change, void *event_data, void *event_args, int event_options) {} -void remove_event(timed_event *event, timed_event **event_list, timed_event **event_list_tail) {} +timed_event *schedule_new_event(int event_type, int high_priority, time_t run_time, int recurring, unsigned long event_interval, void *timing_func, int compensate_for_time_change, void *event_data, void *event_args, int event_options) { return NULL; } +void add_event(squeue_t *sq, timed_event *event) {} +void remove_event(squeue_t *sq, timed_event *event) {} diff --git a/t-tap/stub_flapping.c b/t-tap/stub_flapping.c index 9f859a5..86f3157 100644 --- a/t-tap/stub_flapping.c +++ b/t-tap/stub_flapping.c @@ -1,4 +1,6 @@ /* Stub for base/flapping.c */ +void check_for_host_flapping(host *hst, int update, int actual_check, int allow_flapstart_notification) {} +void check_for_service_flapping(service *svc, int update, int allow_flapstart_notification) {} void disable_service_flap_detection(service *svc) {} void disable_host_flap_detection(host *hst) {} void disable_flap_detection_routines(void) {} diff --git a/t-tap/stub_iobroker.c b/t-tap/stub_iobroker.c new file mode 100644 index 0000000..dccf43c --- /dev/null +++ b/t-tap/stub_iobroker.c @@ -0,0 +1,4 @@ +/* Stub functions for lib/iobroker.c */ +int iobroker_get_num_fds(iobroker_set *iobs) { return 1; } +int iobroker_poll(iobroker_set *iobs, int timeout) { return 0; } +const char *iobroker_strerror(int error) { return ""; } diff --git a/t-tap/stub_logging.c b/t-tap/stub_logging.c index c11c150..c9f0bed 100644 --- a/t-tap/stub_logging.c +++ b/t-tap/stub_logging.c @@ -1,2 +1,32 @@ /* Stub for base/logging.c */ int write_to_all_logs(char *buffer, unsigned long data_type) {} +int log_host_event(host *hst) { return OK; } +int log_service_event(service *svc) { return OK; } +void logit(int data_type, int display, const char *fmt, ...) {} +int fix_log_file_owner(uid_t uid, gid_t gid) { return 0; } +int close_log_file(void) { return 0; } +#ifndef TEST_CHECKS_C +int log_debug_info(int level, int verbosity, const char *fmt, ...) { + va_list ap; + char *buffer = NULL; + struct timeval now; + struct tm tmnow; + + if(!(debug_level == DEBUGL_ALL || (level & debug_level))) + return OK; + + if(verbosity > debug_verbosity) + return OK; + + gettimeofday(&now, NULL); + localtime_r(&(now.tv_sec), &tmnow); + va_start(ap, fmt); + vasprintf(&buffer, fmt, ap); + printf("[%04d-%02d-%02d %02d:%02d:%02d.%06d] %s", tmnow.tm_year+1900, + tmnow.tm_mon+1, tmnow.tm_mday, tmnow.tm_hour, tmnow.tm_min, + tmnow.tm_sec, now.tv_usec, buffer); + free(buffer); + va_end(ap); + } +#endif +int rotate_log_file(time_t rotation_time) { return OK; } diff --git a/t-tap/stub_macros.c b/t-tap/stub_macros.c new file mode 100644 index 0000000..a9dfb60 --- /dev/null +++ b/t-tap/stub_macros.c @@ -0,0 +1,13 @@ +/* Stub file for routines from macros.c */ +char *macro_user[MAX_USER_MACROS]; + +int init_macros(void) { return OK; } +int grab_host_macros_r(nagios_macros *mac, host *hst) { return OK; } +int grab_service_macros_r(nagios_macros *mac, service *svc) { return OK; } +int process_macros_r(nagios_macros *mac, char *input_buffer, char **output_buffer, int options) { return OK; } +int clear_volatile_macros_r(nagios_macros *mac) { return OK; } +int clear_host_macros_r(nagios_macros *mac) { return OK; } +int free_macrox_names(void) { return OK; } +nagios_macros *get_global_macros(void) { return NULL; } +int clear_argv_macros_r(nagios_macros *mac) { return OK; } +int set_all_macro_environment_vars_r(nagios_macros *mac, int set) { return OK; } diff --git a/t-tap/stub_nebmods.c b/t-tap/stub_nebmods.c new file mode 100644 index 0000000..6388883 --- /dev/null +++ b/t-tap/stub_nebmods.c @@ -0,0 +1,7 @@ +/* Stub file for routines from nebmods.c */ + +int neb_free_callback_list(void) { return OK; } +int neb_unload_all_modules(int flags, int reason) { return OK; } +int neb_free_module_list(void) { return OK; } +int neb_deinit_modules(void) { return OK; } +int neb_add_module(char *filename, char *args, int should_be_loaded) { return OK; } diff --git a/t-tap/stub_netutils.c b/t-tap/stub_netutils.c new file mode 100644 index 0000000..9acfc17 --- /dev/null +++ b/t-tap/stub_netutils.c @@ -0,0 +1,5 @@ +/* Stub file for routines from netutils.c */ + +int my_tcp_connect(const char *host_name, int port, int *sd, int timeout) { return OK; } +int my_sendall(int s, const char *buf, int *len, int timeout) { return OK; } +int my_recvall(int s, char *buf, int *len, int timeout) { return OK; } diff --git a/t-tap/stub_notifications.c b/t-tap/stub_notifications.c index a0a1575..8c42a7b 100644 --- a/t-tap/stub_notifications.c +++ b/t-tap/stub_notifications.c @@ -1,3 +1,5 @@ /* Stub for base/notifications.c */ int service_notification(service *svc, int type, char *not_author, char *not_data, int options) {} int host_notification(host *hst, int type, char *not_author, char *not_data, int options) {} +time_t get_next_host_notification_time(host *temp_host, time_t time_t1) { return (time_t)0; } +time_t get_next_service_notification_time(service *temp_service, time_t time_t1) { return (time_t)0; } diff --git a/t-tap/stub_nsock.c b/t-tap/stub_nsock.c new file mode 100644 index 0000000..ad321fc --- /dev/null +++ b/t-tap/stub_nsock.c @@ -0,0 +1,34 @@ +/* Stub functions for lib/nsock.c */ +static inline int nsock_vprintf(int sd, const char *fmt, va_list ap, int plus) +{ + char buf[4096]; + int len; + + /* -2 to accommodate vsnprintf()'s which don't include nul on overflow */ + len = vsnprintf(buf, sizeof(buf) - 2, fmt, ap); + if (len < 0) + return len; + buf[len] = 0; + return len; +} + +int nsock_printf_nul(int sd, const char *fmt, ...) +{ + va_list ap; + int ret; + + va_start(ap, fmt); + ret = nsock_vprintf(sd, fmt, ap, 1); + va_end(ap); + return ret; +} + +int nsock_printf(int sd, const char *fmt, ...) { + va_list ap; + int ret; + + va_start(ap, fmt); + ret = nsock_vprintf(sd, fmt, ap, 0); + va_end(ap); + return ret; +} diff --git a/t-tap/stub_objects.c b/t-tap/stub_objects.c index f841b1b..1096b75 100644 --- a/t-tap/stub_objects.c +++ b/t-tap/stub_objects.c @@ -1,9 +1,12 @@ /* Stub file for common/objects.c */ -service * find_service(char *host_name, char *svc_desc) {} -host * find_host(char *name) {} -hostgroup * find_hostgroup(char *name) {} -contactgroup * find_contactgroup(char *name) {} -servicegroup * find_servicegroup(char *name) {} -contact * find_contact(char *name) {} -command * find_command(char *name) {} -timeperiod * find_timeperiod(char *name) {} +service *find_service(const char *host_name, const char *svc_desc) { return NULL; } +host *find_host(const char *name) { return NULL; } +hostgroup *find_hostgroup(const char *name) { return NULL; } +contactgroup *find_contactgroup(const char *name) { return NULL; } +servicegroup *find_servicegroup(const char *name) { return NULL; } +contact *find_contact(const char *name) { return NULL; } +command *find_command(const char *name) { return NULL; } +timeperiod *find_timeperiod(const char *name) { return NULL; } +int prepend_object_to_objectlist(objectlist **list, void *object_ptr) { return OK; } +int free_objectlist(objectlist **temp_list) { return OK; } +int free_object_data(void) { return OK; } diff --git a/t-tap/stub_perfdata.c b/t-tap/stub_perfdata.c index 3561be5..9d47544 100644 --- a/t-tap/stub_perfdata.c +++ b/t-tap/stub_perfdata.c @@ -1 +1,2 @@ -int update_host_performance_data(host *hst) {} +int update_host_performance_data(host *hst) {} +int update_service_performance_data(service *svc) { return OK; } diff --git a/t-tap/stub_sehandlers.c b/t-tap/stub_sehandlers.c index 9b48b23..2373bb9 100644 --- a/t-tap/stub_sehandlers.c +++ b/t-tap/stub_sehandlers.c @@ -1,2 +1,4 @@ int obsessive_compulsive_host_check_processor(host *hst) {} +int obsessive_compulsive_service_check_processor(service *svc) { return OK; } int handle_host_event(host *hst) {} +int handle_service_event(service *svc) { return OK; } diff --git a/t-tap/stub_statusdata.c b/t-tap/stub_statusdata.c index e0f8971..eea589a 100644 --- a/t-tap/stub_statusdata.c +++ b/t-tap/stub_statusdata.c @@ -1,5 +1,8 @@ /* Stub for common/statusdata.c */ int update_service_status(service *svc, int aggregated_dump) {} -int update_host_status(host *hst, int aggregated_dump) {} +int update_host_status(host *hst, int aggregated_dump) { return OK; } +#if !(defined(TEST_CHECKS_C) || defined(TEST_EVENTS_C)) int update_program_status(int aggregated_dump) {} +#endif int update_contact_status(contact *cntct, int aggregated_dump) {} +int update_all_status_data(void) { return OK; } diff --git a/t-tap/stub_utils.c b/t-tap/stub_utils.c index 85d2c6b..70846b2 100644 --- a/t-tap/stub_utils.c +++ b/t-tap/stub_utils.c @@ -1,5 +1,5 @@ /* Stub for base/utils.c */ void get_next_valid_time(time_t pref_time, time_t *valid_time, timeperiod *tperiod) {} int update_check_stats(int check_type, time_t check_time) {} -int move_check_result_to_queue(char *checkresult_file) {} int check_time_against_period(time_t test_time, timeperiod *tperiod) {} +void free_memory(nagios_macros *mac) {} diff --git a/t-tap/stub_workers.c b/t-tap/stub_workers.c new file mode 100644 index 0000000..1f5cc32 --- /dev/null +++ b/t-tap/stub_workers.c @@ -0,0 +1,4 @@ +/* Stub file for routines from macros.c */ +int wproc_run_check(check_result *cr, char *cmd, nagios_macros *mac) { return OK; } +int wproc_can_spawn(struct load_control *lc) { return 1; } +void wproc_reap(int jobs, int msecs) {} diff --git a/t-tap/stub_xodtemplate.c b/t-tap/stub_xodtemplate.c new file mode 100644 index 0000000..a1e574a --- /dev/null +++ b/t-tap/stub_xodtemplate.c @@ -0,0 +1,3 @@ +/* Stub file for routines from xodtemplate.c */ + +int xodtemplate_read_config_data(const char *main_config_file, int options) { return OK; } diff --git a/t-tap/test-stubs.c b/t-tap/test-stubs.c index 3f374b9..b9ff9d7 100644 --- a/t-tap/test-stubs.c +++ b/t-tap/test-stubs.c @@ -2,29 +2,16 @@ #define NAGIOS_TEST_STUBS__ #include "macros.h" -/* give up the (fake) lock after 3 tries at getting it */ -int pthread_mutex_trylock(pthread_mutex_t *mutex) { - static int loops = 0; - if(loops < 3) { - loops++; - return -1; - } - loops = 0; - return 0; - } - /* Loads of variables + stubbed functions */ char *config_file = "etc/nagios.cfg"; int test_scheduling; time_t program_start; time_t event_start; -time_t last_command_check; int sigshutdown = FALSE; int sigrestart = FALSE; -double sleep_time; int interval_length = 60; int service_inter_check_delay_method; int host_inter_check_delay_method; @@ -54,7 +41,6 @@ int retention_update_interval; int max_parallel_service_checks; int currently_running_service_checks; -int aggregate_status_updates; int status_update_interval; int log_rotation_method; @@ -142,14 +128,12 @@ check_result *read_check_result(void) {} int broker_service_check(int type, int flags, int attr, service *svc, int check_type, struct timeval start_time, struct timeval end_time, char *cmd, double latency, double exectime, int timeout, int early_timeout, int retcode, char *cmdline, struct timeval *timestamp) {} int get_raw_command_line(command *a, char *b, char **c, int d) {} int get_raw_command_line_r(nagios_macros *mac, command *a, char *b, char **c, int d) {} -check_result check_result_info; char *temp_path; int dbuf_init(dbuf *db, int chunk_size) {} int update_check_stats(int check_type, time_t check_time) {} int set_all_macro_environment_vars_r(nagios_macros *mac, int set) {} int close_command_file(void) {} void reset_sighandler(void) {} -void service_check_sighandler(int sig) {} unsigned long max_debug_file_size = DEFAULT_MAX_DEBUG_FILE_SIZE; int host_check_timeout = DEFAULT_HOST_CHECK_TIMEOUT; int broker_host_check(int type, int flags, int attr, host *hst, int check_type, int state, int state_type, struct timeval start_time, struct timeval end_time, char *cmd, double latency, double exectime, int timeout, int early_timeout, int retcode, char *cmdline, char *output, char *long_output, char *perfdata, struct timeval *timestamp) {} @@ -158,7 +142,6 @@ int dbuf_strcat(dbuf *db, char *buf) {} int dbuf_free(dbuf *db) {} unsigned long next_event_id = 0L; unsigned long next_problem_id = 0L; -int move_check_result_to_queue(char *checkresult_file) {} int free_child_process_memory = -1; void free_memory(nagios_macros *mac) {} int accept_passive_service_checks = TRUE; @@ -186,7 +169,6 @@ timed_event *event_list_low_tail = NULL; void remove_event(timed_event *event, timed_event **event_list, timed_event **event_list_tail) {} void reschedule_event(timed_event *event, timed_event **event_list, timed_event **event_list_tail) {} int process_passive_service_check(time_t check_time, char *host_name, char *svc_description, int return_code, char *output) {} -void process_passive_checks(void) {} int soft_state_dependencies = FALSE; int additional_freshness_latency = DEFAULT_ADDITIONAL_FRESHNESS_LATENCY; hostdependency *get_first_hostdependency_by_dependent_host(char *host_name, void **ptr) { @@ -196,7 +178,6 @@ hostdependency *get_first_hostdependency_by_dependent_host(char *host_name, void hostdependency *get_next_hostdependency_by_dependent_host(char *host_name, void **ptr) {} int currently_running_host_checks = 0; int my_system_r(nagios_macros *mac, char *cmd, int timeout, int *early_timeout, double *exectime, char **output, int max_output_length) {} -void host_check_sighandler(int sig) {} int accept_passive_host_checks = TRUE; int passive_host_checks_are_soft = DEFAULT_PASSIVE_HOST_CHECKS_SOFT; int translate_passive_host_checks = DEFAULT_TRANSLATE_PASSIVE_HOST_CHECKS; diff --git a/t-tap/test_checks.c b/t-tap/test_checks.c index 2f0024a..f081bbe 100644 --- a/t-tap/test_checks.c +++ b/t-tap/test_checks.c @@ -16,6 +16,7 @@ * *****************************************************************************/ +#define TEST_CHECKS_C #define NSCORE 1 #include "config.h" #include "comments.h" @@ -26,25 +27,35 @@ #include "nagios.h" #include "broker.h" #include "perfdata.h" +#include "../lib/lnag-utils.h" #include "tap.h" -#include "test-stubs.c" #include "stub_sehandlers.c" #include "stub_comments.c" #include "stub_perfdata.c" #include "stub_downtime.c" -#include "../common/shared.c" +#include "stub_notifications.c" +#include "stub_logging.c" +#include "stub_broker.c" +#include "stub_macros.c" +#include "stub_workers.c" +#include "stub_events.c" +#include "stub_statusdata.c" +#include "stub_flapping.c" +#include "stub_nebmods.c" +#include "stub_netutils.c" +#include "stub_commands.c" +#include "stub_xodtemplate.c" -int log_host_retries = 0; int date_format; /* Test specific functions + variables */ service *svc1 = NULL, *svc2 = NULL; host *host1 = NULL; int found_log_rechecking_host_when_service_wobbles = 0; -int found_log_run_async_host_check_3x = 0; +int found_log_run_async_host_check = 0; check_result *tmp_check_result; -void setup_check_result() { +void setup_check_result(int check_type) { struct timeval start_time, finish_time; start_time.tv_sec = 1234567890L; start_time.tv_usec = 0L; @@ -52,7 +63,7 @@ void setup_check_result() { finish_time.tv_usec = 0L; tmp_check_result = (check_result *)malloc(sizeof(check_result)); - tmp_check_result->check_type = SERVICE_CHECK_ACTIVE; + tmp_check_result->check_type = check_type; tmp_check_result->check_options = 0; tmp_check_result->scheduled_check = TRUE; tmp_check_result->reschedule_check = TRUE; @@ -85,8 +96,8 @@ int log_debug_info(int level, int verbosity, const char *fmt, ...) { if(strcmp(buffer, "Service wobbled between non-OK states, so we'll recheck the host state...\n") == 0) { found_log_rechecking_host_when_service_wobbles++; } - if(strcmp(buffer, "run_async_host_check_3x()\n") == 0) { - found_log_run_async_host_check_3x++; + if(strcmp(buffer, "run_async_host_check()\n") == 0) { + found_log_run_async_host_check++; } free(buffer); va_end(ap); @@ -130,6 +141,7 @@ setup_objects(time_t time) { svc1->host_problem_at_last_check = FALSE; svc1->plugin_output = strdup("Initial state"); svc1->last_hard_state_change = (time_t)1111111111; + svc1->accept_passive_checks = 1; /* Second service .... to be configured! */ svc2 = (service *)calloc(1, sizeof(service)); @@ -144,22 +156,14 @@ setup_objects(time_t time) { } -int -main(int argc, char **argv) { - time_t now = 0L; - - - plan_tests(42); - - time(&now); - +void run_service_check_tests(int check_type, time_t when) { /* Test to confirm that if a service is warning, the notified_on_critical is reset */ tmp_check_result = (check_result *)calloc(1, sizeof(check_result)); tmp_check_result->host_name = strdup("host1"); tmp_check_result->service_description = strdup("Normal service"); tmp_check_result->object_check_type = SERVICE_CHECK; - tmp_check_result->check_type = SERVICE_CHECK_ACTIVE; + tmp_check_result->check_type = check_type; tmp_check_result->check_options = 0; tmp_check_result->scheduled_check = TRUE; tmp_check_result->reschedule_check = TRUE; @@ -173,9 +177,9 @@ main(int argc, char **argv) { tmp_check_result->return_code = 1; tmp_check_result->output = strdup("Warning - check notified_on_critical reset"); - setup_objects(now); + setup_objects(when); svc1->last_state = STATE_CRITICAL; - svc1->notified_on_critical = TRUE; + svc1->notification_options = OPT_CRITICAL; svc1->current_notification_number = 999; svc1->last_notification = (time_t)11111; svc1->next_notification = (time_t)22222; @@ -199,14 +203,12 @@ main(int argc, char **argv) { host1->current_state = HOST_DOWN; svc1->current_state = STATE_OK; svc1->state_type = HARD_STATE; - setup_check_result(); + setup_check_result(check_type); tmp_check_result->return_code = STATE_CRITICAL; tmp_check_result->output = strdup("CRITICAL failure"); - log_service_event_flag = 0; handle_async_service_check_result(svc1, tmp_check_result); - ok(log_service_event_flag == 1, "log_service_event() was called"); ok(svc1->last_hard_state_change == (time_t)1234567890, "Got last_hard_state_change time=%lu", svc1->last_hard_state_change); ok(svc1->last_state_change == svc1->last_hard_state_change, "Got same last_state_change"); ok(svc1->last_hard_state == 2, "Should save the last hard state as critical for next time"); @@ -222,7 +224,7 @@ main(int argc, char **argv) { OK -> WARNING 1/4 -> ack -> WARNING 2/4 -> OK transition Tests that the ack is left for 2/4 */ - setup_objects(now); + setup_objects(when); host1->current_state = HOST_UP; host1->max_attempts = 4; svc1->last_state = STATE_OK; @@ -230,7 +232,7 @@ main(int argc, char **argv) { svc1->current_state = STATE_OK; svc1->state_type = SOFT_STATE; - setup_check_result(); + setup_check_result(check_type); tmp_check_result->return_code = STATE_WARNING; tmp_check_result->output = strdup("WARNING failure"); handle_async_service_check_result(svc1, tmp_check_result); @@ -243,14 +245,14 @@ main(int argc, char **argv) { svc1->acknowledgement_type = ACKNOWLEDGEMENT_NORMAL; - setup_check_result(); + setup_check_result(check_type); tmp_check_result->return_code = STATE_WARNING; tmp_check_result->output = strdup("WARNING failure"); handle_async_service_check_result(svc1, tmp_check_result); ok(svc1->acknowledgement_type == ACKNOWLEDGEMENT_NORMAL, "Ack left"); - setup_check_result(); + setup_check_result(check_type); tmp_check_result->return_code = STATE_OK; tmp_check_result->output = strdup("Back to OK"); handle_async_service_check_result(svc1, tmp_check_result); @@ -264,7 +266,7 @@ main(int argc, char **argv) { OK -> WARNING 1/4 -> ack -> WARNING 2/4 -> WARNING 3/4 -> WARNING 4/4 -> WARNING 4/4 -> OK transition Tests that the ack is not removed on hard state change */ - setup_objects(now); + setup_objects(when); host1->current_state = HOST_UP; host1->max_attempts = 4; svc1->last_state = STATE_OK; @@ -273,12 +275,14 @@ main(int argc, char **argv) { svc1->state_type = SOFT_STATE; svc1->current_attempt = 1; - setup_check_result(); + setup_check_result(check_type); tmp_check_result->return_code = STATE_OK; tmp_check_result->output = strdup("Reset to OK"); handle_async_service_check_result(svc1, tmp_check_result); + ok(svc1->current_attempt == 1, "Current attempt is 1") || + diag("Current attempt now: %d", svc1->current_attempt); - setup_check_result(); + setup_check_result(check_type); tmp_check_result->return_code = STATE_WARNING; tmp_check_result->output = strdup("WARNING failure 1"); handle_async_service_check_result(svc1, tmp_check_result); @@ -287,29 +291,37 @@ main(int argc, char **argv) { ok(svc1->acknowledgement_type == ACKNOWLEDGEMENT_NONE, "No acks - testing transition to hard warning state"); svc1->acknowledgement_type = ACKNOWLEDGEMENT_NORMAL; + ok(svc1->current_attempt == 1, "Current attempt is 1") || + diag("Current attempt now: %d", svc1->current_attempt); - setup_check_result(); + setup_check_result(check_type); tmp_check_result->return_code = STATE_WARNING; tmp_check_result->output = strdup("WARNING failure 2"); handle_async_service_check_result(svc1, tmp_check_result); ok(svc1->state_type == SOFT_STATE, "Soft state"); ok(svc1->acknowledgement_type == ACKNOWLEDGEMENT_NORMAL, "Ack left"); + ok(svc1->current_attempt == 2, "Current attempt is 2") || + diag("Current attempt now: %d", svc1->current_attempt); - setup_check_result(); + setup_check_result(check_type); tmp_check_result->return_code = STATE_WARNING; tmp_check_result->output = strdup("WARNING failure 3"); handle_async_service_check_result(svc1, tmp_check_result); ok(svc1->state_type == SOFT_STATE, "Soft state"); ok(svc1->acknowledgement_type == ACKNOWLEDGEMENT_NORMAL, "Ack left"); + ok(svc1->current_attempt == 3, "Current attempt is 3") || + diag("Current attempt now: %d", svc1->current_attempt); - setup_check_result(); + setup_check_result(check_type); tmp_check_result->return_code = STATE_WARNING; tmp_check_result->output = strdup("WARNING failure 4"); handle_async_service_check_result(svc1, tmp_check_result); ok(svc1->state_type == HARD_STATE, "Hard state"); ok(svc1->acknowledgement_type == ACKNOWLEDGEMENT_NORMAL, "Ack left on hard failure"); + ok(svc1->current_attempt == 4, "Current attempt is 4") || + diag("Current attempt now: %d", svc1->current_attempt); - setup_check_result(); + setup_check_result(check_type); tmp_check_result->return_code = STATE_OK; tmp_check_result->output = strdup("Back to OK"); handle_async_service_check_result(svc1, tmp_check_result); @@ -322,7 +334,7 @@ main(int argc, char **argv) { OK -> WARNING 1/1 -> ack -> WARNING -> OK transition Tests that the ack is not removed on 2nd warning, but is on OK */ - setup_objects(now); + setup_objects(when); host1->current_state = HOST_UP; host1->max_attempts = 4; svc1->last_state = STATE_OK; @@ -331,7 +343,7 @@ main(int argc, char **argv) { svc1->state_type = SOFT_STATE; svc1->current_attempt = 1; svc1->max_attempts = 2; - setup_check_result(); + setup_check_result(check_type); tmp_check_result->return_code = STATE_WARNING; tmp_check_result->output = strdup("WARNING failure 1"); @@ -341,13 +353,13 @@ main(int argc, char **argv) { svc1->acknowledgement_type = ACKNOWLEDGEMENT_NORMAL; - setup_check_result(); + setup_check_result(check_type); tmp_check_result->return_code = STATE_WARNING; tmp_check_result->output = strdup("WARNING failure 2"); handle_async_service_check_result(svc1, tmp_check_result); ok(svc1->acknowledgement_type == ACKNOWLEDGEMENT_NORMAL, "Ack left"); - setup_check_result(); + setup_check_result(check_type); tmp_check_result->return_code = STATE_OK; tmp_check_result->output = strdup("Back to OK"); handle_async_service_check_result(svc1, tmp_check_result); @@ -358,7 +370,7 @@ main(int argc, char **argv) { UP -> DOWN 1/4 -> ack -> DOWN 2/4 -> DOWN 3/4 -> DOWN 4/4 -> UP transition Tests that the ack is not removed on 2nd DOWN, but is on UP */ - setup_objects(now); + setup_objects(when); host1->current_state = HOST_UP; host1->last_state = HOST_UP; host1->last_hard_state = HOST_UP; @@ -369,15 +381,15 @@ main(int argc, char **argv) { host1->plugin_output = strdup(""); host1->long_plugin_output = strdup(""); host1->perf_data = strdup(""); - host1->host_check_command = strdup("Dummy command required"); - host1->accept_passive_host_checks = TRUE; + host1->check_command = strdup("Dummy command required"); + host1->accept_passive_checks = TRUE; passive_host_checks_are_soft = TRUE; - setup_check_result(); + setup_check_result(check_type); tmp_check_result->return_code = STATE_CRITICAL; tmp_check_result->output = strdup("DOWN failure 2"); tmp_check_result->check_type = HOST_CHECK_PASSIVE; - handle_async_host_check_result_3x(host1, tmp_check_result); + handle_async_host_check_result(host1, tmp_check_result); ok(host1->acknowledgement_type == ACKNOWLEDGEMENT_NONE, "No ack set"); ok(host1->current_attempt == 2, "Attempts right (not sure why this goes into 2 and not 1)") || diag("current_attempt=%d", host1->current_attempt); ok(strcmp(host1->plugin_output, "DOWN failure 2") == 0, "output set") || diag("plugin_output=%s", host1->plugin_output); @@ -385,14 +397,14 @@ main(int argc, char **argv) { host1->acknowledgement_type = ACKNOWLEDGEMENT_NORMAL; tmp_check_result->output = strdup("DOWN failure 3"); - handle_async_host_check_result_3x(host1, tmp_check_result); + handle_async_host_check_result(host1, tmp_check_result); ok(host1->acknowledgement_type == ACKNOWLEDGEMENT_NORMAL, "Ack should be retained as in soft state"); ok(host1->current_attempt == 3, "Attempts incremented") || diag("current_attempt=%d", host1->current_attempt); ok(strcmp(host1->plugin_output, "DOWN failure 3") == 0, "output set") || diag("plugin_output=%s", host1->plugin_output); tmp_check_result->output = strdup("DOWN failure 4"); - handle_async_host_check_result_3x(host1, tmp_check_result); + handle_async_host_check_result(host1, tmp_check_result); ok(host1->acknowledgement_type == ACKNOWLEDGEMENT_NORMAL, "Ack should be retained as in soft state"); ok(host1->current_attempt == 4, "Attempts incremented") || diag("current_attempt=%d", host1->current_attempt); ok(strcmp(host1->plugin_output, "DOWN failure 4") == 0, "output set") || diag("plugin_output=%s", host1->plugin_output); @@ -400,12 +412,28 @@ main(int argc, char **argv) { tmp_check_result->return_code = STATE_OK; tmp_check_result->output = strdup("UP again"); - handle_async_host_check_result_3x(host1, tmp_check_result); + handle_async_host_check_result(host1, tmp_check_result); ok(host1->acknowledgement_type == ACKNOWLEDGEMENT_NONE, "Ack reset due to state change"); ok(host1->current_attempt == 1, "Attempts reset") || diag("current_attempt=%d", host1->current_attempt); ok(strcmp(host1->plugin_output, "UP again") == 0, "output set") || diag("plugin_output=%s", host1->plugin_output); + } + +int +main(int argc, char **argv) { + time_t now = 0L; + + accept_passive_host_checks = TRUE; + accept_passive_service_checks = TRUE; + + plan_tests(92); + + time(&now); + + run_service_check_tests(SERVICE_CHECK_ACTIVE, now); + run_service_check_tests(SERVICE_CHECK_PASSIVE, now); + return exit_status(); } diff --git a/t-tap/test_commands.c b/t-tap/test_commands.c index 5b16ac9..6b59b3e 100644 --- a/t-tap/test_commands.c +++ b/t-tap/test_commands.c @@ -33,25 +33,14 @@ #include "stub_utils.c" #include "stub_sretention.c" #include "stub_checks.c" +#include "stub_macros.c" #include "tap.h" -void logit(int data_type, int display, const char *fmt, ...) {} -int log_debug_info(int level, int verbosity, const char *fmt, ...) { - va_list ap; - va_start(ap, fmt); - /* vprintf( fmt, ap ); */ - va_end(ap); - } - -circular_buffer external_command_buffer; -time_t last_command_check; -int external_command_buffer_slots; char *temp_path; int date_format; host *host_list; service *service_list; int accept_passive_service_checks; -time_t last_command_status_update; int check_host_freshness; int check_service_freshness; int check_external_commands; @@ -64,7 +53,6 @@ int execute_service_checks; int enable_event_handlers; int accept_passive_host_checks; int accept_passive_service_checks; -int enable_failure_prediction; int process_performance_data; int execute_host_checks; int execute_service_checks; @@ -72,6 +60,11 @@ char *global_service_event_handler; command *global_service_event_handler_ptr; char *global_host_event_handler; command *global_host_event_handler_ptr; +char *command_file = NULL; +iobroker_set *nagios_iobs = NULL; +int sigrestart = FALSE; +int debug_level = 0; +int debug_verbosity = 0; /* Catch lower calls through these stubs */ time_t test_start_time = 0L; diff --git a/t-tap/test_downtime.c b/t-tap/test_downtime.c index 5bc1887..c243867 100644 --- a/t-tap/test_downtime.c +++ b/t-tap/test_downtime.c @@ -23,26 +23,19 @@ #include "downtime.h" #include "stub_broker.c" #include "stub_comments.c" -#include "stub_objects.c" #include "stub_statusdata.c" #include "stub_notifications.c" -#include "stub_shared.c" #include "stub_events.c" +#include "stub_logging.c" +#include "stub_nebmods.c" +#include "stub_netutils.c" +#include "stub_commands.c" +#include "stub_checks.c" #include "tap.h" -void logit(int data_type, int display, const char *fmt, ...) {} -int log_debug_info(int level, int verbosity, const char *fmt, ...) { - va_list ap; - va_start(ap, fmt); - /* vprintf( fmt, ap ); */ - va_end(ap); - } - timed_event *event_list_high = NULL; timed_event *event_list_high_tail = NULL; -unsigned long next_downtime_id = 1L; - extern scheduled_downtime *scheduled_downtime_list; int @@ -53,27 +46,40 @@ main(int argc, char **argv) { unsigned long downtime_id = 0L; scheduled_downtime *temp_downtime; int i = 0; + char *main_config_file = "../t/etc/nagios-test-downtime.cfg"; + + /* Initialize configuration variables */ + init_main_cfg_vars(1); + init_shared_cfg_vars(1); + + /* Read the configuration */ + read_main_config_file(main_config_file); + read_object_config_data(main_config_file, READ_ALL_OBJECT_DATA); + pre_flight_check(); + initialize_downtime_data(); plan_tests(38); time(&now); - schedule_downtime(HOST_DOWNTIME, "host1", NULL, temp_start_time, "user", "test comment", temp_start_time, temp_end_time, 0, 0, 0, &downtime_id); + next_downtime_id = 1L; + + schedule_downtime(HOST_DOWNTIME, "host1", NULL, temp_start_time, "user", "test comment", temp_start_time, temp_end_time, 1, 0, 0, &downtime_id); ok(downtime_id == 1L, "Got host1 downtime: %lu", downtime_id); - schedule_downtime(HOST_DOWNTIME, "host2", NULL, temp_start_time, "user", "test comment", temp_start_time, temp_end_time, 0, 0, 0, &downtime_id); + schedule_downtime(HOST_DOWNTIME, "host2", NULL, temp_start_time, "user", "test comment", temp_start_time, temp_end_time, 1, 0, 0, &downtime_id); ok(downtime_id == 2L, "Got host2 downtime: %lu", downtime_id); - schedule_downtime(HOST_DOWNTIME, "host3", NULL, temp_start_time, "user", "diff comment", temp_start_time, temp_end_time, 0, 0, 0, &downtime_id); + schedule_downtime(HOST_DOWNTIME, "host3", NULL, temp_start_time, "user", "diff comment", temp_start_time, temp_end_time, 1, 0, 0, &downtime_id); ok(downtime_id == 3L, "Got host3 downtime: %lu", downtime_id); - schedule_downtime(HOST_DOWNTIME, "host4", NULL, temp_start_time, "user", "test comment", temp_start_time + 1, temp_end_time, 0, 0, 0, &downtime_id); + schedule_downtime(HOST_DOWNTIME, "host4", NULL, temp_start_time, "user", "test comment", temp_start_time + 1, temp_end_time, 1, 0, 0, &downtime_id); ok(downtime_id == 4L, "Got host4 downtime: %lu", downtime_id); - schedule_downtime(SERVICE_DOWNTIME, "host1", "svc", temp_start_time, "user", "svc comment", temp_start_time, temp_end_time, 0, 0, 0, &downtime_id); + schedule_downtime(SERVICE_DOWNTIME, "host1", "svc", temp_start_time, "user", "svc comment", temp_start_time, temp_end_time, 1, 0, 0, &downtime_id); ok(downtime_id == 5L, "Got host1::svc downtime: %lu", downtime_id); - schedule_downtime(SERVICE_DOWNTIME, "host2", "svc", temp_start_time, "user", "diff comment", temp_start_time, temp_end_time, 0, 0, 0, &downtime_id); + schedule_downtime(SERVICE_DOWNTIME, "host2", "svc", temp_start_time, "user", "diff comment", temp_start_time, temp_end_time, 1, 0, 0, &downtime_id); ok(downtime_id == 6L, "Got host2::svc downtime: %lu", downtime_id); - schedule_downtime(SERVICE_DOWNTIME, "host3", "svc", temp_start_time, "user", "svc comment", temp_start_time + 1, temp_end_time, 0, 0, 0, &downtime_id); + schedule_downtime(SERVICE_DOWNTIME, "host3", "svc", temp_start_time, "user", "svc comment", temp_start_time + 1, temp_end_time, 1, 0, 0, &downtime_id); ok(downtime_id == 7L, "Got host3::svc downtime: %lu", downtime_id); - schedule_downtime(SERVICE_DOWNTIME, "host4", "svc", temp_start_time, "user", "uniq comment", temp_start_time, temp_end_time, 0, 0, 0, &downtime_id); + schedule_downtime(SERVICE_DOWNTIME, "host4", "svc", temp_start_time, "user", "uniq comment", temp_start_time, temp_end_time, 1, 0, 0, &downtime_id); ok(downtime_id == 8L, "Got host4::svc downtime: %lu", downtime_id); for(temp_downtime = scheduled_downtime_list, i = 0; temp_downtime != NULL; temp_downtime = temp_downtime->next, i++) {} @@ -101,7 +107,7 @@ main(int argc, char **argv) { ok(i == 1, "Deleted 1 by unique comment: %d", i); for(temp_downtime = scheduled_downtime_list, i = 0; temp_downtime != NULL; temp_downtime = temp_downtime->next, i++) { - diag("downtime id: %d", temp_downtime->downtime_id); + printf("# downtime id: %d\n", temp_downtime->downtime_id); } ok(i == 3, "Got 3 downtimes left: %d", i); @@ -114,31 +120,31 @@ main(int argc, char **argv) { /* Set all downtimes up again */ - schedule_downtime(HOST_DOWNTIME, "host1", NULL, temp_start_time, "user", "test comment", temp_start_time, temp_end_time, 0, 0, 0, &downtime_id); + schedule_downtime(HOST_DOWNTIME, "host1", NULL, temp_start_time, "user", "test comment", temp_start_time, temp_end_time, 1, 0, 0, &downtime_id); ok(downtime_id == 9L, "Got host1 downtime: %lu", downtime_id); - schedule_downtime(HOST_DOWNTIME, "host2", NULL, temp_start_time, "user", "test comment", temp_start_time, temp_end_time, 0, 0, 0, &downtime_id); + schedule_downtime(HOST_DOWNTIME, "host2", NULL, temp_start_time, "user", "test comment", temp_start_time, temp_end_time, 1, 0, 0, &downtime_id); ok(downtime_id == 10L, "Got host2 downtime: %lu", downtime_id); - schedule_downtime(HOST_DOWNTIME, "host3", NULL, temp_start_time, "user", "diff comment", temp_start_time + 1, temp_end_time, 0, 0, 0, &downtime_id); + schedule_downtime(HOST_DOWNTIME, "host3", NULL, temp_start_time, "user", "diff comment", temp_start_time + 1, temp_end_time, 1, 0, 0, &downtime_id); ok(downtime_id == 11L, "Got host3 downtime: %lu", downtime_id); - schedule_downtime(HOST_DOWNTIME, "host4", NULL, temp_start_time, "user", "test comment", temp_start_time + 1, temp_end_time, 0, 0, 0, &downtime_id); + schedule_downtime(HOST_DOWNTIME, "host4", NULL, temp_start_time, "user", "test comment", temp_start_time + 1, temp_end_time, 1, 0, 0, &downtime_id); ok(downtime_id == 12L, "Got host4 downtime: %lu", downtime_id); - schedule_downtime(SERVICE_DOWNTIME, "host1", "svc", temp_start_time, "user", "svc comment", temp_start_time, temp_end_time, 0, 0, 0, &downtime_id); + schedule_downtime(SERVICE_DOWNTIME, "host1", "svc", temp_start_time, "user", "svc comment", temp_start_time, temp_end_time, 1, 0, 0, &downtime_id); ok(downtime_id == 13L, "Got host1::svc downtime: %lu", downtime_id); - schedule_downtime(SERVICE_DOWNTIME, "host2", "svc", temp_start_time, "user", "diff comment", temp_start_time, temp_end_time, 0, 0, 0, &downtime_id); + schedule_downtime(SERVICE_DOWNTIME, "host2", "svc", temp_start_time, "user", "diff comment", temp_start_time, temp_end_time, 1, 0, 0, &downtime_id); ok(downtime_id == 14L, "Got host2::svc downtime: %lu", downtime_id); - schedule_downtime(SERVICE_DOWNTIME, "host3", "svc", temp_start_time, "user", "svc comment", temp_start_time, temp_end_time, 0, 0, 0, &downtime_id); + schedule_downtime(SERVICE_DOWNTIME, "host3", "svc", temp_start_time, "user", "svc comment", temp_start_time, temp_end_time, 1, 0, 0, &downtime_id); ok(downtime_id == 15L, "Got host3::svc downtime: %lu", downtime_id); - schedule_downtime(SERVICE_DOWNTIME, "host4", "svc", temp_start_time, "user", "uniq comment", temp_start_time, temp_end_time, 0, 0, 0, &downtime_id); + schedule_downtime(SERVICE_DOWNTIME, "host4", "svc", temp_start_time, "user", "uniq comment", temp_start_time, temp_end_time, 1, 0, 0, &downtime_id); ok(downtime_id == 16L, "Got host4::svc downtime: %lu", downtime_id); - schedule_downtime(SERVICE_DOWNTIME, "host1", "svc2", temp_start_time, "user", "svc2 comment", temp_start_time, temp_end_time, 0, 0, 0, &downtime_id); + schedule_downtime(SERVICE_DOWNTIME, "host1", "svc2", temp_start_time, "user", "svc2 comment", temp_start_time, temp_end_time, 1, 0, 0, &downtime_id); ok(downtime_id == 17L, "Got host1::svc2 downtime: %lu", downtime_id); - schedule_downtime(SERVICE_DOWNTIME, "host2", "svc2", temp_start_time, "user", "test comment", temp_start_time, temp_end_time, 0, 0, 0, &downtime_id); + schedule_downtime(SERVICE_DOWNTIME, "host2", "svc2", temp_start_time, "user", "test comment", temp_start_time, temp_end_time, 1, 0, 0, &downtime_id); ok(downtime_id == 18L, "Got host2::svc2 downtime: %lu", downtime_id); - schedule_downtime(SERVICE_DOWNTIME, "host3", "svc2", temp_start_time, "user", "svc2 comment", temp_start_time + 1, temp_end_time, 0, 0, 0, &downtime_id); + schedule_downtime(SERVICE_DOWNTIME, "host3", "svc2", temp_start_time, "user", "svc2 comment", temp_start_time + 1, temp_end_time, 1, 0, 0, &downtime_id); ok(downtime_id == 19L, "Got host3::svc2 downtime: %lu", downtime_id); - schedule_downtime(SERVICE_DOWNTIME, "host4", "svc2", temp_start_time, "user", "test comment", temp_start_time, temp_end_time, 0, 0, 0, &downtime_id); + schedule_downtime(SERVICE_DOWNTIME, "host4", "svc2", temp_start_time, "user", "test comment", temp_start_time, temp_end_time, 1, 0, 0, &downtime_id); ok(downtime_id == 20L, "Got host4::svc2 downtime: %lu", downtime_id); i = delete_downtime_by_hostname_service_description_start_time_comment("host2", NULL, 0, "test comment"); @@ -160,7 +166,7 @@ main(int argc, char **argv) { ok(i == 0, "Deleted 0") || diag("Actually deleted: %d", i); for(temp_downtime = scheduled_downtime_list, i = 0; temp_downtime != NULL; temp_downtime = temp_downtime->next, i++) { - diag("downtime id: %d", temp_downtime->downtime_id); + printf("# downtime id: %d\n", temp_downtime->downtime_id); } ok(i == 4, "Got 4 downtimes left: %d", i); diff --git a/t-tap/test_events.c b/t-tap/test_events.c index e71990e..8fc5b5a 100644 --- a/t-tap/test_events.c +++ b/t-tap/test_events.c @@ -16,6 +16,8 @@ * *****************************************************************************/ +#define TEST_EVENTS_C + #define NSCORE 1 #include "config.h" #include "common.h" @@ -26,90 +28,30 @@ #include "broker.h" #include "sretention.h" #include "tap.h" +#include "stub_logging.c" +#include "stub_broker.c" +#include "stub_sretention.c" +#include "stub_statusdata.c" +#include "stub_downtime.c" +#include "stub_comments.c" +#include "stub_notifications.c" +#include "stub_workers.c" +#include "stub_nebmods.c" +#include "stub_netutils.c" +#include "stub_commands.c" +#include "stub_flapping.c" +#include "stub_sehandlers.c" +#include "stub_perfdata.c" +#include "stub_nsock.c" +#include "stub_iobroker.c" -char *config_file = "etc/nagios.cfg"; -int test_scheduling; - -time_t program_start; -time_t event_start; -time_t last_command_check; - -int sigshutdown = FALSE; -int sigrestart = FALSE; - -double sleep_time; -int interval_length = 60; -int service_inter_check_delay_method; -int host_inter_check_delay_method; -int service_interleave_factor_method; -int max_host_check_spread; -int max_service_check_spread; - -int command_check_interval; -int check_reaper_interval; -int service_freshness_check_interval; -int host_freshness_check_interval; -int auto_rescheduling_interval; -int host_freshness_check_interval; -int auto_rescheduling_interval; -int auto_rescheduling_window; - -int check_external_commands; -int check_orphaned_services; -int check_orphaned_hosts; -int check_service_freshness; -int check_host_freshness; -int auto_reschedule_checks; - -int retain_state_information; -int retention_update_interval; - -int max_parallel_service_checks; -int currently_running_service_checks; - -int aggregate_status_updates; -int status_update_interval; - -int log_rotation_method; - -int service_check_timeout; - -int execute_service_checks = 1; -int execute_host_checks; - -int child_processes_fork_twice; - -int time_change_threshold; - - -extern timed_event *event_list_low; -extern timed_event *event_list_low_tail; -extern timed_event *event_list_high; -extern timed_event *event_list_high_tail; - -host *host_list; -service *service_list; - -int check_for_expired_comment(unsigned long temp_long) {} -void broker_timed_event(int int1, int int2, int int3, timed_event *timed_event1, struct timeval *timeval1) {} int perform_scheduled_host_check(host *temp_host, int int1, double double1) { time_t now = 0L; time(&now); temp_host->last_check = now; } -int check_for_expired_downtime(void) {} -int reap_check_results(void) {} -void check_host_result_freshness() {} -int check_for_nagios_updates(int int1, int int2) {} -time_t get_next_service_notification_time(service *temp_service, time_t time_t1) {} -int save_state_information(int int1) {} -void get_time_breakdown(unsigned long long1, int *int1, int *int2, int *int3, int *int4) {} -int check_for_external_commands(void) {} -void check_for_orphaned_hosts() {} -void check_service_result_freshness() {} -int check_time_against_period(time_t time_t1, timeperiod *timeperiod) {} -time_t get_next_log_rotation_time(void) {} -void check_for_orphaned_services() {} + +#if 0 int run_scheduled_service_check(service *service1, int int1, double double1) { currently_running_service_checks++; time_t now = 0L; @@ -117,11 +59,7 @@ int run_scheduled_service_check(service *service1, int int1, double double1) { service1->last_check = now; /* printf("Currently running service checks: %d\n", currently_running_service_checks); */ } -int handle_scheduled_downtime_by_id(unsigned long long1) {} -int rotate_log_file(time_t time_t1) {} -time_t get_next_host_notification_time(host *temp_host, time_t time_t1) {} -void get_next_valid_time(time_t time_t1, time_t *time_t2, timeperiod *temp_timeperiod) {} -void logit(int int1, int int2, const char *fmt, ...) {} +#endif int c = 0; int update_program_status(int aggregated_dump) { @@ -134,28 +72,24 @@ int update_program_status(int aggregated_dump) { c = 0; } } -int update_service_status(service *svc, int aggregated_dump) {} -int update_all_status_data(void) {} -int log_debug_info(int level, int verbosity, const char *fmt, ...) { - va_list ap; - va_start(ap, fmt); - /* vprintf( fmt, ap ); */ - va_end(ap); - } -int update_host_status(host *hst, int aggregated_dump) {} /* Test variables */ service *svc1 = NULL, *svc2 = NULL, *svc3 = NULL; host *host1 = NULL; +void test_event_process_svc1_results(void *args) { + check_result *tmp_check_result = (check_result *)args; + service *svc = find_service(tmp_check_result->host_name, + tmp_check_result->service_description); + handle_async_service_check_result(svc, tmp_check_result); +} + void setup_events(time_t time) { timed_event *new_event = NULL; /* First service is a normal one */ - svc1 = (service *)malloc(sizeof(service)); - svc1->host_name = strdup("Host1"); - svc1->description = strdup("Normal service"); + svc1 = find_service("host1", "Normal service"); svc1->check_options = 0; svc1->next_check = time; svc1->state_type = SOFT_STATE; @@ -168,17 +102,17 @@ setup_events(time_t time) { new_event->event_data = (void *)svc1; new_event->event_args = (void *)NULL; new_event->event_options = 0; - new_event->run_time = 0L; /* Straight away */ + new_event->priority = 0; + new_event->run_time = svc1->next_check; new_event->recurring = FALSE; new_event->event_interval = 0L; new_event->timing_func = NULL; new_event->compensate_for_time_change = TRUE; - reschedule_event(new_event, &event_list_low, &event_list_low_tail); + new_event->sq_event = NULL; + reschedule_event(nagios_squeue, new_event); /* Second service is one that will get nudged forward */ - svc2 = (service *)malloc(sizeof(service)); - svc2->host_name = strdup("Host1"); - svc2->description = strdup("To be nudged"); + svc2 = find_service("host1", "To be nudged"); svc2->check_options = 0; svc2->next_check = time; svc2->state_type = SOFT_STATE; @@ -191,12 +125,55 @@ setup_events(time_t time) { new_event->event_data = (void *)svc2; new_event->event_args = (void *)NULL; new_event->event_options = 0; - new_event->run_time = 0L; /* Straight away */ + new_event->priority = 0; + new_event->run_time = svc2->next_check; new_event->recurring = FALSE; new_event->event_interval = 0L; new_event->timing_func = NULL; new_event->compensate_for_time_change = TRUE; - reschedule_event(new_event, &event_list_low, &event_list_low_tail); + new_event->sq_event = NULL; + reschedule_event(nagios_squeue, new_event); + +} + +setup_svc1_result_events(time_t time) { + timed_event *new_event = NULL; + check_result *tmp_check_result = NULL; + + /* Results for first check */ + tmp_check_result = (check_result *)calloc(1, sizeof(check_result)); + tmp_check_result->host_name = strdup("host1"); + tmp_check_result->service_description = strdup("Normal service"); + tmp_check_result->object_check_type = SERVICE_CHECK; + tmp_check_result->check_type = SERVICE_CHECK_ACTIVE; + tmp_check_result->check_options = 0; + tmp_check_result->scheduled_check = TRUE; + tmp_check_result->reschedule_check = FALSE; + tmp_check_result->latency = 0.666; + tmp_check_result->start_time.tv_sec = time; + tmp_check_result->start_time.tv_usec = 500000; + tmp_check_result->finish_time.tv_sec = time + 4; + tmp_check_result->finish_time.tv_usec = 0; + tmp_check_result->early_timeout = 0; + tmp_check_result->exited_ok = TRUE; + tmp_check_result->return_code = 0; + tmp_check_result->output = strdup("OK - Everything Hunky Dorey"); + + /* Event to process those results */ + new_event = (timed_event *)malloc(sizeof(timed_event)); + new_event->event_type = EVENT_USER_FUNCTION; + new_event->event_data = (void *)test_event_process_svc1_results; + new_event->event_args = (void *)tmp_check_result; + new_event->event_options = 0; + new_event->priority = 0; + new_event->run_time = tmp_check_result->finish_time.tv_sec; + new_event->recurring = FALSE; + new_event->event_interval = 0L; + new_event->timing_func = NULL; + new_event->compensate_for_time_change = TRUE; + new_event->sq_event = NULL; + reschedule_event(nagios_squeue, new_event); + } void @@ -204,10 +181,7 @@ setup_events_with_host(time_t time) { timed_event *new_event = NULL; /* First service is a normal one */ - if(svc3 == NULL) - svc3 = (service *)malloc(sizeof(service)); - svc3->host_name = strdup("Host0"); - svc3->description = strdup("Normal service"); + svc3 = find_service("host1", "Normal service 2"); svc3->check_options = 0; svc3->next_check = time; svc3->state_type = SOFT_STATE; @@ -220,64 +194,88 @@ setup_events_with_host(time_t time) { new_event->event_data = (void *)svc3; new_event->event_args = (void *)NULL; new_event->event_options = 0; - new_event->run_time = 0L; /* Straight away */ + new_event->priority = 0; + new_event->run_time = svc3->next_check; new_event->recurring = FALSE; new_event->event_interval = 0L; new_event->timing_func = NULL; new_event->compensate_for_time_change = TRUE; - reschedule_event(new_event, &event_list_low, &event_list_low_tail); + new_event->sq_event = NULL; + reschedule_event(nagios_squeue, new_event); - if(host1 == NULL) - host1 = (host *)malloc(sizeof(host)); - host1->name = strdup("Host1"); - host1->address = strdup("127.0.0.1"); + host1 = find_host("host1"); host1->retry_interval = 1; host1->check_interval = 5; host1->check_options = 0; host1->next_check = time; - new_event->recurring = TRUE; host1->state_type = SOFT_STATE; host1->current_state = STATE_OK; + host1->is_executing = 0; new_event = (timed_event *)malloc(sizeof(timed_event)); new_event->event_type = EVENT_HOST_CHECK; new_event->event_data = (void *)host1; new_event->event_args = (void *)NULL; new_event->event_options = 0; - new_event->run_time = 0L; /* Straight away */ - new_event->recurring = TRUE; + new_event->priority = 0; + new_event->run_time = host1->next_check; + new_event->recurring = FALSE; new_event->event_interval = 0L; new_event->timing_func = NULL; new_event->compensate_for_time_change = TRUE; - reschedule_event(new_event, &event_list_low, &event_list_low_tail); + new_event->sq_event = NULL; + reschedule_event(nagios_squeue, new_event); } int main(int argc, char **argv) { + int result; time_t now = 0L; + char *main_config_file = "../t/etc/nagios-test-events.cfg"; - plan_tests(10); + /* Initialize configuration variables */ + init_main_cfg_vars(1); + init_shared_cfg_vars(1); - time(&now); + /* Read the configuration */ + read_main_config_file(main_config_file); + read_object_config_data(main_config_file, READ_ALL_OBJECT_DATA); + pre_flight_check(); + plan_tests(11); + + interval_length = 60; + + nagios_squeue = squeue_create(4096); + ok(nagios_squeue != NULL, "Created nagios squeue"); + + execute_service_checks = 1; currently_running_service_checks = 0; max_parallel_service_checks = 1; + time(&now); setup_events(now); + setup_svc1_result_events(now); + printf("# Running execution loop - may take some time...\n"); event_execution_loop(); - ok(svc1->next_check == now, "svc1 has not had its next check time changed"); - printf("# Nudge amount: %d\n", svc2->next_check - now); - ok(svc2->next_check > now + 5 && svc2->next_check < now + 5 + 10, "svc2 has been nudged"); + ok(svc1->last_check == now, "svc1 has not had its next check time changed") + || diag("last_check = now: %ld", svc1->last_check - now); + ok(svc2->next_check > now + NUDGE_MIN && svc2->next_check < now + NUDGE_MAX, + "svc2 has been nudged") || + diag("Nudge amount: %ld\n", svc2->next_check - now); sigshutdown = FALSE; currently_running_service_checks = 0; max_parallel_service_checks = 2; + time(&now); setup_events(now); + printf("# Running execution loop - may take some time...\n"); event_execution_loop(); - ok(svc1->next_check == now, "svc1 has not had its next check time changed"); - printf("# Nudge amount: %d\n", svc2->next_check - now); - ok(svc2->next_check == now, "svc2 also has not changed, because can execute"); + ok(svc1->next_check == now, "svc1 has not had its next check time changed") + || diag("next_check - now: %ld", svc1->next_check - now); + ok(svc2->next_check == now, "svc2 also has not changed, because can execute") + || diag("Nudge amount: %ld\n", svc2->next_check - now); /* This test should have both services moved forward due to not executing any service checks */ @@ -286,32 +284,38 @@ main(int argc, char **argv) { sigshutdown = FALSE; currently_running_service_checks = 0; max_parallel_service_checks = 2; + time(&now); setup_events(now); svc2->current_state = STATE_CRITICAL; + printf("# Running execution loop - may take some time...\n"); event_execution_loop(); - ok(svc1->next_check == now + 300, "svc1 rescheduled ahead - normal interval"); - ok(svc2->next_check == now + 60, "svc2 rescheduled ahead - retry interval"); - + ok(svc1->next_check == now + 300, "svc1 rescheduled ahead - normal interval") + || diag("next_check - now: %ld", svc1->next_check - now); + ok(svc2->next_check == now + 60, "svc2 rescheduled ahead - retry interval") + || diag("next_check - now: %ld", svc2->next_check - now); /* Checking that a host check immediately following a service check * correctly checks the host */ - timed_event *temp_event = NULL; - while((temp_event = event_list_low) != NULL) { - remove_event(temp_event, &event_list_low, &event_list_low_tail); - } + squeue_destroy(nagios_squeue, 0); + nagios_squeue = squeue_create(4096); sigshutdown = FALSE; currently_running_service_checks = 0; max_parallel_service_checks = 2; execute_service_checks = 0; execute_host_checks = 1; + time(&now); setup_events_with_host(now); + printf("# Running execution loop - may take some time...\n"); event_execution_loop(); - ok(host1->last_check - now <= 2, "host1 was checked (within 2 seconds tolerance)") || diag("last_check:%lu now:%lu", host1->last_check, now); + ok(host1->last_check - now <= 2, + "host1 was checked (within 2 seconds tolerance)") || + diag("last_check - now: %ld", host1->last_check - now); ok(svc3->last_check == 0, "svc3 was skipped"); - ok(host1->next_check == now, "host1 rescheduled ahead - normal interval"); + ok(host1->next_check == now, "host1 rescheduled ahead - normal interval") + || diag("next_check - now: %ld", host1->next_check - now); ok(svc3->next_check == now + 300, "svc3 rescheduled ahead - normal interval"); return exit_status(); diff --git a/t-tap/test_logging.c b/t-tap/test_logging.c index 63942ea..6ddb3e6 100644 --- a/t-tap/test_logging.c +++ b/t-tap/test_logging.c @@ -21,12 +21,27 @@ #include "nagios.h" #include "objects.h" #include "tap.h" -#include "../common/shared.c" +#include "stub_broker.c" +#include "stub_xodtemplate.c" #define TEST_LOGGING 1 -#include "test-stubs.c" int date_format; +char *log_file = NULL; +int verify_config = FALSE; +int test_scheduling = FALSE; +int debug_level = DEFAULT_DEBUG_LEVEL; +char *debug_file; +int debug_verbosity = DEFAULT_DEBUG_VERBOSITY; +unsigned long max_debug_file_size = DEFAULT_MAX_DEBUG_FILE_SIZE; +int use_syslog = DEFAULT_USE_SYSLOG; +unsigned long syslog_options = 0; +unsigned long logging_options = 0; +int log_initial_states = DEFAULT_LOG_INITIAL_STATES; +char *log_archive_path = "var"; +int log_current_states = DEFAULT_LOG_CURRENT_STATES; +int log_service_retries = DEFAULT_LOG_SERVICE_RETRIES; +int use_large_installation_tweaks = DEFAULT_USE_LARGE_INSTALLATION_TWEAKS; char *saved_source; char *saved_dest; @@ -64,13 +79,16 @@ main(int argc, char **argv) { log_rotation_method = LOG_ROTATION_HOURLY; ok(rotate_log_file(rotation_time) == ERROR, "Got an error with rename"); ok(strcmp(saved_dest, log_filename_localtime) == 0, "Got an hourly rotation"); + unlink(log_file); log_file = "var/nagios.log"; log_rotation_method = LOG_ROTATION_HOURLY; ok(system("cp var/nagios.log.dummy var/nagios.log") == 0, "Copied in dummy nagios.log for archiving"); ok(rotate_log_file(rotation_time) == OK, "Log rotation should work happily"); - ok(system("diff var/nagios.log var/nagios.log.expected > /dev/null") == 0, "Got correct contents of nagios.log"); + system("diff var/nagios.log var/nagios.log.expected > var/nagios.log.diff"); + ok(system("diff var/nagios.log.diff var/nagios.log.diff.expected > /dev/null") == 0, "Got correct contents of nagios.log"); + unlink("var/nagios.log.diff"); asprintf(&temp_command, "diff var/nagios.log.dummy %s", log_filename_localtime); ok(system(temp_command) == 0, "nagios log archived correctly"); @@ -84,6 +102,7 @@ main(int argc, char **argv) { ok(stat("var/nagios.log", &stat_new) == 0, "Got new stat info for new log file"); ok(stat_info.st_mode == stat_new.st_mode, "Mode for new log file kept same as original log file"); + unlink(log_filename_localtime); return exit_status(); } diff --git a/t-tap/test_macros.c b/t-tap/test_macros.c new file mode 100644 index 0000000..7c7720d --- /dev/null +++ b/t-tap/test_macros.c @@ -0,0 +1,218 @@ +/***************************************************************************** + * + * test_macros.c - Test macro expansion and escaping + * + * Program: Nagios Core Testing + * License: GPL + * + * First Written: 2013-05-21 + * + * Description: + * + * Tests expansion of macros and escaping. + * + * License: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + *****************************************************************************/ + +#include +#include +#include "../include/objects.h" +#include "../include/nagios.h" +#include "tap.h" +#include "stub_downtime.c" +#include "stub_comments.c" + +/*****************************************************************************/ +/* Dummy functions */ +/*****************************************************************************/ +void logit(int data_type, int display, const char *fmt, ...) { +} +int my_sendall(int s, char *buf, int *len, int timeout) { + return 0; +} + +int log_debug_info(int level, int verbosity, const char *fmt, ...) { + return 0; +} + +int neb_free_callback_list(void) { + return 0; +} + +int neb_deinit_modules(void) { + return 0; +} +void broker_program_state(int type, int flags, int attr, + struct timeval *timestamp) { +} +int neb_unload_all_modules(int flags, int reason) { + return 0; +} +int neb_add_module(char *filename, char *args, int should_be_loaded) { + return 0; +} +void broker_system_command(int type, int flags, int attr, + struct timeval start_time, struct timeval end_time, double exectime, + int timeout, int early_timeout, int retcode, char *cmd, char *output, + struct timeval *timestamp) { +} + +timed_event *schedule_new_event(int event_type, int high_priority, + time_t run_time, int recurring, unsigned long event_interval, + void *timing_func, int compensate_for_time_change, void *event_data, + void *event_args, int event_options) { + return NULL ; +} +int my_tcp_connect(char *host_name, int port, int *sd, int timeout) { + return 0; +} +int my_recvall(int s, char *buf, int *len, int timeout) { + return 0; +} +int neb_free_module_list(void) { + return 0; +} +int close_command_file(void) { + return 0; +} +int close_log_file(void) { + return 0; +} +int fix_log_file_owner(uid_t uid, gid_t gid) { + return 0; +} +int handle_async_service_check_result(service *temp_service, + check_result *queued_check_result) { + return 0; +} +int handle_async_host_check_result(host *temp_host, + check_result *queued_check_result) { + return 0; +} + +/*****************************************************************************/ +/* Local test environment */ +/*****************************************************************************/ + +host test_host = { .name = "name'&%", .address = "address'&%", .notes_url = + "notes_url'&%($HOSTNOTES$)", .notes = "notes'&%($HOSTACTIONURL$)", + .action_url = "action_url'&%", .plugin_output = "name'&%" }; + +/*****************************************************************************/ +/* Helper functions */ +/*****************************************************************************/ + +void init_environment() { + char *p; + + my_free(illegal_output_chars); + illegal_output_chars = strdup("'&"); /* For this tests, remove ' and & */ + + /* This is a part of preflight check, which we can't run */ + for (p = illegal_output_chars; *p; p++) { + illegal_output_char_map[(int) *p] = 1; + } +} + +nagios_macros *setup_macro_object(void) { + nagios_macros *mac = (nagios_macros *) calloc(1, sizeof(nagios_macros)); + grab_host_macros_r(mac, &test_host); + return mac; +} + +#define RUN_MACRO_TEST(_STR, _EXPECT, _OPTS) \ + do { \ + if( OK == process_macros_r(mac, (_STR), &output, _OPTS ) ) {\ + ok( 0 == strcmp( output, _EXPECT ), "'%s': '%s' == '%s'", (_STR), output, (_EXPECT) ); \ + } else { \ + fail( "process_macros_r returns ERROR for " _STR ); \ + } \ + } while(0) + +/*****************************************************************************/ +/* Tests */ +/*****************************************************************************/ + +void test_escaping(nagios_macros *mac) { + char *output; + + /* Nothing should be changed... options == 0 */ + RUN_MACRO_TEST( "$HOSTNAME$ '&%", "name'&% '&%", 0); + + /* Nothing should be changed... HOSTNAME doesn't accept STRIP_ILLEGAL_MACRO_CHARS */ + RUN_MACRO_TEST( "$HOSTNAME$ '&%", "name'&% '&%", STRIP_ILLEGAL_MACRO_CHARS); + + /* ' and & should be stripped from the macro, according to + * init_environment(), but not from the initial string + */ + RUN_MACRO_TEST( "$HOSTOUTPUT$ '&%", "name% '&%", STRIP_ILLEGAL_MACRO_CHARS); + + /* ESCAPE_MACRO_CHARS doesn't seem to do anything... exist always in pair + * with STRIP_ILLEGAL_MACRO_CHARS + */ + RUN_MACRO_TEST( "$HOSTOUTPUT$ '&%", "name'&% '&%", ESCAPE_MACRO_CHARS); + RUN_MACRO_TEST( "$HOSTOUTPUT$ '&%", "name% '&%", + STRIP_ILLEGAL_MACRO_CHARS | ESCAPE_MACRO_CHARS); + + /* $HOSTNAME$ should be url-encoded, but not the tailing chars */ + RUN_MACRO_TEST( "$HOSTNAME$ '&%", "name%27%26%25 '&%", + URL_ENCODE_MACRO_CHARS); + + /* The notes in the notesurl should be url-encoded, no more encoding should + * exist + */ + RUN_MACRO_TEST( "$HOSTNOTESURL$ '&%", + "notes_url'&%(notes%27%26%25%28action_url%27%26%25%29) '&%", 0); + + /* '& in the source string shouldn't be removed, because HOSTNOTESURL + * doesn't accept STRIP_ILLEGAL_MACRO_CHARS, as in the url. the macros + * included in the string should be url-encoded, and therefore not contain & + * and ' + */ + RUN_MACRO_TEST( "$HOSTNOTESURL$ '&%", + "notes_url'&%(notes%27%26%25%28action_url%27%26%25%29) '&%", + STRIP_ILLEGAL_MACRO_CHARS); + + /* This should double-encode some chars ($HOSTNOTESURL$ should contain + * url-encoded chars, and should itself be url-encoded + */ + RUN_MACRO_TEST( "$HOSTNOTESURL$ '&%", + "notes_url%27%26%25%28notes%2527%2526%2525%2528action_url%2527%2526%2525%2529%29 '&%", + URL_ENCODE_MACRO_CHARS); +} + +/*****************************************************************************/ +/* Main function */ +/*****************************************************************************/ + +int main(void) { + nagios_macros *mac; + + plan_tests(9); + + reset_variables(); + init_environment(); + init_macros(); + + mac = setup_macro_object(); + + test_escaping(mac); + + cleanup(); + free(mac); + return exit_status(); +} diff --git a/t-tap/test_nagios_config.c b/t-tap/test_nagios_config.c index 9ea9773..e066deb 100644 --- a/t-tap/test_nagios_config.c +++ b/t-tap/test_nagios_config.c @@ -4,11 +4,8 @@ * * Program: Nagios Core Testing * License: GPL - * Copyright (c) 2009 Nagios Core Development Team and Community Contributors - * Copyright (c) 1999-2009 Ethan Galstad * * First Written: 10-08-2009, based on nagios.c - * Last Modified: 10-08-2009 * * Description: * @@ -45,269 +42,16 @@ #include "../include/nebmods.h" #include "../include/nebmodules.h" #include "tap.h" - -char *config_file = NULL; -char *log_file = NULL; -char *command_file = NULL; -char *temp_file = NULL; -char *temp_path = NULL; -char *check_result_path = NULL; -char *lock_file = NULL; -char *log_archive_path = NULL; -char *p1_file = NULL; /**** EMBEDDED PERL ****/ -char *auth_file = NULL; /**** EMBEDDED PERL INTERPRETER AUTH FILE ****/ -char *nagios_user = NULL; -char *nagios_group = NULL; - -extern char *macro_x[MACRO_X_COUNT]; - -char *global_host_event_handler = NULL; -char *global_service_event_handler = NULL; -command *global_host_event_handler_ptr = NULL; -command *global_service_event_handler_ptr = NULL; - -char *ocsp_command = NULL; -char *ochp_command = NULL; -command *ocsp_command_ptr = NULL; -command *ochp_command_ptr = NULL; - -char *illegal_object_chars = NULL; -char *illegal_output_chars = NULL; - -int use_regexp_matches = FALSE; -int use_true_regexp_matching = FALSE; - -int use_syslog = DEFAULT_USE_SYSLOG; -int log_notifications = DEFAULT_NOTIFICATION_LOGGING; -int log_service_retries = DEFAULT_LOG_SERVICE_RETRIES; -int log_host_retries = DEFAULT_LOG_HOST_RETRIES; -int log_event_handlers = DEFAULT_LOG_EVENT_HANDLERS; -int log_initial_states = DEFAULT_LOG_INITIAL_STATES; -int log_external_commands = DEFAULT_LOG_EXTERNAL_COMMANDS; -int log_passive_checks = DEFAULT_LOG_PASSIVE_CHECKS; - -unsigned long logging_options = 0; -unsigned long syslog_options = 0; - -int service_check_timeout = DEFAULT_SERVICE_CHECK_TIMEOUT; -int host_check_timeout = DEFAULT_HOST_CHECK_TIMEOUT; -int event_handler_timeout = DEFAULT_EVENT_HANDLER_TIMEOUT; -int notification_timeout = DEFAULT_NOTIFICATION_TIMEOUT; -int ocsp_timeout = DEFAULT_OCSP_TIMEOUT; -int ochp_timeout = DEFAULT_OCHP_TIMEOUT; - -double sleep_time = DEFAULT_SLEEP_TIME; -int interval_length = DEFAULT_INTERVAL_LENGTH; -int service_inter_check_delay_method = ICD_SMART; -int host_inter_check_delay_method = ICD_SMART; -int service_interleave_factor_method = ILF_SMART; -int max_host_check_spread = DEFAULT_HOST_CHECK_SPREAD; -int max_service_check_spread = DEFAULT_SERVICE_CHECK_SPREAD; - -int command_check_interval = DEFAULT_COMMAND_CHECK_INTERVAL; -int check_reaper_interval = DEFAULT_CHECK_REAPER_INTERVAL; -int max_check_reaper_time = DEFAULT_MAX_REAPER_TIME; -int service_freshness_check_interval = DEFAULT_FRESHNESS_CHECK_INTERVAL; -int host_freshness_check_interval = DEFAULT_FRESHNESS_CHECK_INTERVAL; -int auto_rescheduling_interval = DEFAULT_AUTO_RESCHEDULING_INTERVAL; - -int check_external_commands = DEFAULT_CHECK_EXTERNAL_COMMANDS; -int check_orphaned_services = DEFAULT_CHECK_ORPHANED_SERVICES; -int check_orphaned_hosts = DEFAULT_CHECK_ORPHANED_HOSTS; -int check_service_freshness = DEFAULT_CHECK_SERVICE_FRESHNESS; -int check_host_freshness = DEFAULT_CHECK_HOST_FRESHNESS; -int auto_reschedule_checks = DEFAULT_AUTO_RESCHEDULE_CHECKS; -int auto_rescheduling_window = DEFAULT_AUTO_RESCHEDULING_WINDOW; - -int additional_freshness_latency = DEFAULT_ADDITIONAL_FRESHNESS_LATENCY; -int allow_empty_hostgroup_assignment = DEFAULT_ALLOW_EMPTY_HOSTGROUP_ASSIGNMENT; - -int check_for_updates = DEFAULT_CHECK_FOR_UPDATES; -int bare_update_check = DEFAULT_BARE_UPDATE_CHECK; -time_t last_update_check = 0L; -int update_available = FALSE; -char *last_program_version = NULL; -char *new_program_version = NULL; - -time_t last_command_check = 0L; -time_t last_command_status_update = 0L; -time_t last_log_rotation = 0L; - -int use_aggressive_host_checking = DEFAULT_AGGRESSIVE_HOST_CHECKING; -unsigned long cached_host_check_horizon = DEFAULT_CACHED_HOST_CHECK_HORIZON; -unsigned long cached_service_check_horizon = DEFAULT_CACHED_SERVICE_CHECK_HORIZON; -int enable_predictive_host_dependency_checks = DEFAULT_ENABLE_PREDICTIVE_HOST_DEPENDENCY_CHECKS; -int enable_predictive_service_dependency_checks = DEFAULT_ENABLE_PREDICTIVE_SERVICE_DEPENDENCY_CHECKS; - -int soft_state_dependencies = FALSE; - -int retain_state_information = FALSE; -int retention_update_interval = DEFAULT_RETENTION_UPDATE_INTERVAL; -int use_retained_program_state = TRUE; -int use_retained_scheduling_info = FALSE; -int retention_scheduling_horizon = DEFAULT_RETENTION_SCHEDULING_HORIZON; -unsigned long modified_host_process_attributes = MODATTR_NONE; -unsigned long modified_service_process_attributes = MODATTR_NONE; -unsigned long retained_host_attribute_mask = 0L; -unsigned long retained_service_attribute_mask = 0L; -unsigned long retained_contact_host_attribute_mask = 0L; -unsigned long retained_contact_service_attribute_mask = 0L; -unsigned long retained_process_host_attribute_mask = 0L; -unsigned long retained_process_service_attribute_mask = 0L; - -unsigned long next_comment_id = 0L; -unsigned long next_downtime_id = 0L; -unsigned long next_event_id = 0L; -unsigned long next_problem_id = 0L; -unsigned long next_notification_id = 0L; - -int log_rotation_method = LOG_ROTATION_NONE; - -int sigshutdown = FALSE; -int sigrestart = FALSE; -char *sigs[35] = {"EXIT", "HUP", "INT", "QUIT", "ILL", "TRAP", "ABRT", "BUS", "FPE", "KILL", "USR1", "SEGV", "USR2", "PIPE", "ALRM", "TERM", "STKFLT", "CHLD", "CONT", "STOP", "TSTP", "TTIN", "TTOU", "URG", "XCPU", "XFSZ", "VTALRM", "PROF", "WINCH", "IO", "PWR", "UNUSED", "ZERR", "DEBUG", (char *)NULL}; -int caught_signal = FALSE; -int sig_id = 0; - -int restarting = FALSE; - -int verify_config = FALSE; -int verify_object_relationships = TRUE; -int verify_circular_paths = TRUE; -int test_scheduling = FALSE; -int precache_objects = FALSE; -int use_precached_objects = FALSE; - -int daemon_mode = FALSE; -int daemon_dumps_core = TRUE; - -int max_parallel_service_checks = DEFAULT_MAX_PARALLEL_SERVICE_CHECKS; -int currently_running_service_checks = 0; -int currently_running_host_checks = 0; - -time_t program_start = 0L; -time_t event_start = 0L; -int nagios_pid = 0; -int enable_notifications = TRUE; -int execute_service_checks = TRUE; -int accept_passive_service_checks = TRUE; -int execute_host_checks = TRUE; -int accept_passive_host_checks = TRUE; -int enable_event_handlers = TRUE; -int obsess_over_services = FALSE; -int obsess_over_hosts = FALSE; -int enable_failure_prediction = TRUE; - -int translate_passive_host_checks = DEFAULT_TRANSLATE_PASSIVE_HOST_CHECKS; -int passive_host_checks_are_soft = DEFAULT_PASSIVE_HOST_CHECKS_SOFT; - -int aggregate_status_updates = TRUE; -int status_update_interval = DEFAULT_STATUS_UPDATE_INTERVAL; - -int time_change_threshold = DEFAULT_TIME_CHANGE_THRESHOLD; - -unsigned long event_broker_options = BROKER_NOTHING; - -int process_performance_data = DEFAULT_PROCESS_PERFORMANCE_DATA; - -int enable_flap_detection = DEFAULT_ENABLE_FLAP_DETECTION; - -double low_service_flap_threshold = DEFAULT_LOW_SERVICE_FLAP_THRESHOLD; -double high_service_flap_threshold = DEFAULT_HIGH_SERVICE_FLAP_THRESHOLD; -double low_host_flap_threshold = DEFAULT_LOW_HOST_FLAP_THRESHOLD; -double high_host_flap_threshold = DEFAULT_HIGH_HOST_FLAP_THRESHOLD; - -int use_large_installation_tweaks = DEFAULT_USE_LARGE_INSTALLATION_TWEAKS; -int enable_environment_macros = TRUE; -int free_child_process_memory = -1; -int child_processes_fork_twice = -1; - -int enable_embedded_perl = DEFAULT_ENABLE_EMBEDDED_PERL; -int use_embedded_perl_implicitly = DEFAULT_USE_EMBEDDED_PERL_IMPLICITLY; -int embedded_perl_initialized = FALSE; - -int date_format = DATE_FORMAT_US; -char *use_timezone = NULL; - -int command_file_fd; -FILE *command_file_fp; -int command_file_created = FALSE; -unsigned long update_uid = 0L; - - -extern contact *contact_list; -extern contactgroup *contactgroup_list; -extern hostgroup *hostgroup_list; -extern command *command_list; -extern timeperiod *timeperiod_list; -extern serviceescalation *serviceescalation_list; -extern host *host_list; -extern char *xrddefault_retention_file; - -notification *notification_list; - -check_result check_result_info; -check_result *check_result_list = NULL; -unsigned long max_check_result_file_age = DEFAULT_MAX_CHECK_RESULT_AGE; - -dbuf check_result_dbuf; - -circular_buffer external_command_buffer; -circular_buffer check_result_buffer; -pthread_t worker_threads[TOTAL_WORKER_THREADS]; -int external_command_buffer_slots = DEFAULT_EXTERNAL_COMMAND_BUFFER_SLOTS; - -check_stats check_statistics[MAX_CHECK_STATS_TYPES]; - -char *debug_file; -int debug_level = DEFAULT_DEBUG_LEVEL; -int debug_verbosity = DEFAULT_DEBUG_VERBOSITY; -unsigned long max_debug_file_size = DEFAULT_MAX_DEBUG_FILE_SIZE; - - -/* Dummy variables */ -sched_info scheduling_info; -timed_event event_list_low; -timed_event event_list_high; -timed_event *event_list_high_tail = NULL; - - -/* Dummy functions */ -void logit(int data_type, int display, const char *fmt, ...) {} -int my_sendall(int s, char *buf, int *len, int timeout) {} -int write_to_log(char *buffer, unsigned long data_type, time_t *timestamp) {} -int log_debug_info(int level, int verbosity, const char *fmt, ...) { - va_list ap; - va_start(ap, fmt); - /* vprintf( fmt, ap ); */ - va_end(ap); - } - -int neb_free_callback_list(void) {} -void broker_program_status(int type, int flags, int attr, struct timeval *timestamp) {} -int neb_deinit_modules(void) {} -void broker_program_state(int type, int flags, int attr, struct timeval *timestamp) {} -void broker_comment_data(int type, int flags, int attr, int comment_type, int entry_type, char *host_name, char *svc_description, time_t entry_time, char *author_name, char *comment_data, int persistent, int source, int expires, time_t expire_time, unsigned long comment_id, struct timeval *timestamp) {} -int neb_unload_all_modules(int flags, int reason) {} -int neb_add_module(char *filename, char *args, int should_be_loaded) {} -void broker_system_command(int type, int flags, int attr, struct timeval start_time, struct timeval end_time, double exectime, int timeout, int early_timeout, int retcode, char *cmd, char *output, struct timeval *timestamp) {} - -int schedule_new_event(int event_type, int high_priority, time_t run_time, int recurring, unsigned long event_interval, void *timing_func, int compensate_for_time_change, void *event_data, void *event_args, int event_options) {} -int my_tcp_connect(char *host_name, int port, int *sd, int timeout) {} -int my_recvall(int s, char *buf, int *len, int timeout) {} -int neb_free_module_list(void) {} -void remove_event(timed_event *event, timed_event **event_list, timed_event **event_list_tail) {} -void check_for_service_flapping(service *svc, int update, int allow_flapstart_notification) {} -int update_host_status(host *hst, int aggregated_dump) {} -int update_contact_status(contact *cntct, int aggregated_dump) {} -time_t get_next_service_notification_time(service *temp_service, time_t time_t1) {} -void broker_retention_data(int type, int flags, int attr, struct timeval *timestamp) {} -int host_notification(host *hst, int type, char *not_author, char *not_data, int options) {} -void broker_downtime_data(int type, int flags, int attr, int downtime_type, char *host_name, char *svc_description, time_t entry_time, char *author_name, char *comment_data, time_t start_time, time_t end_time, int fixed, unsigned long triggered_by, unsigned long duration, unsigned long downtime_id, struct timeval *timestamp) {} -int update_service_status(service *svc, int aggregated_dump) {} -time_t get_next_host_notification_time(host *temp_host, time_t time_t1) {} -void check_for_host_flapping(host *hst, int update, int actual_check, int allow_flapstart_notification) {} -int service_notification(service *svc, int type, char *not_author, char *not_data, int options) {} +#include "stub_events.c" +#include "stub_logging.c" +#include "stub_commands.c" +#include "stub_checks.c" +#include "stub_nebmods.c" +#include "stub_netutils.c" +#include "stub_broker.c" +#include "stub_statusdata.c" +#include "stub_flapping.c" +#include "stub_notifications.c" int main(int argc, char **argv) { @@ -342,6 +86,8 @@ int main(int argc, char **argv) { result = pre_flight_check(); ok(result == OK, "Preflight check okay"); + initialize_downtime_data(); + for(temp_hostgroup = hostgroup_list; temp_hostgroup != NULL; temp_hostgroup = temp_hostgroup->next) { c++; //printf("Hostgroup=%s\n", temp_hostgroup->group_name); @@ -361,7 +107,7 @@ int main(int argc, char **argv) { temp_host = find_host("host1"); ok(temp_host->current_state == 0, "State is assumed OK on initial load"); - xrddefault_retention_file = strdup("smallconfig/retention.dat"); +// xrddefault_retention_file = strdup("smallconfig/retention.dat"); ok(xrddefault_read_state_information() == OK, "Reading retention data"); ok(temp_host->current_state == 1, "State changed due to retention file settings"); diff --git a/t-tap/test_strtoul.c b/t-tap/test_strtoul.c deleted file mode 100644 index 2121e3a..0000000 --- a/t-tap/test_strtoul.c +++ /dev/null @@ -1,67 +0,0 @@ -/***************************************************************************** -* -* test_strtoul.c - Test strtoul function for downtime -* -* Program: Nagios Core Testing -* License: GPL -* Copyright (c) 2009 Nagios Core Development Team and Community Contributors -* Copyright (c) 1999-2009 Ethan Galstad -* -* First Written: 12-Mov-2010 -* Last Modified: 12-Nov-2010 -* -* Description: -* -* Tests system strtoul - to ensure that it works as expected as some systems -* may differ in usage -* -* License: -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License version 2 as -* published by the Free Software Foundation. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -* -*****************************************************************************/ - -#include -#include -#include "tap.h" - -char *svr_hostname = "hostname"; -char *svr_fqdn = "hostname.domain.name"; -char *svr_ip = "192.168.1.1"; -char *svr_downtime_id = "1234"; -char *end_ptr = NULL; -unsigned long downtime_id = 0L; - -int main(int argc, char **argv) { - - plan_tests(8); - - downtime_id = strtoul(svr_hostname, &end_ptr, 10); - ok(downtime_id == 0, "hostname downtime_id is 0"); - ok(strlen(end_ptr) == 8, "hostname end_ptr is 8 chars"); - - downtime_id = strtoul(svr_fqdn, &end_ptr, 10); - ok(downtime_id == 0, "fqdn downtime_id is 0"); - ok(strlen(end_ptr) == 20, "fqdn end_ptr is 20 chars"); - - downtime_id = strtoul(svr_ip, &end_ptr, 10); - ok(downtime_id == 192, "ip downtime_id is 192"); - ok(strlen(end_ptr) == 8, "ip end_ptr is 8 chars"); - - downtime_id = strtoul(svr_downtime_id, &end_ptr, 10); - ok(downtime_id == 1234, "svr_downtime_id downtime_id is 1234"); - ok(strlen(end_ptr) == 0, "svr_downtime_id end_ptr is 0 chars"); - - return exit_status(); - } diff --git a/t-tap/test_timeperiods.c b/t-tap/test_timeperiods.c index ded1771..30b7a76 100644 --- a/t-tap/test_timeperiods.c +++ b/t-tap/test_timeperiods.c @@ -4,11 +4,8 @@ * * Program: Nagios Core Testing * License: GPL - * Copyright (c) 2009 Nagios Core Development Team and Community Contributors - * Copyright (c) 1999-2009 Ethan Galstad * * First Written: 10-08-2009, based on nagios.c - * Last Modified: 10-08-2009 * * Description: * @@ -45,273 +42,47 @@ #include "../include/nebmods.h" #include "../include/nebmodules.h" #include "tap.h" - -char *config_file = NULL; -char *log_file = NULL; -char *command_file = NULL; -char *temp_file = NULL; -char *temp_path = NULL; -char *check_result_path = NULL; -char *lock_file = NULL; -char *log_archive_path = NULL; -char *p1_file = NULL; /**** EMBEDDED PERL ****/ -char *auth_file = NULL; /**** EMBEDDED PERL INTERPRETER AUTH FILE ****/ -char *nagios_user = NULL; -char *nagios_group = NULL; - -extern char *macro_x[MACRO_X_COUNT]; - -char *global_host_event_handler = NULL; -char *global_service_event_handler = NULL; -command *global_host_event_handler_ptr = NULL; -command *global_service_event_handler_ptr = NULL; - -char *ocsp_command = NULL; -char *ochp_command = NULL; -command *ocsp_command_ptr = NULL; -command *ochp_command_ptr = NULL; - -char *illegal_object_chars = NULL; -char *illegal_output_chars = NULL; - -int use_regexp_matches = FALSE; -int use_true_regexp_matching = FALSE; - -int use_syslog = DEFAULT_USE_SYSLOG; -int log_notifications = DEFAULT_NOTIFICATION_LOGGING; -int log_service_retries = DEFAULT_LOG_SERVICE_RETRIES; -int log_host_retries = DEFAULT_LOG_HOST_RETRIES; -int log_event_handlers = DEFAULT_LOG_EVENT_HANDLERS; -int log_initial_states = DEFAULT_LOG_INITIAL_STATES; -int log_external_commands = DEFAULT_LOG_EXTERNAL_COMMANDS; -int log_passive_checks = DEFAULT_LOG_PASSIVE_CHECKS; - -unsigned long logging_options = 0; -unsigned long syslog_options = 0; - -int service_check_timeout = DEFAULT_SERVICE_CHECK_TIMEOUT; -int host_check_timeout = DEFAULT_HOST_CHECK_TIMEOUT; -int event_handler_timeout = DEFAULT_EVENT_HANDLER_TIMEOUT; -int notification_timeout = DEFAULT_NOTIFICATION_TIMEOUT; -int ocsp_timeout = DEFAULT_OCSP_TIMEOUT; -int ochp_timeout = DEFAULT_OCHP_TIMEOUT; - -double sleep_time = DEFAULT_SLEEP_TIME; -int interval_length = DEFAULT_INTERVAL_LENGTH; -int service_inter_check_delay_method = ICD_SMART; -int host_inter_check_delay_method = ICD_SMART; -int service_interleave_factor_method = ILF_SMART; -int max_host_check_spread = DEFAULT_HOST_CHECK_SPREAD; -int max_service_check_spread = DEFAULT_SERVICE_CHECK_SPREAD; - -int command_check_interval = DEFAULT_COMMAND_CHECK_INTERVAL; -int check_reaper_interval = DEFAULT_CHECK_REAPER_INTERVAL; -int max_check_reaper_time = DEFAULT_MAX_REAPER_TIME; -int service_freshness_check_interval = DEFAULT_FRESHNESS_CHECK_INTERVAL; -int host_freshness_check_interval = DEFAULT_FRESHNESS_CHECK_INTERVAL; -int auto_rescheduling_interval = DEFAULT_AUTO_RESCHEDULING_INTERVAL; - -int check_external_commands = DEFAULT_CHECK_EXTERNAL_COMMANDS; -int check_orphaned_services = DEFAULT_CHECK_ORPHANED_SERVICES; -int check_orphaned_hosts = DEFAULT_CHECK_ORPHANED_HOSTS; -int check_service_freshness = DEFAULT_CHECK_SERVICE_FRESHNESS; -int check_host_freshness = DEFAULT_CHECK_HOST_FRESHNESS; -int auto_reschedule_checks = DEFAULT_AUTO_RESCHEDULE_CHECKS; -int auto_rescheduling_window = DEFAULT_AUTO_RESCHEDULING_WINDOW; - -int additional_freshness_latency = DEFAULT_ADDITIONAL_FRESHNESS_LATENCY; -int allow_empty_hostgroup_assignment = DEFAULT_ALLOW_EMPTY_HOSTGROUP_ASSIGNMENT; - -int check_for_updates = DEFAULT_CHECK_FOR_UPDATES; -int bare_update_check = DEFAULT_BARE_UPDATE_CHECK; -time_t last_update_check = 0L; -int update_available = FALSE; -char *last_program_version = NULL; -char *new_program_version = NULL; - -time_t last_command_check = 0L; -time_t last_command_status_update = 0L; -time_t last_log_rotation = 0L; - -int use_aggressive_host_checking = DEFAULT_AGGRESSIVE_HOST_CHECKING; -unsigned long cached_host_check_horizon = DEFAULT_CACHED_HOST_CHECK_HORIZON; -unsigned long cached_service_check_horizon = DEFAULT_CACHED_SERVICE_CHECK_HORIZON; -int enable_predictive_host_dependency_checks = DEFAULT_ENABLE_PREDICTIVE_HOST_DEPENDENCY_CHECKS; -int enable_predictive_service_dependency_checks = DEFAULT_ENABLE_PREDICTIVE_SERVICE_DEPENDENCY_CHECKS; - -int soft_state_dependencies = FALSE; - -int retain_state_information = FALSE; -int retention_update_interval = DEFAULT_RETENTION_UPDATE_INTERVAL; -int use_retained_program_state = TRUE; -int use_retained_scheduling_info = FALSE; -int retention_scheduling_horizon = DEFAULT_RETENTION_SCHEDULING_HORIZON; -unsigned long modified_host_process_attributes = MODATTR_NONE; -unsigned long modified_service_process_attributes = MODATTR_NONE; -unsigned long retained_host_attribute_mask = 0L; -unsigned long retained_service_attribute_mask = 0L; -unsigned long retained_contact_host_attribute_mask = 0L; -unsigned long retained_contact_service_attribute_mask = 0L; -unsigned long retained_process_host_attribute_mask = 0L; -unsigned long retained_process_service_attribute_mask = 0L; - -unsigned long next_comment_id = 0L; -unsigned long next_downtime_id = 0L; -unsigned long next_event_id = 0L; -unsigned long next_problem_id = 0L; -unsigned long next_notification_id = 0L; - -int log_rotation_method = LOG_ROTATION_NONE; - -int sigshutdown = FALSE; -int sigrestart = FALSE; -char *sigs[35] = {"EXIT", "HUP", "INT", "QUIT", "ILL", "TRAP", "ABRT", "BUS", "FPE", "KILL", "USR1", "SEGV", "USR2", "PIPE", "ALRM", "TERM", "STKFLT", "CHLD", "CONT", "STOP", "TSTP", "TTIN", "TTOU", "URG", "XCPU", "XFSZ", "VTALRM", "PROF", "WINCH", "IO", "PWR", "UNUSED", "ZERR", "DEBUG", (char *)NULL}; -int caught_signal = FALSE; -int sig_id = 0; - -int restarting = FALSE; - -int verify_config = FALSE; -int verify_object_relationships = TRUE; -int verify_circular_paths = TRUE; -int test_scheduling = FALSE; -int precache_objects = FALSE; -int use_precached_objects = FALSE; - -int daemon_mode = FALSE; -int daemon_dumps_core = TRUE; - -int max_parallel_service_checks = DEFAULT_MAX_PARALLEL_SERVICE_CHECKS; -int currently_running_service_checks = 0; -int currently_running_host_checks = 0; - -time_t program_start = 0L; -time_t event_start = 0L; -int nagios_pid = 0; -int enable_notifications = TRUE; -int execute_service_checks = TRUE; -int accept_passive_service_checks = TRUE; -int execute_host_checks = TRUE; -int accept_passive_host_checks = TRUE; -int enable_event_handlers = TRUE; -int obsess_over_services = FALSE; -int obsess_over_hosts = FALSE; -int enable_failure_prediction = TRUE; - -int translate_passive_host_checks = DEFAULT_TRANSLATE_PASSIVE_HOST_CHECKS; -int passive_host_checks_are_soft = DEFAULT_PASSIVE_HOST_CHECKS_SOFT; - -int aggregate_status_updates = TRUE; -int status_update_interval = DEFAULT_STATUS_UPDATE_INTERVAL; - -int time_change_threshold = DEFAULT_TIME_CHANGE_THRESHOLD; - -unsigned long event_broker_options = BROKER_NOTHING; - -int process_performance_data = DEFAULT_PROCESS_PERFORMANCE_DATA; - -int enable_flap_detection = DEFAULT_ENABLE_FLAP_DETECTION; - -double low_service_flap_threshold = DEFAULT_LOW_SERVICE_FLAP_THRESHOLD; -double high_service_flap_threshold = DEFAULT_HIGH_SERVICE_FLAP_THRESHOLD; -double low_host_flap_threshold = DEFAULT_LOW_HOST_FLAP_THRESHOLD; -double high_host_flap_threshold = DEFAULT_HIGH_HOST_FLAP_THRESHOLD; - -int use_large_installation_tweaks = DEFAULT_USE_LARGE_INSTALLATION_TWEAKS; -int enable_environment_macros = TRUE; -int free_child_process_memory = -1; -int child_processes_fork_twice = -1; - -int enable_embedded_perl = DEFAULT_ENABLE_EMBEDDED_PERL; -int use_embedded_perl_implicitly = DEFAULT_USE_EMBEDDED_PERL_IMPLICITLY; -int embedded_perl_initialized = FALSE; - -int date_format = DATE_FORMAT_US; -char *use_timezone = NULL; - -int command_file_fd; -FILE *command_file_fp; -int command_file_created = FALSE; -unsigned long update_uid = 0L; - - -extern contact *contact_list; -extern contactgroup *contactgroup_list; -extern hostgroup *hostgroup_list; -extern command *command_list; -extern timeperiod *timeperiod_list; -extern serviceescalation *serviceescalation_list; -extern host *host_list; - -notification *notification_list; - -check_result check_result_info; -check_result *check_result_list = NULL; -unsigned long max_check_result_file_age = DEFAULT_MAX_CHECK_RESULT_AGE; - -dbuf check_result_dbuf; - -circular_buffer external_command_buffer; -circular_buffer check_result_buffer; -pthread_t worker_threads[TOTAL_WORKER_THREADS]; -int external_command_buffer_slots = DEFAULT_EXTERNAL_COMMAND_BUFFER_SLOTS; - -check_stats check_statistics[MAX_CHECK_STATS_TYPES]; - -char *debug_file; -int debug_level = DEFAULT_DEBUG_LEVEL; -int debug_verbosity = DEFAULT_DEBUG_VERBOSITY; -unsigned long max_debug_file_size = DEFAULT_MAX_DEBUG_FILE_SIZE; - - -/* Dummy variables */ -sched_info scheduling_info; -timed_event event_list_low; -timed_event event_list_high; +#include "stub_downtime.c" /* Dummy functions */ void logit(int data_type, int display, const char *fmt, ...) {} -int my_sendall(int s, char *buf, int *len, int timeout) {} +int my_sendall(int s, char *buf, int *len, int timeout) { return 0; } void free_comment_data(void) {} -int write_to_log(char *buffer, unsigned long data_type, time_t *timestamp) {} -int log_debug_info(int level, int verbosity, const char *fmt, ...) {} +int write_to_log(char *buffer, unsigned long data_type, time_t *timestamp) { return 0; } +int log_debug_info(int level, int verbosity, const char *fmt, ...) { return 0; } -int neb_free_callback_list(void) {} +int neb_free_callback_list(void) { return 0; } void broker_program_status(int type, int flags, int attr, struct timeval *timestamp) {} -int neb_deinit_modules(void) {} +int neb_deinit_modules(void) { return 0; } void broker_program_state(int type, int flags, int attr, struct timeval *timestamp) {} void broker_comment_data(int type, int flags, int attr, int comment_type, int entry_type, char *host_name, char *svc_description, time_t entry_time, char *author_name, char *comment_data, int persistent, int source, int expires, time_t expire_time, unsigned long comment_id, struct timeval *timestamp) {} -int neb_unload_all_modules(int flags, int reason) {} -int neb_add_module(char *filename, char *args, int should_be_loaded) {} +int neb_unload_all_modules(int flags, int reason) { return 0; } +int neb_add_module(char *filename, char *args, int should_be_loaded) { return 0; } void broker_system_command(int type, int flags, int attr, struct timeval start_time, struct timeval end_time, double exectime, int timeout, int early_timeout, int retcode, char *cmd, char *output, struct timeval *timestamp) {} -int schedule_new_event(int event_type, int high_priority, time_t run_time, int recurring, unsigned long event_interval, void *timing_func, int compensate_for_time_change, void *event_data, void *event_args, int event_options) {} -int my_tcp_connect(char *host_name, int port, int *sd, int timeout) {} -int my_recvall(int s, char *buf, int *len, int timeout) {} -int neb_free_module_list(void) {} +timed_event *schedule_new_event(int event_type, int high_priority, time_t run_time, int recurring, unsigned long event_interval, void *timing_func, int compensate_for_time_change, void *event_data, void *event_args, int event_options) { return NULL; } +int my_tcp_connect(char *host_name, int port, int *sd, int timeout) { return 0; } +int my_recvall(int s, char *buf, int *len, int timeout) { return 0; } +int neb_free_module_list(void) { return 0; } +int close_command_file(void) { return 0; } +int close_log_file(void) { return 0; } +int fix_log_file_owner(uid_t uid, gid_t gid) { return 0; } +int handle_async_service_check_result(service *temp_service, check_result *queued_check_result) { return 0; } +int handle_async_host_check_result(host *temp_host, check_result *queued_check_result) { return 0; } int main(int argc, char **argv) { int result; - int error = FALSE; - char *buffer = NULL; - int display_license = FALSE; - int display_help = FALSE; int c = 0; - struct tm *tm; time_t current_time; time_t test_time; time_t saved_test_time; time_t next_valid_time = 0L; time_t chosen_valid_time = 0L; - char datestring[256]; - host *temp_host = NULL; - hostgroup *temp_hostgroup = NULL; - hostsmember *temp_member = NULL; timeperiod *temp_timeperiod = NULL; int is_valid_time = 0; int iterations = 1000; - plan_tests(6043); + plan_tests(6046); /* reset program variables */ reset_variables(); @@ -363,7 +134,7 @@ int main(int argc, char **argv) { is_valid_time = check_time_against_period(test_time, temp_timeperiod); ok(is_valid_time == OK, "Always OK for 24x7 with TZ=UTC, time_t=%lu", test_time); chosen_valid_time = 0L; - _get_next_valid_time(test_time, test_time, &chosen_valid_time, temp_timeperiod); + _get_next_valid_time(test_time, &chosen_valid_time, temp_timeperiod); ok(test_time == chosen_valid_time, "get_next_valid_time always returns same time"); test_time += 1800; c++; @@ -376,7 +147,7 @@ int main(int argc, char **argv) { while(c < iterations) { is_valid_time = check_time_against_period(test_time, temp_timeperiod); ok(is_valid_time == OK, "Always OK for 24x7 with TZ=Europe/London, time_t=%lu", test_time); - _get_next_valid_time(test_time, test_time, &chosen_valid_time, temp_timeperiod); + _get_next_valid_time(test_time, &chosen_valid_time, temp_timeperiod); ok(test_time == chosen_valid_time, "get_next_valid_time always returns same time, time_t=%lu", test_time); test_time += 1800; c++; @@ -394,7 +165,7 @@ int main(int argc, char **argv) { while(c < iterations) { is_valid_time = check_time_against_period(test_time, temp_timeperiod); ok(is_valid_time == OK, "Always OK for 24x7 with TZ=America/New_York, time_t=%lu", test_time); - _get_next_valid_time(test_time, test_time, &chosen_valid_time, temp_timeperiod); + _get_next_valid_time(test_time, &chosen_valid_time, temp_timeperiod); ok(test_time == chosen_valid_time, "get_next_valid_time always returns same time, time_t=%lu", test_time); test_time += 1800; c++; @@ -411,58 +182,48 @@ int main(int argc, char **argv) { /* Timeperiod exclude tests, from Jean Gabes */ temp_timeperiod = find_timeperiod("Test_exclude"); - ok(temp_timeperiod != NULL, "ME: Testing Exclude timeperiod"); - test_time = 1278939600; - /* printf("Testing at time %s", ctime(&test_time)); */ + ok(temp_timeperiod != NULL, "Testing Exclude timeperiod"); + test_time = 1278939600; //mon jul 12 15:00:00 is_valid_time = check_time_against_period(test_time, temp_timeperiod); - ok(is_valid_time == ERROR, "ME: 12 Jul 2010 15:00:00 - false"); + ok(is_valid_time == ERROR, "12 Jul 2010 15:00:00 should not be valid"); - _get_next_valid_time(test_time, test_time, &chosen_valid_time, temp_timeperiod); - /* printf("JEAN: Got chosent time at %s", ctime(&chosen_valid_time)); */ - todo_start("Bug in exclude"); - ok(chosen_valid_time == 1288103400, "ME: Next valid time=Tue Oct 26 16:30:00 2010"); - todo_end(); + _get_next_valid_time(test_time, &chosen_valid_time, temp_timeperiod); + ok(chosen_valid_time == 1288103400, "Next valid time should be Tue Oct 26 16:30:00 2010, was %s", ctime(&chosen_valid_time)); temp_timeperiod = find_timeperiod("Test_exclude2"); - ok(temp_timeperiod != NULL, "ME: Testing Exclude timeperiod 2"); - test_time = 1278939600; - /* printf("Testing at time %s", ctime(&test_time)); */ + ok(temp_timeperiod != NULL, "Testing Exclude timeperiod 2"); + test_time = 1278939600; //mon jul 12 15:00:00 is_valid_time = check_time_against_period(test_time, temp_timeperiod); - ok(is_valid_time == ERROR, "ME: 12 Jul 2010 15:00:00 - false"); - _get_next_valid_time(test_time, test_time, &chosen_valid_time, temp_timeperiod); - /* printf("JEAN: Got chosent time at %s", ctime(&chosen_valid_time)); */ - todo_start("Bug in exclude 2"); - ok(chosen_valid_time == 1279058340, "ME: Next valid time=Tue Jul 13 23:59:00 2010"); - todo_end(); + ok(is_valid_time == ERROR, "12 Jul 2010 15:00:00 should not be valid"); + _get_next_valid_time(test_time, &chosen_valid_time, temp_timeperiod); + ok(chosen_valid_time == 1279058340, "Next valid time should be Tue Jul 13 23:59:00 2010, was %s", ctime(&chosen_valid_time)); temp_timeperiod = find_timeperiod("Test_exclude3"); - ok(temp_timeperiod != NULL, "ME: Testing Exclude timeperiod 3"); - test_time = 1278939600; - /* printf("Testing at time %s", ctime(&test_time)); */ + ok(temp_timeperiod != NULL, "Testing Exclude timeperiod 3"); + test_time = 1278939600; //mon jul 12 15:00:00 is_valid_time = check_time_against_period(test_time, temp_timeperiod); - ok(is_valid_time == ERROR, "ME: 12 Jul 2010 15:00:00 - false"); - _get_next_valid_time(test_time, test_time, &chosen_valid_time, temp_timeperiod); - /* printf("JEAN: Got chosent time at %s", ctime(&chosen_valid_time)); */ - todo_start("Bug in exclude 3"); - ok(chosen_valid_time == 1284474600, "ME: Next valid time=Tue Sep 14 16:30:00 2010"); - todo_end(); + ok(is_valid_time == ERROR, "12 Jul 2010 15:00:00 should not be valid"); + _get_next_valid_time(test_time, &chosen_valid_time, temp_timeperiod); + ok(chosen_valid_time == 1284474600, "Next valid time should be Tue Sep 14 16:30:00 2010, was %s", ctime(&chosen_valid_time)); temp_timeperiod = find_timeperiod("Test_exclude4"); - ok(temp_timeperiod != NULL, "ME: Testing Exclude timeperiod 4"); - test_time = 1278939600; - /* printf("Testing at time %s", ctime(&test_time)); */ + ok(temp_timeperiod != NULL, "Testing Exclude timeperiod 4"); + test_time = 1278939600; //mon jul 12 15:00:00 is_valid_time = check_time_against_period(test_time, temp_timeperiod); - ok(is_valid_time == ERROR, "ME: 12 Jul 2010 15:00:00 - false"); - _get_next_valid_time(test_time, test_time, &chosen_valid_time, temp_timeperiod); - /* printf("JEAN: Got chosent time at %s", ctime(&chosen_valid_time)); */ - todo_start("Bug in exclude 3"); - ok(chosen_valid_time == 1283265000, "ME: Next valid time=Tue Aug 31 16:30:00 2010"); - todo_end(); - + ok(is_valid_time == ERROR, "12 Jul 2010 15:00:00 should not be valid"); + _get_next_valid_time(test_time, &chosen_valid_time, temp_timeperiod); + ok(chosen_valid_time == 1283265000, "Next valid time should be Tue Aug 31 16:30:00 2010, was %s", ctime(&chosen_valid_time)); + temp_timeperiod = find_timeperiod("exclude_always"); + ok(temp_timeperiod != NULL, "Testing exclude always"); + test_time = 1278939600; //mon jul 12 15:00:00 + is_valid_time = check_time_against_period(test_time, temp_timeperiod); + ok(is_valid_time == ERROR, "12 Jul 2010 15:00:00 should not be valid"); + _get_next_valid_time(test_time, &chosen_valid_time, temp_timeperiod); + ok(chosen_valid_time == test_time, "There should be no next valid time, was %s", ctime(&chosen_valid_time)); /* Back to New york */ @@ -479,64 +240,62 @@ int main(int argc, char **argv) { test_time = 1256421000; is_valid_time = check_time_against_period(test_time, temp_timeperiod); ok(is_valid_time == ERROR, "Sat Oct 24 22:50:00 2009 - false"); - _get_next_valid_time(test_time, test_time, &chosen_valid_time, temp_timeperiod); + _get_next_valid_time(test_time, &chosen_valid_time, temp_timeperiod); ok(chosen_valid_time == 1256425200, "Next valid time=Sun Oct 25 00:00:00 2009"); test_time = 1256421661; is_valid_time = check_time_against_period(test_time, temp_timeperiod); ok(is_valid_time == ERROR, "Sat Oct 24 23:01:01 2009 - false"); - _get_next_valid_time(test_time, test_time, &chosen_valid_time, temp_timeperiod); + _get_next_valid_time(test_time, &chosen_valid_time, temp_timeperiod); ok(chosen_valid_time == 1256425200, "Next valid time=Sun Oct 25 00:00:00 2009"); test_time = 1256425400; is_valid_time = check_time_against_period(test_time, temp_timeperiod); ok(is_valid_time == OK, "Sun Oct 25 00:03:20 2009 - true"); - _get_next_valid_time(test_time, test_time, &chosen_valid_time, temp_timeperiod); + _get_next_valid_time(test_time, &chosen_valid_time, temp_timeperiod); ok(chosen_valid_time == test_time, "Next valid time=Sun Oct 25 00:03:20 2009"); test_time = 1256429700; is_valid_time = check_time_against_period(test_time, temp_timeperiod); ok(is_valid_time == OK, "Sun Oct 25 01:15:00 2009 - true"); - _get_next_valid_time(test_time, test_time, &chosen_valid_time, temp_timeperiod); + _get_next_valid_time(test_time, &chosen_valid_time, temp_timeperiod); ok(chosen_valid_time == test_time, "Next valid time=Sun Oct 25 01:15:00 2009"); test_time = 1256430400; is_valid_time = check_time_against_period(test_time, temp_timeperiod); ok(is_valid_time == ERROR, "Sun Oct 25 01:26:40 2009 - false"); - _get_next_valid_time(test_time, test_time, &chosen_valid_time, temp_timeperiod); - todo_start("Is a bug in get_next_valid_time for a time that falls in the DST change hour period"); - ok(chosen_valid_time == 1256440500, "Next valid time=Sun Oct 25 03:15:00 2009") || printf("chosen_valid_time=%lu\n", chosen_valid_time); - todo_end(); + _get_next_valid_time(test_time, &chosen_valid_time, temp_timeperiod); + ok(chosen_valid_time == 1256440500, "Next valid time should be Sun Oct 25 03:15:00 2009, was %s", ctime(&chosen_valid_time)); test_time = 1256440500; is_valid_time = check_time_against_period(test_time, temp_timeperiod); ok(is_valid_time == OK, "Sun Oct 25 03:15:00 2009 - true"); - _get_next_valid_time(test_time, test_time, &chosen_valid_time, temp_timeperiod); + _get_next_valid_time(test_time, &chosen_valid_time, temp_timeperiod); ok(chosen_valid_time == test_time, "Next valid time=Sun Oct 25 03:15:00 2009"); test_time = 1256500000; is_valid_time = check_time_against_period(test_time, temp_timeperiod); ok(is_valid_time == OK, "Sun Oct 25 19:46:40 2009 - true"); - _get_next_valid_time(test_time, test_time, &chosen_valid_time, temp_timeperiod); + _get_next_valid_time(test_time, &chosen_valid_time, temp_timeperiod); ok(chosen_valid_time == 1256500000, "Next valid time=Sun Oct 25 19:46:40 2009"); test_time = 1256508000; is_valid_time = check_time_against_period(test_time, temp_timeperiod); ok(is_valid_time == OK, "Sun Oct 25 22:00:00 2009 - true"); - _get_next_valid_time(test_time, test_time, &chosen_valid_time, temp_timeperiod); + _get_next_valid_time(test_time, &chosen_valid_time, temp_timeperiod); ok(chosen_valid_time == 1256508000, "Next valid time=Sun Oct 25 22:00:00 2009"); test_time = 1256508001; is_valid_time = check_time_against_period(test_time, temp_timeperiod); ok(is_valid_time == ERROR, "Sun Oct 25 22:00:01 2009 - false"); - _get_next_valid_time(test_time, test_time, &chosen_valid_time, temp_timeperiod); + _get_next_valid_time(test_time, &chosen_valid_time, temp_timeperiod); ok(chosen_valid_time == 1257033600, "Next valid time=Sun Nov 1 00:00:00 2009"); test_time = 1256513000; is_valid_time = check_time_against_period(test_time, temp_timeperiod); ok(is_valid_time == ERROR, "Sun Oct 25 23:23:20 2009 - false"); - _get_next_valid_time(test_time, test_time, &chosen_valid_time, temp_timeperiod); + _get_next_valid_time(test_time, &chosen_valid_time, temp_timeperiod); ok(chosen_valid_time == 1257033600, "Next valid time=Sun Nov 1 00:00:00 2009"); @@ -550,7 +309,7 @@ int main(int argc, char **argv) { test_time = 1268109420; is_valid_time = check_time_against_period(test_time, temp_timeperiod); ok(is_valid_time == ERROR, "Mon Mar 8 23:37:00 2010 - false"); - _get_next_valid_time(test_time, test_time, &chosen_valid_time, temp_timeperiod); + _get_next_valid_time(test_time, &chosen_valid_time, temp_timeperiod); ok(chosen_valid_time == 1268115300, "Next valid time=Tue Mar 9 01:15:00 2010"); @@ -563,5 +322,3 @@ int main(int argc, char **argv) { return exit_status(); } - - diff --git a/t-tap/test_xsddefault.c b/t-tap/test_xsddefault.c index c2d3204..6a11149 100644 --- a/t-tap/test_xsddefault.c +++ b/t-tap/test_xsddefault.c @@ -4,8 +4,6 @@ * * Program: Nagios Core Testing * License: GPL - * Copyright (c) 2009-2010 Nagios Core Development Team and Community Contributors - * Copyright (c) 1999-2009 Ethan Galstad * * First Written: 06-01-2010, based on test_nagios_config.c * @@ -43,7 +41,7 @@ #include "../include/skiplist.h" #include "tap.h" -extern comment *comment_list; +extern nagios_comment *comment_list; extern scheduled_downtime *scheduled_downtime_list; int main(int argc, char **argv) { @@ -51,7 +49,7 @@ int main(int argc, char **argv) { int c; int last_id; time_t last_time; - comment *temp_comment; + nagios_comment *temp_comment; scheduled_downtime *temp_downtime; plan_tests(7); diff --git a/t-tap/var/nagios.log.diff.expected b/t-tap/var/nagios.log.diff.expected new file mode 100644 index 0000000..84d854d --- /dev/null +++ b/t-tap/var/nagios.log.diff.expected @@ -0,0 +1,3 @@ +0a1,2 +> [1242949698] LOG ROTATION: HOURLY +> [1242949698] LOG VERSION: 2.0 diff --git a/t/610cgistatus.t b/t/610cgistatus.t index e80b350..6408bce 100644 --- a/t/610cgistatus.t +++ b/t/610cgistatus.t @@ -15,7 +15,7 @@ my $cgi = "$cgi_dir/status.cgi"; my $output; -plan tests => 8; +plan tests => 9; my $numhosts; @@ -29,11 +29,11 @@ ok( $numhosts > 1, "Got $numhosts hosts, which is more than 1"); $output = `NAGIOS_CGI_CONFIG=etc/cgi.cfg REMOTE_USER=nagiosadmin REQUEST_METHOD=GET QUERY_STRING=host=host1 $cgi`; like( $output, '/status.cgi\?host=host1&sorttype=1&sortoption=1/', "Host value should be set to specific host if passed in" ); -like( $output, '/1 Matching Service Entries Displayed/', "Found the one host" ); +like( $output, '/1 Matching Services/', "Found the one host" ); $output = `NAGIOS_CGI_CONFIG=etc/cgi.cfg REMOTE_USER=nagiosadmin REQUEST_METHOD=GET QUERY_STRING=host= $cgi`; like( $output, '/status.cgi\?host=&sorttype=1&sortoption=1/', "Host value kept as blank if set to blank" ); -like( $output, '/0 Matching Service Entries Displayed/', "Got no hosts because looking for a blank name" ); +like( $output, '/0 Matching Services/', "Got no hosts because looking for a blank name" ); $output = `NAGIOS_CGI_CONFIG=etc/cgi.cfg REMOTE_USER=nagiosadmin REQUEST_METHOD=GET $cgi`; like( $output, '/status.cgi\?host=all&sorttype=1&sortoption=1/', "Host value should be set to all if nothing set initially" ); @@ -41,3 +41,6 @@ like( $output, '/status.cgi\?host=all&sorttype=1&sortoption=1/', "Host value sho $_ = grep /title=/, split("\n", $output); is( $_, $numhosts, "Same number of hosts" ); +$output = `NAGIOS_CGI_CONFIG=etc/cgi.cfg REMOTE_USER=second REQUEST_METHOD=GET QUERY_STRING=host=all $cgi`; +like( $output, '/1 Matching Services/', "Got 1 service, as permission only allows one host"); + diff --git a/t/615cgierror.t b/t/615cgierror.t index 97ce4a6..b7340c1 100644 --- a/t/615cgierror.t +++ b/t/615cgierror.t @@ -16,8 +16,6 @@ opendir(DIR, $cgi_dir) or die "Cannot opendir $cgi_dir: $!"; my %cgis = map { ( $_ => 1 ) } grep /\.cgi$/, readdir DIR; closedir DIR; -plan tests => scalar keys %cgis; - # Remove these two because the output is different my @todos = qw(statuswml.cgi statuswrl.cgi); @@ -25,13 +23,14 @@ TODO: { local $TODO = "Output is different for these CGIs"; foreach my $cgi (@todos) { delete $cgis{$cgi}; - my $output = `NAGIOS_CGI_CONFIG=etc/cgi.nonexistant REQUEST_METHOD=GET $cgi_dir/$cgi`; - like( $output, "/Error: Could not open CGI config file 'etc/cgi.nonexistant' for reading/", "Found error for $cgi" ); +# my $output = `NAGIOS_CGI_CONFIG=etc/cgi.nonexistent REQUEST_METHOD=GET $cgi_dir/$cgi`; +# like( $output, "/Error: Could not open CGI config file 'etc/cgi.nonexistent' for reading/", "Found error for $cgi" ); } } - +plan tests => scalar keys %cgis; + foreach my $cgi (sort keys %cgis) { - my $output = `NAGIOS_CGI_CONFIG=etc/cgi.nonexistant REQUEST_METHOD=GET $cgi_dir/$cgi`; - like( $output, "/Error: Could not open CGI config file 'etc/cgi.nonexistant' for reading/", "Found error for $cgi" ); + my $output = `NAGIOS_CGI_CONFIG=etc/cgi.nonexistent REQUEST_METHOD=GET $cgi_dir/$cgi`; + like( $output, "/Error: Could not open CGI config file 'etc/cgi.nonexistent' for reading/", "Found error for $cgi" ); } diff --git a/t/618cgisecurity.t b/t/618cgisecurity.t index 1f7d0cd..dd1469e 100644 --- a/t/618cgisecurity.t +++ b/t/618cgisecurity.t @@ -16,7 +16,9 @@ plan 'no_plan'; my $output = `NAGIOS_CGI_CONFIG=etc/cgi.cfg REQUEST_METHOD=GET QUERY_STRING="layer=' style=xss:expression(alert('XSS')) '" $cgi_dir/statusmap.cgi`; unlike( $output, qr/' style=xss:expression\(alert\('XSS'\)\) '/, "XSS injection not passed straight through" ); -like( $output, qr/' style=xss:expression(alert('XSS')) '/, "Expected escaping of quotes" ) || diag $output; + +# Is this correct? Nothing weird happens anyway, so let's assume so +like( $output, qr/' style=xss:expression(alert('XSS')) '/, "Expected escaping of quotes" ) || diag $output; $output = `REMOTE_USER=nagiosadmin NAGIOS_CGI_CONFIG=etc/cgi.cfg REQUEST_METHOD=GET QUERY_STRING="type=command&expand=" $cgi_dir/config.cgi`; diff --git a/t/620history.t b/t/620history.t deleted file mode 100644 index 39b96b7..0000000 --- a/t/620history.t +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/perl - -use warnings; -use strict; -use FindBin qw($Bin); - -use Test::More; - -eval "use Test::HTML::Lint"; -if ($@) { - plan skip_all => "Need Test::HTML::Lint"; -} - -eval "use Test::WWW::Mechanize::CGI"; -if ($@) { - plan skip_all => "Need Test::WWW::Mechanize::CGI"; -} - -my $lint; -eval '$lint = HTML::Lint->new( only_types => HTML::Lint::Error::STRUCTURE )'; - -plan tests => 3; - -chdir $Bin or die "Cannot chdir"; - -my $topdir = "$Bin/.."; -my $cgi_dir = "$topdir/cgi"; - -my $mech = Test::WWW::Mechanize::CGI->new; - -$mech->env( NAGIOS_CGI_CONFIG => "etc/cgi.cfg" ); -$mech->cgi_application("$cgi_dir/history.cgi"); - -$mech->get_ok("http://localhost/"); - -$mech->title_is("Nagios History"); - -html_ok( $lint, $mech->content, "HTML correct" ); - diff --git a/t/621extinfo.t b/t/621extinfo.t deleted file mode 100644 index 516c47c..0000000 --- a/t/621extinfo.t +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/perl - -use warnings; -use strict; -use FindBin qw($Bin); - -use Test::More; - -eval "use Test::HTML::Lint"; -if ($@) { - plan skip_all => "Need Test::HTML::Lint"; -} - -eval "use Test::WWW::Mechanize::CGI"; -if ($@) { - plan skip_all => "Need Test::WWW::Mechanize::CGI"; -} - -my $lint; -eval '$lint = HTML::Lint->new( only_types => HTML::Lint::Error::STRUCTURE )'; - -plan tests => 3; - -chdir $Bin or die "Cannot chdir"; - -my $topdir = "$Bin/.."; -my $cgi_dir = "$topdir/cgi"; - -my $mech = Test::WWW::Mechanize::CGI->new; - -$mech->env( REMOTE_USER => "nagiosadmin" ); -$mech->env( NAGIOS_CGI_CONFIG => "etc/cgi.cfg" ); -$mech->cgi_application("$cgi_dir/extinfo.cgi"); - -$mech->get_ok("http://localhost/"); - -$mech->title_is("Extended Information"); - -html_ok( $lint, $mech->content, "HTML correct" ); - diff --git a/t/623cmd-local.t b/t/623cmd-local.t index 8d0b76f..c0fcd25 100644 --- a/t/623cmd-local.t +++ b/t/623cmd-local.t @@ -568,21 +568,6 @@ like( $output, "/
    Scheduled Downtime ID: